Merge "Change TestActivity to not be immersive" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 1fb5f34..20f879c 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -428,7 +428,10 @@
aconfig_declarations {
name: "com.android.media.flags.bettertogether-aconfig",
package: "com.android.media.flags",
- srcs: ["media/java/android/media/flags/media_better_together.aconfig"],
+ srcs: [
+ "media/java/android/media/flags/media_better_together.aconfig",
+ "media/java/android/media/flags/fade_manager_configuration.aconfig",
+ ],
}
java_aconfig_library {
diff --git a/Android.bp b/Android.bp
index c1fb41f..fa7c97d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,7 +95,7 @@
":platform-compat-native-aidl",
// AIDL sources from external directories
- ":android.hardware.biometrics.common-V3-java-source",
+ ":android.hardware.biometrics.common-V4-java-source",
":android.hardware.biometrics.fingerprint-V3-java-source",
":android.hardware.gnss-V2-java-source",
":android.hardware.graphics.common-V3-java-source",
@@ -379,6 +379,7 @@
// system propagates "required" properly.
"gps_debug.conf",
"protolog.conf.json.gz",
+ "framework-res",
// any install dependencies should go into framework-minus-apex-install-dependencies
// rather than here to avoid bloating incremental build time
],
diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig
index f5e33a80..e73b434 100644
--- a/apex/jobscheduler/framework/aconfig/job.aconfig
+++ b/apex/jobscheduler/framework/aconfig/job.aconfig
@@ -1,6 +1,13 @@
package: "android.app.job"
flag {
+ name: "enforce_minimum_time_windows"
+ namespace: "backstage_power"
+ description: "Enforce a minimum time window for job latencies & deadlines"
+ bug: "311402873"
+}
+
+flag {
name: "job_debug_info_apis"
namespace: "backstage_power"
description: "Add APIs to let apps attach debug information to jobs"
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 742ed5f..4bc7313 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -23,6 +23,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.util.TimeUtils.formatDuration;
import android.annotation.BytesLong;
@@ -36,6 +37,7 @@
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Overridable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ComponentName;
@@ -48,7 +50,9 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Log;
@@ -113,6 +117,16 @@
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public static final long REJECT_NEGATIVE_NETWORK_ESTIMATES = 253665015L;
+ /**
+ * Enforce a minimum time window between job latencies and deadlines.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Overridable // Aid in testing
+ public static final long ENFORCE_MINIMUM_TIME_WINDOWS = 311402873L;
+
/** @hide */
@IntDef(prefix = { "NETWORK_TYPE_" }, value = {
NETWORK_TYPE_NONE,
@@ -1866,10 +1880,40 @@
* Set deadline which is the maximum scheduling latency. The job will be run by this
* deadline even if other requirements (including a delay set through
* {@link #setMinimumLatency(long)}) are not met.
+ * {@link JobParameters#isOverrideDeadlineExpired()} will return {@code true} if the job's
+ * deadline has passed.
+ *
* <p>
* Because it doesn't make sense setting this property on a periodic job, doing so will
* throw an {@link java.lang.IllegalArgumentException} when
* {@link android.app.job.JobInfo.Builder#build()} is called.
+ *
+ * <p class="note">
+ * Since a job will run once the deadline has passed regardless of the status of other
+ * constraints, setting a deadline of 0 with other constraints makes those constraints
+ * meaningless when it comes to execution decisions. Avoid doing this.
+ * </p>
+ *
+ * <p>
+ * Short deadlines hinder the system's ability to optimize scheduling behavior and may
+ * result in running jobs at inopportune times. Therefore, starting in Android version
+ * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}, minimum time windows will be
+ * enforced to help make it easier to better optimize job execution. Time windows are
+ * defined as the time between a job's {@link #setMinimumLatency(long) minimum latency}
+ * and its deadline. If the minimum latency is not set, it is assumed to be 0.
+ * The following minimums will be enforced:
+ * <ul>
+ * <li>
+ * Jobs with {@link #PRIORITY_DEFAULT} or higher priorities have a minimum time
+ * window of one hour.
+ * </li>
+ * <li>Jobs with {@link #PRIORITY_LOW} have a minimum time window of 6 hours.</li>
+ * <li>Jobs with {@link #PRIORITY_MIN} have a minimum time window of 12 hours.</li>
+ * </ul>
+ *
+ * Work that must happen immediately should use {@link #setExpedited(boolean)} or
+ * {@link #setUserInitiated(boolean)} in the appropriate manner.
+ *
* @see JobInfo#getMaxExecutionDelayMillis()
*/
public Builder setOverrideDeadline(long maxExecutionDelayMillis) {
@@ -2143,12 +2187,14 @@
*/
public JobInfo build() {
return build(Compatibility.isChangeEnabled(DISALLOW_DEADLINES_FOR_PREFETCH_JOBS),
- Compatibility.isChangeEnabled(REJECT_NEGATIVE_NETWORK_ESTIMATES));
+ Compatibility.isChangeEnabled(REJECT_NEGATIVE_NETWORK_ESTIMATES),
+ Compatibility.isChangeEnabled(ENFORCE_MINIMUM_TIME_WINDOWS));
}
/** @hide */
public JobInfo build(boolean disallowPrefetchDeadlines,
- boolean rejectNegativeNetworkEstimates) {
+ boolean rejectNegativeNetworkEstimates,
+ boolean enforceMinimumTimeWindows) {
// This check doesn't need to be inside enforceValidity. It's an unnecessary legacy
// check that would ideally be phased out instead.
if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
@@ -2157,7 +2203,8 @@
" setRequiresDeviceIdle is an error.");
}
JobInfo jobInfo = new JobInfo(this);
- jobInfo.enforceValidity(disallowPrefetchDeadlines, rejectNegativeNetworkEstimates);
+ jobInfo.enforceValidity(disallowPrefetchDeadlines, rejectNegativeNetworkEstimates,
+ enforceMinimumTimeWindows);
return jobInfo;
}
@@ -2176,7 +2223,8 @@
* @hide
*/
public final void enforceValidity(boolean disallowPrefetchDeadlines,
- boolean rejectNegativeNetworkEstimates) {
+ boolean rejectNegativeNetworkEstimates,
+ boolean enforceMinimumTimeWindows) {
// Check that network estimates require network type and are reasonable values.
if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0)
&& networkRequest == null) {
@@ -2291,6 +2339,39 @@
throw new IllegalArgumentException("Invalid priority level provided: " + mPriority);
}
+ if (enforceMinimumTimeWindows
+ && Flags.enforceMinimumTimeWindows()
+ // TODO(312197030): remove exemption for the system
+ && !UserHandle.isCore(Process.myUid())
+ && hasLateConstraint && !isPeriodic) {
+ final long windowStart = hasEarlyConstraint ? minLatencyMillis : 0;
+ if (mPriority >= PRIORITY_DEFAULT) {
+ if (maxExecutionDelayMillis - windowStart < HOUR_IN_MILLIS) {
+ throw new IllegalArgumentException(
+ getPriorityString(mPriority)
+ + " cannot have a time window less than 1 hour."
+ + " Delay=" + windowStart
+ + ", deadline=" + maxExecutionDelayMillis);
+ }
+ } else if (mPriority >= PRIORITY_LOW) {
+ if (maxExecutionDelayMillis - windowStart < 6 * HOUR_IN_MILLIS) {
+ throw new IllegalArgumentException(
+ getPriorityString(mPriority)
+ + " cannot have a time window less than 6 hours."
+ + " Delay=" + windowStart
+ + ", deadline=" + maxExecutionDelayMillis);
+ }
+ } else {
+ if (maxExecutionDelayMillis - windowStart < 12 * HOUR_IN_MILLIS) {
+ throw new IllegalArgumentException(
+ getPriorityString(mPriority)
+ + " cannot have a time window less than 12 hours."
+ + " Delay=" + windowStart
+ + ", deadline=" + maxExecutionDelayMillis);
+ }
+ }
+ }
+
if (isExpedited) {
if (hasEarlyConstraint) {
throw new IllegalArgumentException("An expedited job cannot have a time delay");
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 2d972d0..f97100b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -268,6 +268,7 @@
/** Master list of jobs. */
final JobStore mJobs;
private final CountDownLatch mJobStoreLoadedLatch;
+ private final CountDownLatch mStartControllerTrackingLatch;
/** Tracking the standby bucket state of each app */
final StandbyTracker mStandbyTracker;
/** Tracking amount of time each package runs for. */
@@ -2521,6 +2522,7 @@
mBatteryStateTracker.startTracking();
// Create the controllers.
+ mStartControllerTrackingLatch = new CountDownLatch(1);
mControllers = new ArrayList<StateController>();
mPrefetchController = new PrefetchController(this);
mControllers.add(mPrefetchController);
@@ -2552,6 +2554,8 @@
new TareController(this, backgroundJobsController, mConnectivityController);
mControllers.add(mTareController);
+ startControllerTrackingAsync();
+
mRestrictiveControllers = new ArrayList<>();
mRestrictiveControllers.add(batteryController);
mRestrictiveControllers.add(mConnectivityController);
@@ -2623,16 +2627,22 @@
public void onBootPhase(int phase) {
if (PHASE_LOCK_SETTINGS_READY == phase) {
// This is the last phase before PHASE_SYSTEM_SERVICES_READY. We need to ensure that
+ // controllers have started tracking and that
// persisted jobs are loaded before we can proceed to PHASE_SYSTEM_SERVICES_READY.
try {
+ mStartControllerTrackingLatch.await();
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Couldn't wait on controller tracking start latch");
+ }
+ try {
mJobStoreLoadedLatch.await();
} catch (InterruptedException e) {
Slog.e(TAG, "Couldn't wait on job store loading latch");
}
} else if (PHASE_SYSTEM_SERVICES_READY == phase) {
mConstantsObserver.start();
- for (StateController controller : mControllers) {
- controller.onSystemServicesReady();
+ for (int i = mControllers.size() - 1; i >= 0; --i) {
+ mControllers.get(i).onSystemServicesReady();
}
mAppStateTracker = (AppStateTrackerImpl) Objects.requireNonNull(
@@ -2695,6 +2705,17 @@
}
}
+ private void startControllerTrackingAsync() {
+ mHandler.post(() -> {
+ synchronized (mLock) {
+ for (int i = mControllers.size() - 1; i >= 0; --i) {
+ mControllers.get(i).startTrackingLocked();
+ }
+ }
+ mStartControllerTrackingLatch.countDown();
+ });
+ }
+
/**
* Called when we have a job status object that we need to insert in our
* {@link com.android.server.job.JobStore}, and make sure all the relevant controllers know
@@ -4367,7 +4388,7 @@
Slog.w(TAG, "Uid " + uid + " set bias on its job");
return new JobInfo.Builder(job)
.setBias(JobInfo.BIAS_DEFAULT)
- .build(false, false);
+ .build(false, false, false);
}
}
@@ -4389,7 +4410,9 @@
job.enforceValidity(
CompatChanges.isChangeEnabled(
JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid),
- rejectNegativeNetworkEstimates);
+ rejectNegativeNetworkEstimates,
+ CompatChanges.isChangeEnabled(
+ JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS, callingUid));
if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
@@ -5176,6 +5199,12 @@
return mTareController;
}
+ @VisibleForTesting
+ protected void waitOnAsyncLoadingForTesting() throws Exception {
+ mStartControllerTrackingLatch.await();
+ // Ignore the job store loading for testing.
+ }
+
// Shell command infrastructure
int getJobState(PrintWriter pw, String pkgName, int userId, @Nullable String namespace,
int jobId) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index afcbdda..53b14d6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -1495,7 +1495,7 @@
// return value), the deadline is dropped. Periodic jobs require all constraints
// to be met, so there's no issue with their deadlines.
// The same logic applies for other target SDK-based validation checks.
- builtJob = jobBuilder.build(false, false);
+ builtJob = jobBuilder.build(false, false, false);
} catch (Exception e) {
Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize(), e);
return null;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 25b3421..cd3ba6b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -73,6 +73,10 @@
LocalServices.getService(ActivityManagerInternal.class));
mAppStateTracker = (AppStateTrackerImpl) Objects.requireNonNull(
LocalServices.getService(AppStateTracker.class));
+ }
+
+ @Override
+ public void startTrackingLocked() {
mAppStateTracker.addListener(mForceAppStandbyListener);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 5246f2b..ddbc2ec 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -78,11 +78,15 @@
FlexibilityController flexibilityController) {
super(service);
mPowerTracker = new PowerTracker();
- mPowerTracker.startTracking();
mFlexibilityController = flexibilityController;
}
@Override
+ public void startTrackingLocked() {
+ mPowerTracker.startTracking();
+ }
+
+ @Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasPowerConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
index b029e00..9d4cba1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
@@ -106,7 +106,10 @@
public ComponentController(JobSchedulerService service) {
super(service);
+ }
+ @Override
+ public void startTrackingLocked() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index a900d16..13a474cc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -201,6 +201,10 @@
mPercentToDropConstraints =
mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS;
mPrefetchController = prefetchController;
+ }
+
+ @Override
+ public void startTrackingLocked() {
if (mFlexibilityEnabled) {
mPrefetchController.registerPrefetchChangedListener(mPrefetchChangedListener);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index 47d3fd5..adee322 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -19,7 +19,6 @@
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.NonNull;
-import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.provider.DeviceConfig;
@@ -56,7 +55,7 @@
public IdleController(JobSchedulerService service,
FlexibilityController flexibilityController) {
super(service);
- initIdleStateTracking(mContext);
+ initIdleStateTracker();
mFlexibilityController = flexibilityController;
}
@@ -127,7 +126,7 @@
* Idle state tracking, and messaging with the task manager when
* significant state changes occur
*/
- private void initIdleStateTracking(Context ctx) {
+ private void initIdleStateTracker() {
final boolean isCar = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
if (isCar) {
@@ -135,7 +134,11 @@
} else {
mIdleTracker = new DeviceIdlenessTracker();
}
- mIdleTracker.startTracking(ctx, mService, this);
+ }
+
+ @Override
+ public void startTrackingLocked() {
+ mIdleTracker.startTracking(mContext, mService, this);
}
@Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 13bea6b..b7480649 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -636,7 +636,7 @@
.build());
// Don't perform validation checks at this point since we've already passed the
// initial validation check.
- job = builder.build(false, false);
+ job = builder.build(false, false, false);
}
this.job = job;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
index fdeb072..865e541 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
@@ -134,7 +134,10 @@
mThresholdAlarmListener = new ThresholdAlarmListener(
mContext, AppSchedulingModuleThread.get().getLooper());
mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+ }
+ @Override
+ public void startTrackingLocked() {
mUsageStatsManagerInternal
.registerLaunchTimeChangedListener(mEstimatedLaunchTimeChangedListener);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
index 44ac798..2b92051 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
@@ -56,6 +56,12 @@
}
/**
+ * Called to get the controller to start tracking relevant information. This is called before
+ * {@link #onSystemServicesReady()}.
+ */
+ public void startTrackingLocked() {}
+
+ /**
* Called when the system boot phase has reached
* {@link com.android.server.SystemService#PHASE_SYSTEM_SERVICES_READY}.
*/
@@ -67,6 +73,7 @@
* This logic is put here so the JobManager can be completely agnostic of Controller logic.
* Also called when updating a task, so implementing controllers have to be aware of
* preexisting tasks.
+ * This will never be called before {@link #onSystemServicesReady()}.
*/
public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
index 11e2ff7..0c48c4e5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
@@ -55,6 +55,10 @@
public StorageController(JobSchedulerService service) {
super(service);
mStorageTracker = new StorageTracker();
+ }
+
+ @Override
+ public void startTrackingLocked() {
mStorageTracker.startTracking();
}
diff --git a/core/api/current.txt b/core/api/current.txt
index f01563a..119a3de 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12428,7 +12428,7 @@
method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback);
method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler);
method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalStatus(int, int, long, @Nullable android.app.PendingIntent) throws android.content.pm.PackageManager.NameNotFoundException;
- method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String, @NonNull android.content.IntentSender) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull String, @NonNull android.content.IntentSender);
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull android.content.pm.VersionedPackage, @NonNull android.content.IntentSender);
@@ -12853,6 +12853,8 @@
field public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; // 0x4
field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
+ field @FlaggedApi("android.content.pm.archiving") public static final int DELETE_ARCHIVE = 16; // 0x10
+ field @FlaggedApi("android.content.pm.archiving") public static final int DELETE_SHOW_DIALOG = 32; // 0x20
field public static final int DONT_KILL_APP = 1; // 0x1
field public static final String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
field public static final String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
@@ -19508,6 +19510,7 @@
field @Deprecated @NonNull public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_RADIAL_DISTORTION;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.String> LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID;
+ field @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
@@ -19533,6 +19536,7 @@
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_FACE_DETECT_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Point[]> STATISTICS_HOT_PIXEL_MAP;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> STATISTICS_HOT_PIXEL_MAP_MODE;
+ field @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.LensIntrinsicsSample[]> STATISTICS_LENS_INTRINSICS_SAMPLES;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.LensShadingMap> STATISTICS_LENS_SHADING_CORRECTION_MAP;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_LENS_SHADING_MAP_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_OIS_DATA_MODE;
@@ -19689,6 +19693,12 @@
method public boolean isMultiResolution();
}
+ @FlaggedApi("com.android.internal.camera.flags.concert_mode") public final class LensIntrinsicsSample {
+ ctor @FlaggedApi("com.android.internal.camera.flags.concert_mode") public LensIntrinsicsSample(long, @NonNull float[]);
+ method @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public float[] getLensIntrinsics();
+ method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public long getTimestamp();
+ }
+
public final class LensShadingMap {
method public void copyGainFactors(float[], int);
method public int getColumnCount();
@@ -33205,6 +33215,7 @@
public static class PerformanceHintManager.Session implements java.io.Closeable {
method public void close();
method public void reportActualWorkDuration(long);
+ method @FlaggedApi("android.os.adpf_gpu_report_actual_work_duration") public void reportActualWorkDuration(@NonNull android.os.WorkDuration);
method @FlaggedApi("android.os.adpf_prefer_power_efficiency") public void setPreferPowerEfficiency(boolean);
method public void setThreads(@NonNull int[]);
method public void updateTargetWorkDuration(long);
@@ -33554,6 +33565,7 @@
method public static boolean setCurrentTimeMillis(long);
method public static void sleep(long);
method public static long uptimeMillis();
+ method @FlaggedApi("android.os.adpf_gpu_report_actual_work_duration") public static long uptimeNanos();
}
public class TestLooperManager {
@@ -33819,6 +33831,22 @@
method @RequiresPermission(android.Manifest.permission.VIBRATE) public final void vibrate(@NonNull android.os.CombinedVibration, @Nullable android.os.VibrationAttributes);
}
+ @FlaggedApi("android.os.adpf_gpu_report_actual_work_duration") public final class WorkDuration implements android.os.Parcelable {
+ ctor public WorkDuration();
+ ctor public WorkDuration(long, long, long, long);
+ method public int describeContents();
+ method public long getActualCpuDurationNanos();
+ method public long getActualGpuDurationNanos();
+ method public long getActualTotalDurationNanos();
+ method public long getWorkPeriodStartTimestampNanos();
+ method public void setActualCpuDurationNanos(long);
+ method public void setActualGpuDurationNanos(long);
+ method public void setActualTotalDurationNanos(long);
+ method public void setWorkPeriodStartTimestampNanos(long);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.WorkDuration> CREATOR;
+ }
+
public class WorkSource implements android.os.Parcelable {
ctor public WorkSource();
ctor public WorkSource(android.os.WorkSource);
@@ -39264,7 +39292,7 @@
method @Nullable public java.util.Date getKeyValidityStart();
method @NonNull public String getKeystoreAlias();
method public int getMaxUsageCount();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
method public int getPurposes();
method @NonNull public String[] getSignaturePaddings();
method public int getUserAuthenticationType();
@@ -39272,7 +39300,7 @@
method public boolean isDevicePropertiesAttestationIncluded();
method @NonNull public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isStrongBoxBacked();
method public boolean isUnlockedDeviceRequired();
@@ -39304,7 +39332,7 @@
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -39409,14 +39437,14 @@
method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
method @Nullable public java.util.Date getKeyValidityStart();
method public int getMaxUsageCount();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
method public int getPurposes();
method @NonNull public String[] getSignaturePaddings();
method public int getUserAuthenticationType();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUnlockedDeviceRequired();
method public boolean isUserAuthenticationRequired();
@@ -39438,7 +39466,7 @@
method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
+ method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
@@ -47195,7 +47223,7 @@
method public void getSelectionPath(int, int, android.graphics.Path);
method public final float getSpacingAdd();
method public final float getSpacingMultiplier();
- method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public final CharSequence getText();
+ method @NonNull public final CharSequence getText();
method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public final android.text.TextDirectionHeuristic getTextDirectionHeuristic();
method public abstract int getTopPadding();
method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public boolean getUseBoundsForWidth();
diff --git a/core/api/removed.txt b/core/api/removed.txt
index b7714f1..12b1f6a 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -30,20 +30,6 @@
}
-package android.app.usage {
-
- public class StorageStatsManager {
- method @Deprecated public long getFreeBytes(String) throws java.io.IOException;
- method @Deprecated public long getTotalBytes(String) throws java.io.IOException;
- method @Deprecated public boolean isQuotaSupported(String);
- method @Deprecated public android.app.usage.ExternalStorageStats queryExternalStatsForUser(String, android.os.UserHandle) throws java.io.IOException;
- method @Deprecated public android.app.usage.StorageStats queryStatsForPackage(String, String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated public android.app.usage.StorageStats queryStatsForUid(String, int) throws java.io.IOException;
- method @Deprecated public android.app.usage.StorageStats queryStatsForUser(String, android.os.UserHandle) throws java.io.IOException;
- }
-
-}
-
package android.content {
public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 847edd1..30d57bb 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -351,6 +351,7 @@
field public static final String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER";
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SET_WALLPAPER_DIM_AMOUNT = "android.permission.SET_WALLPAPER_DIM_AMOUNT";
+ field @FlaggedApi("android.service.chooser.support_nfc_resolver") public static final String SHOW_CUSTOMIZED_RESOLVER = "android.permission.SHOW_CUSTOMIZED_RESOLVER";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
field public static final String SIGNAL_REBOOT_READINESS = "android.permission.SIGNAL_REBOOT_READINESS";
@@ -3872,6 +3873,7 @@
field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1
field public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
+ field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_DELETE_FLAGS = "android.content.pm.extra.DELETE_FLAGS";
field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
field @Deprecated public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH";
field public static final int LOCATION_DATA_APP = 0; // 0x0
@@ -11782,6 +11784,14 @@
}
+package android.service.chooser {
+
+ @FlaggedApi("android.service.chooser.support_nfc_resolver") public class CustomChoosers {
+ method @FlaggedApi("android.service.chooser.support_nfc_resolver") @NonNull public static android.content.Intent createNfcResolverIntent(@NonNull android.content.Intent, @Nullable CharSequence, @NonNull java.util.List<android.content.pm.ResolveInfo>);
+ }
+
+}
+
package android.service.cloudsearch {
public abstract class CloudSearchService extends android.app.Service {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 00432dc..c52d27ea 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -971,6 +971,7 @@
private final ActivityManager.TaskDescription mTaskDescription =
new ActivityManager.TaskDescription();
+ private int mLastTaskDescriptionHashCode;
protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
@@ -7612,6 +7613,13 @@
mTaskDescription.setIcon(Icon.createWithBitmap(icon));
}
}
+ if (mLastTaskDescriptionHashCode == mTaskDescription.hashCode()) {
+ // Early return if the hashCode is the same.
+ // Note that we do not use #equals() to perform the check because there are several
+ // places in this class that directly sets the value to mTaskDescription.
+ return;
+ }
+ mLastTaskDescriptionHashCode = mTaskDescription.hashCode();
ActivityClient.getInstance().setTaskDescription(mToken, mTaskDescription);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 854e121..6b7f4880 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2309,6 +2309,32 @@
}
@Override
+ public int hashCode() {
+ int result = 17;
+ if (mLabel != null) {
+ result = result * 31 + mLabel.hashCode();
+ }
+ if (mIcon != null) {
+ result = result * 31 + mIcon.hashCode();
+ }
+ if (mIconFilename != null) {
+ result = result * 31 + mIconFilename.hashCode();
+ }
+ result = result * 31 + mColorPrimary;
+ result = result * 31 + mColorBackground;
+ result = result * 31 + mColorBackgroundFloating;
+ result = result * 31 + mStatusBarColor;
+ result = result * 31 + mNavigationBarColor;
+ result = result * 31 + mStatusBarAppearance;
+ result = result * 31 + (mEnsureStatusBarContrastWhenTransparent ? 1 : 0);
+ result = result * 31 + (mEnsureNavigationBarContrastWhenTransparent ? 1 : 0);
+ result = result * 31 + mResizeMode;
+ result = result * 31 + mMinWidth;
+ result = result * 31 + mMinHeight;
+ return result;
+ }
+
+ @Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof TaskDescription)) {
return false;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 32c40df..ea9bb39 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -46,7 +46,6 @@
import android.os.WorkSource;
import android.util.ArraySet;
import android.util.Pair;
-import android.util.StatsEvent;
import com.android.internal.os.TimeoutRecord;
@@ -1224,7 +1223,8 @@
* @return The stats event for the cached apps high watermark since last pull.
*/
@NonNull
- public abstract StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull);
+ // TODO: restore to android.util.StatsEvent once Ravenwood includes Mainline stubs
+ public abstract Object getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull);
/**
* Internal method for clearing app data, with the extra param that is used to indicate restore.
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
index 18fc0ce..041866001 100644
--- a/core/java/android/app/Person.java
+++ b/core/java/android/app/Person.java
@@ -189,6 +189,11 @@
*/
public void visitUris(@NonNull Consumer<Uri> visitor) {
visitor.accept(getIconUri());
+ if (Flags.visitRiskyUris()) {
+ if (mUri != null && !mUri.isEmpty()) {
+ visitor.accept(Uri.parse(mUri));
+ }
+ }
}
/** Builder for the immutable {@link Person} class. */
diff --git a/core/java/android/app/time/TEST_MAPPING b/core/java/android/app/time/TEST_MAPPING
index 0f7a070..7673aca 100644
--- a/core/java/android/app/time/TEST_MAPPING
+++ b/core/java/android/app/time/TEST_MAPPING
@@ -15,10 +15,7 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- }
- ],
- // TODO(b/182461754): Change to "presubmit" when go/test-mapping-slo-guide allows.
- "postsubmit": [
+ },
{
"name": "FrameworksTimeServicesTests",
"options": [
diff --git a/core/java/android/app/timedetector/TEST_MAPPING b/core/java/android/app/timedetector/TEST_MAPPING
index 43dd82f..c7ca6a2 100644
--- a/core/java/android/app/timedetector/TEST_MAPPING
+++ b/core/java/android/app/timedetector/TEST_MAPPING
@@ -15,10 +15,7 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- }
- ],
- // TODO(b/182461754): Change to "presubmit" when go/test-mapping-slo-guide allows.
- "postsubmit": [
+ },
{
"name": "FrameworksTimeServicesTests",
"options": [
diff --git a/core/java/android/app/timezonedetector/TEST_MAPPING b/core/java/android/app/timezonedetector/TEST_MAPPING
index 2be5614..c8d0bb2 100644
--- a/core/java/android/app/timezonedetector/TEST_MAPPING
+++ b/core/java/android/app/timezonedetector/TEST_MAPPING
@@ -15,10 +15,7 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- }
- ],
- // TODO(b/182461754): Change to "presubmit" when go/test-mapping-slo-guide allows.
- "postsubmit": [
+ },
{
"name": "FrameworksTimeServicesTests",
"options": [
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 1ef1563..a4b1753 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -35,8 +35,6 @@
import android.os.storage.CrateInfo;
import android.os.storage.StorageManager;
-import com.android.internal.util.Preconditions;
-
import java.io.File;
import java.io.IOException;
import java.util.Collection;
@@ -77,7 +75,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public boolean isQuotaSupported(String uuid) {
return isQuotaSupported(convert(uuid));
@@ -120,7 +118,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public long getTotalBytes(String uuid) throws IOException {
return getTotalBytes(convert(uuid));
@@ -152,7 +150,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public long getFreeBytes(String uuid) throws IOException {
return getFreeBytes(convert(uuid));
@@ -221,7 +219,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public StorageStats queryStatsForPackage(String uuid, String packageName,
UserHandle user) throws PackageManager.NameNotFoundException, IOException {
@@ -262,7 +260,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public StorageStats queryStatsForUid(String uuid, int uid) throws IOException {
return queryStatsForUid(convert(uuid), uid);
@@ -300,7 +298,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException {
return queryStatsForUser(convert(uuid), user);
@@ -337,7 +335,7 @@
}
}
- /** @removed */
+ /** {@hide} */
@Deprecated
public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user)
throws IOException {
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 1f25fd0..32ecb58 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -80,7 +80,7 @@
long timeout);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES,android.Manifest.permission.REQUEST_DELETE_PACKAGES})")
- void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);
+ void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle, int flags);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
void requestUnarchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d35c392..457fd63 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -323,6 +323,14 @@
*/
@SystemApi
public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
+ /**
+ * Key for passing extra delete flags during archiving.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
+ public static final String EXTRA_DELETE_FLAGS = "android.content.pm.extra.DELETE_FLAGS";
/**
* Type of DataLoader for this session. Will be one of
@@ -2330,6 +2338,7 @@
* communicated.
*
* @param statusReceiver Callback used to notify when the operation is completed.
+ * @param flags Flags for archiving. Can be 0 or {@link PackageManager#DELETE_SHOW_DIALOG}.
* @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not
* available to the caller or isn't archived.
*/
@@ -2337,11 +2346,12 @@
Manifest.permission.DELETE_PACKAGES,
Manifest.permission.REQUEST_DELETE_PACKAGES})
@FlaggedApi(Flags.FLAG_ARCHIVING)
- public void requestArchive(@NonNull String packageName, @NonNull IntentSender statusReceiver)
+ public void requestArchive(@NonNull String packageName, @NonNull IntentSender statusReceiver,
+ @DeleteFlags int flags)
throws PackageManager.NameNotFoundException {
try {
mInstaller.requestArchive(packageName, mInstallerPackageName, statusReceiver,
- new UserHandle(mUserId));
+ new UserHandle(mUserId), flags);
} catch (ParcelableException e) {
e.maybeRethrow(PackageManager.NameNotFoundException.class);
} catch (RemoteException e) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a22fe3f..7bb673a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2552,6 +2552,7 @@
DELETE_SYSTEM_APP,
DELETE_DONT_KILL_APP,
DELETE_CHATTY,
+ DELETE_SHOW_DIALOG,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeleteFlags {}
@@ -2595,15 +2596,21 @@
public static final int DELETE_DONT_KILL_APP = 0x00000008;
/**
- * Flag parameter for {@link #deletePackage} to indicate that the deletion is an archival. This
+ * Flag parameter for {@link PackageInstaller#uninstall(VersionedPackage, int, IntentSender)} to
+ * indicate that the deletion is an archival. This
* flag is only for internal usage as part of
- * {@link PackageInstaller#requestArchive(String, IntentSender)}.
- *
- * @hide
+ * {@link PackageInstaller#requestArchive}.
*/
+ @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
public static final int DELETE_ARCHIVE = 0x00000010;
/**
+ * Show a confirmation dialog to the user when app is being deleted.
+ */
+ @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
+ public static final int DELETE_SHOW_DIALOG = 0x00000020;
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that package deletion
* should be chatty.
*
@@ -8964,7 +8971,7 @@
* Returns true if an app is archivable.
*
* @throws NameNotFoundException if the given package name is not available to the caller.
- * @see PackageInstaller#requestArchive(String, IntentSender)
+ * @see PackageInstaller#requestArchive
*/
@FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
public boolean isAppArchivable(@NonNull String packageName) throws NameNotFoundException {
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 12ab0f6..35f295a 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -5226,6 +5226,60 @@
new Key<android.hardware.camera2.params.OisSample[]>("android.statistics.oisSamples", android.hardware.camera2.params.OisSample[].class);
/**
+ * <p>An array of intra-frame lens intrinsic samples.</p>
+ * <p>Contains an array of intra-frame {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} updates. This must
+ * not be confused or compared to {@link CaptureResult#STATISTICS_OIS_SAMPLES android.statistics.oisSamples}. Although OIS could be the
+ * main driver, all relevant factors such as focus distance and optical zoom must also
+ * be included. Do note that OIS samples must not be applied on top of the lens intrinsic
+ * samples.
+ * Support for this capture result can be queried via
+ * {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.
+ * If available, clients can expect multiple samples per capture result. The specific
+ * amount will depend on current frame duration and sampling rate. Generally a sampling rate
+ * greater than or equal to 200Hz is considered sufficient for high quality results.</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CaptureResult#STATISTICS_OIS_SAMPLES
+ */
+ @PublicKey
+ @NonNull
+ @SyntheticKey
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public static final Key<android.hardware.camera2.params.LensIntrinsicsSample[]> STATISTICS_LENS_INTRINSICS_SAMPLES =
+ new Key<android.hardware.camera2.params.LensIntrinsicsSample[]>("android.statistics.lensIntrinsicsSamples", android.hardware.camera2.params.LensIntrinsicsSample[].class);
+
+ /**
+ * <p>An array of timestamps of lens intrinsics samples, in nanoseconds.</p>
+ * <p>The array contains the timestamps of lens intrinsics samples. The timestamps are in the
+ * same timebase as and comparable to {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp}.</p>
+ * <p><b>Units</b>: nanoseconds</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ *
+ * @see CaptureResult#SENSOR_TIMESTAMP
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public static final Key<long[]> STATISTICS_LENS_INTRINSIC_TIMESTAMPS =
+ new Key<long[]>("android.statistics.lensIntrinsicTimestamps", long[].class);
+
+ /**
+ * <p>An array of intra-frame lens intrinsics.</p>
+ * <p>The data layout and contents of individual array entries matches with
+ * {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}.</p>
+ * <p><b>Units</b>:
+ * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} coordinate system.</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public static final Key<float[]> STATISTICS_LENS_INTRINSIC_SAMPLES =
+ new Key<float[]>("android.statistics.lensIntrinsicSamples", float[].class);
+
+ /**
* <p>Tonemapping / contrast / gamma curve for the blue
* channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
* CONTRAST_CURVE.</p>
@@ -5668,6 +5722,55 @@
new Key<String>("android.logicalMultiCamera.activePhysicalId", String.class);
/**
+ * <p>The current region of the active physical sensor that will be read out for this
+ * capture.</p>
+ * <p>This capture result matches with {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} on non-logical single
+ * camera sensor devices. In case of logical cameras that can switch between several
+ * physical devices in response to {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, this capture result will
+ * not behave like {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} and {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, where the
+ * combination of both reflects the effective zoom and crop of the logical camera output.
+ * Instead, this capture result value will describe the zoom and crop of the active physical
+ * device. Some examples of when the value of this capture result will change include
+ * switches between different physical lenses, switches between regular and maximum
+ * resolution pixel mode and going through the device digital or optical range.
+ * This capture result is similar to {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} with respect to distortion
+ * correction. When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with (0, 0) being the top-left pixel
+ * of the pre-correction active array. When the distortion correction mode is not OFF,
+ * the coordinate system follows {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0, 0) being
+ * the top-left pixel of the active array.</p>
+ * <p>For camera devices with the
+ * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR }
+ * capability or devices where {@link CameraCharacteristics#getAvailableCaptureRequestKeys }
+ * lists {@link CaptureRequest#SENSOR_PIXEL_MODE {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode}}
+ * , the current active physical device
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION android.sensor.info.activeArraySizeMaximumResolution} /
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION android.sensor.info.preCorrectionActiveArraySizeMaximumResolution} must be used as the
+ * coordinate system for requests where {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode} is set to
+ * {@link android.hardware.camera2.CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION }.</p>
+ * <p><b>Units</b>: Pixel coordinates relative to
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} of the currently
+ * {@link CaptureResult#LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID android.logicalMultiCamera.activePhysicalId} depending on distortion correction capability
+ * and mode</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
+ * @see CaptureResult#LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
+ * @see CaptureRequest#SENSOR_PIXEL_MODE
+ */
+ @PublicKey
+ @NonNull
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public static final Key<android.graphics.Rect> LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION =
+ new Key<android.graphics.Rect>("android.logicalMultiCamera.activePhysicalSensorCropRegion", android.graphics.Rect.class);
+
+ /**
* <p>Mode of operation for the lens distortion correction block.</p>
* <p>The lens distortion correction block attempts to improve image quality by fixing
* radial, tangential, or other geometric aberrations in the camera device's optics. If
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 9743c1f..3affb73 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -55,6 +55,7 @@
import android.hardware.camera2.params.DynamicRangeProfiles;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
+import android.hardware.camera2.params.LensIntrinsicsSample;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MandatoryStreamCombination;
import android.hardware.camera2.params.MultiResolutionStreamConfigurationMap;
@@ -849,6 +850,15 @@
return (T) metadata.getMultiResolutionStreamConfigurationMap();
}
});
+ sGetCommandMap.put(
+ CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getLensIntrinsicSamples();
+ }
+ });
}
private int[] getAvailableFormats() {
@@ -1780,6 +1790,56 @@
return samples;
}
+ private boolean setLensIntrinsicsSamples(LensIntrinsicsSample[] samples) {
+ if (samples == null) {
+ return false;
+ }
+
+ long[] tsArray = new long[samples.length];
+ float[] intrinsicsArray = new float[samples.length * 5];
+ for (int i = 0; i < samples.length; i++) {
+ tsArray[i] = samples[i].getTimestamp();
+ System.arraycopy(samples[i].getLensIntrinsics(), 0, intrinsicsArray, 5*i, 5);
+
+ }
+ setBase(CaptureResult.STATISTICS_LENS_INTRINSIC_SAMPLES, intrinsicsArray);
+ setBase(CaptureResult.STATISTICS_LENS_INTRINSIC_TIMESTAMPS, tsArray);
+
+ return true;
+ }
+
+ private LensIntrinsicsSample[] getLensIntrinsicSamples() {
+ long[] timestamps = getBase(CaptureResult.STATISTICS_LENS_INTRINSIC_TIMESTAMPS);
+ float[] intrinsics = getBase(CaptureResult.STATISTICS_LENS_INTRINSIC_SAMPLES);
+
+ if (timestamps == null) {
+ if (intrinsics != null) {
+ throw new AssertionError("timestamps is null but intrinsics is not");
+ }
+
+ return null;
+ }
+
+ if (intrinsics == null) {
+ throw new AssertionError("timestamps is not null but intrinsics is");
+ } else if((intrinsics.length % 5) != 0) {
+ throw new AssertionError("intrinsics are not multiple of 5");
+ }
+
+ if ((intrinsics.length / 5) != timestamps.length) {
+ throw new AssertionError(String.format(
+ "timestamps has %d entries but intrinsics has %d", timestamps.length,
+ intrinsics.length / 5));
+ }
+
+ LensIntrinsicsSample[] samples = new LensIntrinsicsSample[timestamps.length];
+ for (int i = 0; i < timestamps.length; i++) {
+ float[] currentIntrinsic = Arrays.copyOfRange(intrinsics, 5*i, 5*i + 5);
+ samples[i] = new LensIntrinsicsSample(timestamps[i], currentIntrinsic);
+ }
+ return samples;
+ }
+
private Capability[] getExtendedSceneModeCapabilities() {
int[] maxSizes =
getBase(CameraCharacteristics.CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES);
@@ -1947,6 +2007,15 @@
metadata.setLensShadingMap((LensShadingMap) value);
}
});
+ sSetCommandMap.put(
+ CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES.getNativeKey(),
+ new SetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> void setValue(CameraMetadataNative metadata, T value) {
+ metadata.setLensIntrinsicsSamples((LensIntrinsicsSample []) value);
+ }
+ });
}
private boolean setAvailableFormats(int[] value) {
diff --git a/core/java/android/hardware/camera2/params/LensIntrinsicsSample.java b/core/java/android/hardware/camera2/params/LensIntrinsicsSample.java
new file mode 100644
index 0000000..575cbfa
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/LensIntrinsicsSample.java
@@ -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 android.hardware.camera2.params;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.utils.HashCodeHelpers;
+import android.text.TextUtils;
+
+import com.android.internal.camera.flags.Flags;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class to store an
+ * {@link CaptureResult#STATISTICS_LENS_INTRINSICS_SAMPLES lens intrinsics intra-frame sample}.
+ */
+@FlaggedApi(Flags.FLAG_CONCERT_MODE)
+public final class LensIntrinsicsSample {
+ /**
+ * Create a new {@link LensIntrinsicsSample}.
+ *
+ * <p>{@link LensIntrinsicsSample} contains the timestamp and the
+ * {@link CaptureResult#LENS_INTRINSIC_CALIBRATION} sample.
+ *
+ * @param timestamp timestamp of the lens intrinsics sample.
+ * @param lensIntrinsics the lens intrinsic calibration for the sample.
+ *
+ * @throws IllegalArgumentException if lensIntrinsics length is different from 5
+ */
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public LensIntrinsicsSample(final long timestamp, @NonNull final float[] lensIntrinsics) {
+ mTimestampNs = timestamp;
+ Preconditions.checkArgument(lensIntrinsics.length == 5);
+ mLensIntrinsics = lensIntrinsics;
+ }
+
+ /**
+ * Get the timestamp in nanoseconds.
+ *
+ *<p>The timestamps are in the same timebase as and comparable to
+ *{@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp}.</p>
+ *
+ * @return a long value (guaranteed to be finite)
+ */
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public long getTimestamp() {
+ return mTimestampNs;
+ }
+
+ /**
+ * Get the lens intrinsics calibration
+ *
+ * @return a floating point value (guaranteed to be finite)
+ * @see CaptureResult#LENS_INTRINSIC_CALIBRATION
+ */
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @NonNull
+ public float[] getLensIntrinsics() {
+ return mLensIntrinsics;
+ }
+
+ /**
+ * Check if this {@link LensIntrinsicsSample} is equal to another {@link LensIntrinsicsSample}.
+ *
+ * <p>Two samples are only equal if and only if each of the lens intrinsics are equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ } else if (this == obj) {
+ return true;
+ } else if (obj instanceof LensIntrinsicsSample) {
+ final LensIntrinsicsSample other = (LensIntrinsicsSample) obj;
+ return mTimestampNs == other.mTimestampNs
+ && Arrays.equals(mLensIntrinsics, other.getLensIntrinsics());
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ int timestampHash = HashCodeHelpers.hashCode(((float)mTimestampNs));
+ return HashCodeHelpers.hashCode(Arrays.hashCode(mLensIntrinsics), timestampHash);
+ }
+
+ /**
+ * Return the LensIntrinsicsSample as a string representation.
+ *
+ * <p> {@code "LensIntrinsicsSample{timestamp:%l, sample:%s}"} represents the LensIntrinsics
+ * sample's timestamp, and calibration data.</p>
+ *
+ * @return string representation of {@link LensIntrinsicsSample}
+ */
+ @Override
+ public String toString() {
+ return TextUtils.formatSimple("LensIntrinsicsSample{timestamp:%d, sample:%s}", mTimestampNs,
+ Arrays.toString(mLensIntrinsics));
+ }
+
+ private final long mTimestampNs;
+ private final float [] mLensIntrinsics;
+}
diff --git a/core/java/android/os/IHintSession.aidl b/core/java/android/os/IHintSession.aidl
index 6b43e73..fe85da2 100644
--- a/core/java/android/os/IHintSession.aidl
+++ b/core/java/android/os/IHintSession.aidl
@@ -17,6 +17,8 @@
package android.os;
+import android.os.WorkDuration;
+
/** {@hide} */
oneway interface IHintSession {
void updateTargetWorkDuration(long targetDurationNanos);
@@ -24,4 +26,5 @@
void close();
void sendHint(int hint);
void setMode(int mode, boolean enabled);
+ void reportActualWorkDuration2(in WorkDuration[] workDurations);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 86628d9..f2930fe 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -27,6 +27,10 @@
import android.annotation.TestApi;
import android.app.AppOpsManager;
import android.compat.annotation.UnsupportedAppUsage;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
+import android.ravenwood.annotation.RavenwoodThrow;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -228,6 +232,8 @@
* {@link #readMap(Map, ClassLoader, Class, Class)},
* {@link #readSparseArray(ClassLoader, Class)}.
*/
+@RavenwoodKeepWholeClass
+@RavenwoodNativeSubstitutionClass("com.android.hoststubgen.nativesubstitution.Parcel_host")
public final class Parcel {
private static final boolean DEBUG_RECYCLE = false;
@@ -382,8 +388,10 @@
@CriticalNative
private static native void nativeMarkSensitive(long nativePtr);
@FastNative
+ @RavenwoodThrow
private static native void nativeMarkForBinder(long nativePtr, IBinder binder);
@CriticalNative
+ @RavenwoodThrow
private static native boolean nativeIsForRpc(long nativePtr);
@CriticalNative
private static native int nativeDataSize(long nativePtr);
@@ -415,14 +423,17 @@
private static native int nativeWriteFloat(long nativePtr, float val);
@CriticalNative
private static native int nativeWriteDouble(long nativePtr, double val);
+ @RavenwoodThrow
private static native void nativeSignalExceptionForError(int error);
@FastNative
private static native void nativeWriteString8(long nativePtr, String val);
@FastNative
private static native void nativeWriteString16(long nativePtr, String val);
@FastNative
+ @RavenwoodThrow
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
@FastNative
+ @RavenwoodThrow
private static native void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);
private static native byte[] nativeCreateByteArray(long nativePtr);
@@ -441,8 +452,10 @@
@FastNative
private static native String nativeReadString16(long nativePtr);
@FastNative
+ @RavenwoodThrow
private static native IBinder nativeReadStrongBinder(long nativePtr);
@FastNative
+ @RavenwoodThrow
private static native FileDescriptor nativeReadFileDescriptor(long nativePtr);
private static native long nativeCreate();
@@ -452,7 +465,9 @@
private static native byte[] nativeMarshall(long nativePtr);
private static native void nativeUnmarshall(
long nativePtr, byte[] data, int offset, int length);
+ @RavenwoodThrow
private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+ @RavenwoodThrow
private static native boolean nativeCompareDataInRange(
long ptrA, int offsetA, long ptrB, int offsetB, int length);
private static native void nativeAppendFrom(
@@ -461,13 +476,17 @@
private static native boolean nativeHasFileDescriptors(long nativePtr);
private static native boolean nativeHasFileDescriptorsInRange(
long nativePtr, int offset, int length);
+ @RavenwoodThrow
private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
+ @RavenwoodThrow
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
@CriticalNative
+ @RavenwoodThrow
private static native boolean nativeReplaceCallingWorkSourceUid(
long nativePtr, int workSourceUid);
@CriticalNative
+ @RavenwoodThrow
private static native int nativeReadCallingWorkSourceUid(long nativePtr);
/** Last time exception with a stack trace was written */
@@ -476,6 +495,7 @@
private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000;
@CriticalNative
+ @RavenwoodThrow
private static native long nativeGetOpenAshmemSize(long nativePtr);
public final static Parcelable.Creator<String> STRING_CREATOR
@@ -634,10 +654,12 @@
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RavenwoodThrow
public static native long getGlobalAllocSize();
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RavenwoodThrow
public static native long getGlobalAllocCount();
/**
@@ -2918,6 +2940,7 @@
* @see #writeNoException
* @see #readException
*/
+ @RavenwoodReplace
public final void writeException(@NonNull Exception e) {
AppOpsManager.prefixParcelWithAppOpsIfNeeded(this);
@@ -3017,6 +3040,7 @@
* @see #writeException
* @see #readException
*/
+ @RavenwoodReplace
public final void writeNoException() {
AppOpsManager.prefixParcelWithAppOpsIfNeeded(this);
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index f2b60a4..b5c09bb 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -86,6 +87,7 @@
* }
* }</pre></section></div></div>
*/
+@RavenwoodKeepWholeClass
public interface Parcelable {
/** @hide */
@IntDef(flag = true, prefix = { "PARCELABLE_" }, value = {
diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java
index 11084b8..e005910 100644
--- a/core/java/android/os/PerformanceHintManager.java
+++ b/core/java/android/os/PerformanceHintManager.java
@@ -103,7 +103,7 @@
* Any call in this class will change its internal data, so you must do your own thread
* safety to protect from racing.
*
- * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ * All timings should be in {@link SystemClock#uptimeNanos()}.
*/
public static class Session implements Closeable {
private long mNativeSessionPtr;
@@ -269,6 +269,40 @@
public @Nullable int[] getThreadIds() {
return nativeGetThreadIds(mNativeSessionPtr);
}
+
+ /**
+ * Reports the work duration for the last cycle of work.
+ *
+ * The system will attempt to adjust the core placement of the threads within the thread
+ * group and/or the frequency of the core on which they are run to bring the actual duration
+ * close to the target duration.
+ *
+ * @param workDuration the work duration of each component.
+ * @throws IllegalArgumentException if work period start timestamp is not positive, or
+ * actual total duration is not positive, or actual CPU duration is not positive,
+ * or actual GPU duration is negative.
+ */
+ @FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION)
+ public void reportActualWorkDuration(@NonNull WorkDuration workDuration) {
+ if (workDuration.mWorkPeriodStartTimestampNanos <= 0) {
+ throw new IllegalArgumentException(
+ "the work period start timestamp should be positive.");
+ }
+ if (workDuration.mActualTotalDurationNanos <= 0) {
+ throw new IllegalArgumentException("the actual total duration should be positive.");
+ }
+ if (workDuration.mActualCpuDurationNanos <= 0) {
+ throw new IllegalArgumentException("the actual CPU duration should be positive.");
+ }
+ if (workDuration.mActualGpuDurationNanos < 0) {
+ throw new IllegalArgumentException(
+ "the actual GPU duration should be non negative.");
+ }
+ nativeReportActualWorkDuration(mNativeSessionPtr,
+ workDuration.mWorkPeriodStartTimestampNanos,
+ workDuration.mActualTotalDurationNanos,
+ workDuration.mActualCpuDurationNanos, workDuration.mActualGpuDurationNanos);
+ }
}
private static native long nativeAcquireManager();
@@ -285,4 +319,7 @@
private static native void nativeSetThreads(long nativeSessionPtr, int[] tids);
private static native void nativeSetPreferPowerEfficiency(long nativeSessionPtr,
boolean enabled);
+ private static native void nativeReportActualWorkDuration(long nativeSessionPtr,
+ long workPeriodStartTimestampNanos, long actualTotalDurationNanos,
+ long actualCpuDurationNanos, long actualGpuDurationNanos);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 11660f9..7e07e1f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -853,6 +853,7 @@
args.argi2 = pid;
args.argi3 = Long.hashCode(Thread.currentThread().getId());
args.argi4 = THREAD_PRIORITY_DEFAULT;
+ args.arg1 = Boolean.TRUE; // backgroundOk
return args;
});
}
@@ -1105,6 +1106,11 @@
final SomeArgs args =
Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get();
if (args.argi3 == tid) {
+ boolean backgroundOk = (args.arg1 == Boolean.TRUE);
+ if (priority >= THREAD_PRIORITY_BACKGROUND && !backgroundOk) {
+ throw new IllegalArgumentException(
+ "Priority " + priority + " blocked by setCanSelfBackground()");
+ }
args.argi4 = priority;
} else {
throw new UnsupportedOperationException(
@@ -1119,8 +1125,16 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static final native void setCanSelfBackground(boolean backgroundOk);
+ /** @hide */
+ public static final void setCanSelfBackground$ravenwood(boolean backgroundOk) {
+ final SomeArgs args =
+ Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get();
+ args.arg1 = Boolean.valueOf(backgroundOk);
+ }
+
/**
* Sets the scheduling group for a thread.
* @hide
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 2e6cccb..23bd30a 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.app.IAlarmManager;
import android.app.time.UnixEpochTime;
@@ -205,8 +206,8 @@
* Returns nanoseconds since boot, not counting time spent in deep sleep.
*
* @return nanoseconds of non-sleep uptime since boot.
- * @hide
*/
+ @FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION)
@CriticalNative
@android.ravenwood.annotation.RavenwoodReplace
public static native long uptimeNanos();
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 0d0d1da..5d7e04d 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -444,7 +444,8 @@
* these characters they will be replaced with a space character in the trace.
*
* @param sectionName The name of the code section to appear in the trace. This may be at
- * most 127 Unicode code units long.
+ * most 127 Unicode code units long.
+ * @throws IllegalArgumentException if {@code sectionName} is too long.
*/
public static void beginSection(@NonNull String sectionName) {
if (isTagEnabled(TRACE_TAG_APP)) {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/core/java/android/os/WorkDuration.aidl
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to core/java/android/os/WorkDuration.aidl
index 4098987..0f61204 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/core/java/android/os/WorkDuration.aidl
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package android.os;
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
-
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+parcelable WorkDuration cpp_header "android/WorkDuration.h";
\ No newline at end of file
diff --git a/core/java/android/os/WorkDuration.java b/core/java/android/os/WorkDuration.java
new file mode 100644
index 0000000..4fdc34f
--- /dev/null
+++ b/core/java/android/os/WorkDuration.java
@@ -0,0 +1,213 @@
+/*
+ * 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.os;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+
+import java.util.Objects;
+
+/**
+ * WorkDuration contains the measured time in nano seconds of the workload
+ * in each component, see
+ * {@link PerformanceHintManager.Session#reportActualWorkDuration(WorkDuration)}.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION)
+public final class WorkDuration implements Parcelable {
+ long mWorkPeriodStartTimestampNanos = 0;
+ long mActualTotalDurationNanos = 0;
+ long mActualCpuDurationNanos = 0;
+ long mActualGpuDurationNanos = 0;
+ long mTimestampNanos = 0;
+
+ public static final @NonNull Creator<WorkDuration> CREATOR = new Creator<>() {
+ @Override
+ public WorkDuration createFromParcel(Parcel in) {
+ return new WorkDuration(in);
+ }
+
+ @Override
+ public WorkDuration[] newArray(int size) {
+ return new WorkDuration[size];
+ }
+ };
+
+ public WorkDuration() {}
+
+ public WorkDuration(long workPeriodStartTimestampNanos,
+ long actualTotalDurationNanos,
+ long actualCpuDurationNanos,
+ long actualGpuDurationNanos) {
+ mWorkPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
+ mActualTotalDurationNanos = actualTotalDurationNanos;
+ mActualCpuDurationNanos = actualCpuDurationNanos;
+ mActualGpuDurationNanos = actualGpuDurationNanos;
+ }
+
+ /**
+ * @hide
+ */
+ public WorkDuration(long workPeriodStartTimestampNanos,
+ long actualTotalDurationNanos,
+ long actualCpuDurationNanos,
+ long actualGpuDurationNanos,
+ long timestampNanos) {
+ mWorkPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
+ mActualTotalDurationNanos = actualTotalDurationNanos;
+ mActualCpuDurationNanos = actualCpuDurationNanos;
+ mActualGpuDurationNanos = actualGpuDurationNanos;
+ mTimestampNanos = timestampNanos;
+ }
+
+ WorkDuration(@NonNull Parcel in) {
+ mWorkPeriodStartTimestampNanos = in.readLong();
+ mActualTotalDurationNanos = in.readLong();
+ mActualCpuDurationNanos = in.readLong();
+ mActualGpuDurationNanos = in.readLong();
+ mTimestampNanos = in.readLong();
+ }
+
+ /**
+ * Sets the work period start timestamp in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public void setWorkPeriodStartTimestampNanos(long workPeriodStartTimestampNanos) {
+ if (workPeriodStartTimestampNanos <= 0) {
+ throw new IllegalArgumentException(
+ "the work period start timestamp should be positive.");
+ }
+ mWorkPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
+ }
+
+ /**
+ * Sets the actual total duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public void setActualTotalDurationNanos(long actualTotalDurationNanos) {
+ if (actualTotalDurationNanos <= 0) {
+ throw new IllegalArgumentException("the actual total duration should be positive.");
+ }
+ mActualTotalDurationNanos = actualTotalDurationNanos;
+ }
+
+ /**
+ * Sets the actual CPU duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public void setActualCpuDurationNanos(long actualCpuDurationNanos) {
+ if (actualCpuDurationNanos <= 0) {
+ throw new IllegalArgumentException("the actual CPU duration should be positive.");
+ }
+ mActualCpuDurationNanos = actualCpuDurationNanos;
+ }
+
+ /**
+ * Sets the actual GPU duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public void setActualGpuDurationNanos(long actualGpuDurationNanos) {
+ if (actualGpuDurationNanos < 0) {
+ throw new IllegalArgumentException("the actual GPU duration should be non negative.");
+ }
+ mActualGpuDurationNanos = actualGpuDurationNanos;
+ }
+
+ /**
+ * Returns the work period start timestamp based in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public long getWorkPeriodStartTimestampNanos() {
+ return mWorkPeriodStartTimestampNanos;
+ }
+
+ /**
+ * Returns the actual total duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public long getActualTotalDurationNanos() {
+ return mActualTotalDurationNanos;
+ }
+
+ /**
+ * Returns the actual CPU duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public long getActualCpuDurationNanos() {
+ return mActualCpuDurationNanos;
+ }
+
+ /**
+ * Returns the actual GPU duration in nanoseconds.
+ *
+ * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ public long getActualGpuDurationNanos() {
+ return mActualGpuDurationNanos;
+ }
+
+ /**
+ * @hide
+ */
+ public long getTimestampNanos() {
+ return mTimestampNanos;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mWorkPeriodStartTimestampNanos);
+ dest.writeLong(mActualTotalDurationNanos);
+ dest.writeLong(mActualCpuDurationNanos);
+ dest.writeLong(mActualGpuDurationNanos);
+ dest.writeLong(mTimestampNanos);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof WorkDuration)) {
+ return false;
+ }
+ WorkDuration workDuration = (WorkDuration) obj;
+ return workDuration.mTimestampNanos == this.mTimestampNanos
+ && workDuration.mWorkPeriodStartTimestampNanos == this.mWorkPeriodStartTimestampNanos
+ && workDuration.mActualTotalDurationNanos == this.mActualTotalDurationNanos
+ && workDuration.mActualCpuDurationNanos == this.mActualCpuDurationNanos
+ && workDuration.mActualGpuDurationNanos == this.mActualGpuDurationNanos;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mWorkPeriodStartTimestampNanos, mActualTotalDurationNanos,
+ mActualCpuDurationNanos, mActualGpuDurationNanos, mTimestampNanos);
+ }
+}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index c085f33..980c13c 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -68,4 +68,11 @@
namespace: "backstage_power"
description: "Guards a new API in PowerManager to check if battery saver is supported or not."
bug: "305067031"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "adpf_gpu_report_actual_work_duration"
+ namespace: "game"
+ description: "Guards the ADPF GPU APIs."
+ bug: "284324521"
+}
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 28ef70b..0dc0413 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -8,13 +8,6 @@
}
flag {
- name: "mgf1_digest_setter"
- namespace: "hardware_backed_security"
- description: "Feature flag for mgf1 digest setter in key generation and import parameters."
- bug: "308378912"
-}
-
-flag {
name: "fix_unlocked_device_required_keys_v2"
namespace: "hardware_backed_security"
description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys"
diff --git a/core/java/android/service/chooser/CustomChoosers.java b/core/java/android/service/chooser/CustomChoosers.java
new file mode 100644
index 0000000..5b89432
--- /dev/null
+++ b/core/java/android/service/chooser/CustomChoosers.java
@@ -0,0 +1,84 @@
+/*
+ * 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.service.chooser;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Static helper methods that privileged clients can use to initiate Share sessions with extra
+ * customization options that aren't usually available in the stock "Resolver/Chooser" flows.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_SUPPORT_NFC_RESOLVER)
+@SystemApi
+public class CustomChoosers {
+ /**
+ * Intent action to start a Share session with additional customization options. Clients should
+ * use the helper methods in this class to configure their customized share intents, and should
+ * avoid using this action to construct their own intents directly.
+ */
+ private static final String ACTION_SHOW_CUSTOMIZED_RESOLVER =
+ "android.service.chooser.action.SHOW_CUSTOMIZED_RESOLVER";
+
+ /**
+ * "Extras" key for an ArrayList of {@link ResolveInfo} records which are to be shown as the
+ * targets in the customized share session.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RESOLVE_INFOS = "android.service.chooser.extra.RESOLVE_INFOS";
+
+ /**
+ * Build an {@link Intent} to dispatch a "Chooser flow" that picks a target resolution for the
+ * specified {@code target} intent, styling the Chooser UI according to the specified
+ * customization parameters.
+ *
+ * @param target The ambiguous intent that should be resolved to a specific target selected
+ * via the Chooser flow.
+ * @param title An optional "headline" string to display at the top of the Chooser UI, or null
+ * to use the system default.
+ * @param resolutionList Explicit resolution info for targets that should be shown in the
+ * dispatched Share UI.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_SUPPORT_NFC_RESOLVER)
+ @SystemApi
+ @NonNull
+ public static Intent createNfcResolverIntent(
+ @NonNull Intent target,
+ @Nullable CharSequence title,
+ @NonNull List<ResolveInfo> resolutionList) {
+ Intent resolverIntent = new Intent(ACTION_SHOW_CUSTOMIZED_RESOLVER);
+ resolverIntent.putExtra(Intent.EXTRA_INTENT, target);
+ resolverIntent.putExtra(Intent.EXTRA_TITLE, title);
+ resolverIntent.putParcelableArrayListExtra(
+ EXTRA_RESOLVE_INFOS, new ArrayList<>(resolutionList));
+ return resolverIntent;
+ }
+
+ private CustomChoosers() {}
+}
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 3a4a0c5..b1680ab 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -1241,7 +1241,7 @@
* @hide
*/
public byte[] toProto() {
- // TODO: b/308672510 - log new ZenPolicy fields to DNDPolicyProto.
+ // TODO: b/308672510 - log user-customized ZenPolicy fields to DNDPolicyProto.
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ProtoOutputStream proto = new ProtoOutputStream(bytes);
@@ -1267,6 +1267,10 @@
proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders());
proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders());
+ if (Flags.modesApi()) {
+ proto.write(DNDPolicyProto.ALLOW_CHANNELS, getAllowedChannels());
+ }
+
proto.flush();
return bytes.toByteArray();
}
diff --git a/core/java/android/service/timezone/TEST_MAPPING b/core/java/android/service/timezone/TEST_MAPPING
index e5910ea..bf46ff2 100644
--- a/core/java/android/service/timezone/TEST_MAPPING
+++ b/core/java/android/service/timezone/TEST_MAPPING
@@ -7,10 +7,7 @@
"include-filter": "android.service."
}
]
- }
- ],
- // TODO(b/182461754): Change to "presubmit" when go/test-mapping-slo-guide allows.
- "postsubmit": [
+ },
{
"name": "CtsLocationTimeZoneManagerHostTest"
}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index e6fcc0c..388f08a 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -28,31 +28,15 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
-import android.os.Binder;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.CloseGuard;
-import android.util.Log;
-import android.util.Slog;
import com.android.internal.R;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.Reference;
import java.util.List;
-import java.util.Objects;
-import java.util.Queue;
import java.util.concurrent.Executor;
-import java.util.concurrent.LinkedBlockingQueue;
/**
* This class provides access to the speech recognition service. This service allows access to the
@@ -72,11 +56,6 @@
* permission to use this class.
*/
public class SpeechRecognizer {
- /** DEBUG value to enable verbose debug prints */
- private static final boolean DBG = false;
-
- /** Log messages identifier */
- private static final String TAG = "SpeechRecognizer";
/**
* Key used to retrieve an {@code ArrayList<String>} from the {@link Bundle} passed to the
@@ -303,106 +282,17 @@
private static final int MSG_CHECK_RECOGNITION_SUPPORT = 6;
private static final int MSG_TRIGGER_MODEL_DOWNLOAD = 7;
- /** The actual RecognitionService endpoint */
- private IRecognitionService mService;
-
- private final CloseGuard mCloseGuard = new CloseGuard();
-
- /** Context with which the manager was created */
- private final Context mContext;
-
- /** Component to direct service intent to */
- private final ComponentName mServiceComponent;
-
- /** Whether to use on-device speech recognizer. */
- private final boolean mOnDevice;
-
- private IRecognitionServiceManager mManagerService;
-
- /** Handler that will execute the main tasks */
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START:
- handleStartListening((Intent) msg.obj);
- break;
- case MSG_STOP:
- handleStopMessage();
- break;
- case MSG_CANCEL:
- handleCancelMessage();
- break;
- case MSG_CHANGE_LISTENER:
- handleChangeListener((RecognitionListener) msg.obj);
- break;
- case MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT:
- handleSetTemporaryComponent((ComponentName) msg.obj);
- break;
- case MSG_CHECK_RECOGNITION_SUPPORT:
- CheckRecognitionSupportArgs args = (CheckRecognitionSupportArgs) msg.obj;
- handleCheckRecognitionSupport(
- args.mIntent, args.mCallbackExecutor, args.mCallback);
- break;
- case MSG_TRIGGER_MODEL_DOWNLOAD:
- ModelDownloadListenerArgs modelDownloadListenerArgs =
- (ModelDownloadListenerArgs) msg.obj;
- handleTriggerModelDownload(
- modelDownloadListenerArgs.mIntent,
- modelDownloadListenerArgs.mExecutor,
- modelDownloadListenerArgs.mModelDownloadListener);
- break;
- }
- }
- };
-
- /**
- * Temporary queue, saving the messages until the connection will be established, afterwards,
- * only mHandler will receive the messages
- */
- private final Queue<Message> mPendingTasks = new LinkedBlockingQueue<>();
-
- /** The Listener that will receive all the callbacks */
- private final InternalRecognitionListener mListener = new InternalRecognitionListener();
-
- private final IBinder mClientToken = new Binder();
-
- /**
- * The right way to create a {@code SpeechRecognizer} is by using
- * {@link #createSpeechRecognizer} static factory method
- */
- private SpeechRecognizer(final Context context, final ComponentName serviceComponent) {
- this(context, serviceComponent, false);
- }
-
- /**
- * The right way to create a {@code SpeechRecognizer} is by using
- * {@link #createOnDeviceSpeechRecognizer} static factory method
- */
- private SpeechRecognizer(final Context context, boolean onDevice) {
- this(context, null, onDevice);
- }
-
- private SpeechRecognizer(
- final Context context,
- final ComponentName serviceComponent,
- final boolean onDevice) {
- mContext = context;
- mServiceComponent = serviceComponent;
- mOnDevice = onDevice;
- mCloseGuard.open("SpeechRecognizer#destroy()");
- }
+ SpeechRecognizer() { }
/**
* Checks whether a speech recognition service is available on the system. If this method
* returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will
* fail.
- *
+ *
* @param context with which {@code SpeechRecognizer} will be created
* @return {@code true} if recognition is available, {@code false} otherwise
*/
- public static boolean isRecognitionAvailable(@NonNull final Context context) {
+ public static boolean isRecognitionAvailable(@NonNull Context context) {
// TODO(b/176578753): make sure this works well with system speech recognizers.
final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
new Intent(RecognitionService.SERVICE_INTERFACE), 0);
@@ -418,7 +308,7 @@
* @param context with which on-device {@code SpeechRecognizer} will be created
* @return {@code true} if on-device recognition is available, {@code false} otherwise
*/
- public static boolean isOnDeviceRecognitionAvailable(@NonNull final Context context) {
+ public static boolean isOnDeviceRecognitionAvailable(@NonNull Context context) {
ComponentName componentName =
ComponentName.unflattenFromString(
context.getString(R.string.config_defaultOnDeviceSpeechRecognitionService));
@@ -449,7 +339,7 @@
* @return a new {@code SpeechRecognizer}
*/
@MainThread
- public static SpeechRecognizer createSpeechRecognizer(final Context context) {
+ public static SpeechRecognizer createSpeechRecognizer(Context context) {
return createSpeechRecognizer(context, null);
}
@@ -483,19 +373,19 @@
* </queries>
* }</pre>
*
- * @param context in which to create {@code SpeechRecognizer}
+ * @param context in which to create {@code SpeechRecognizer}
* @param serviceComponent the {@link ComponentName} of a specific service to direct this
- * {@code SpeechRecognizer} to
+ * {@code SpeechRecognizer} to
* @return a new {@code SpeechRecognizer}
*/
@MainThread
- public static SpeechRecognizer createSpeechRecognizer(final Context context,
- final ComponentName serviceComponent) {
+ public static SpeechRecognizer createSpeechRecognizer(Context context,
+ ComponentName serviceComponent) {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null");
}
- checkIsCalledFromMainThread();
- return new SpeechRecognizer(context, serviceComponent);
+ SpeechRecognizerImpl.checkIsCalledFromMainThread();
+ return wrapWithProxy(new SpeechRecognizerImpl(context, serviceComponent));
}
/**
@@ -515,11 +405,15 @@
*/
@NonNull
@MainThread
- public static SpeechRecognizer createOnDeviceSpeechRecognizer(@NonNull final Context context) {
+ public static SpeechRecognizer createOnDeviceSpeechRecognizer(@NonNull Context context) {
if (!isOnDeviceRecognitionAvailable(context)) {
throw new UnsupportedOperationException("On-device recognition is not available");
}
- return lenientlyCreateOnDeviceSpeechRecognizer(context);
+ return wrapWithProxy(SpeechRecognizerImpl.lenientlyCreateOnDeviceSpeechRecognizer(context));
+ }
+
+ private static SpeechRecognizer wrapWithProxy(SpeechRecognizer delegate) {
+ return new SpeechRecognizerProxy(delegate);
}
/**
@@ -532,42 +426,21 @@
@NonNull
@MainThread
public static SpeechRecognizer createOnDeviceTestingSpeechRecognizer(
- @NonNull final Context context) {
- return lenientlyCreateOnDeviceSpeechRecognizer(context);
- }
-
- @NonNull
- @MainThread
- private static SpeechRecognizer lenientlyCreateOnDeviceSpeechRecognizer(
- @NonNull final Context context) {
- if (context == null) {
- throw new IllegalArgumentException("Context cannot be null");
- }
- checkIsCalledFromMainThread();
- return new SpeechRecognizer(context, /* onDevice */ true);
+ @NonNull Context context) {
+ return wrapWithProxy(SpeechRecognizerImpl.lenientlyCreateOnDeviceSpeechRecognizer(context));
}
/**
* Sets the listener that will receive all the callbacks. The previous unfinished commands will
* be executed with the old listener, while any following command will be executed with the new
* listener.
- *
+ *
* @param listener listener that will receive all the callbacks from the created
- * {@link SpeechRecognizer}, this must not be null.
+ * {@link SpeechRecognizer}, this must not be null.
*/
@MainThread
public void setRecognitionListener(RecognitionListener listener) {
- checkIsCalledFromMainThread();
- if (mListener.mInternalListener == null) {
- // This shortcut is needed because otherwise, if there's an error connecting, it never
- // gets delivered. I.e., the onSuccess callback set up in connectToSystemService does
- // not get called, MSG_CHANGE_LISTENER does not get executed, so the onError in the same
- // place does not get forwarded anywhere.
- // Thread-wise, this is safe as both this method and the handler are on the UI thread.
- handleChangeListener(listener);
- } else {
- putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener));
- }
+ throw new UnsupportedOperationException();
}
/**
@@ -576,28 +449,13 @@
* no notifications will be received.
*
* @param recognizerIntent contains parameters for the recognition to be performed. The intent
- * may also contain optional extras, see {@link RecognizerIntent}. If these values are
- * not set explicitly, default values will be used by the recognizer.
+ * may also contain optional extras, see {@link RecognizerIntent}. If
+ * these values are not set explicitly, default values will be used by
+ * the recognizer.
*/
@MainThread
- public void startListening(final Intent recognizerIntent) {
- if (recognizerIntent == null) {
- throw new IllegalArgumentException("intent must not be null");
- }
- checkIsCalledFromMainThread();
-
- if (DBG) {
- Slog.i(TAG, "#startListening called");
- if (mService == null) {
- Slog.i(TAG, "Connection is not established yet");
- }
- }
-
- if (mService == null) {
- // First time connection: first establish a connection, then dispatch #startListening.
- connectToSystemService();
- }
- putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent));
+ public void startListening(Intent recognizerIntent) {
+ throw new UnsupportedOperationException();
}
/**
@@ -621,16 +479,7 @@
*/
@MainThread
public void stopListening() {
- checkIsCalledFromMainThread();
-
- if (DBG) {
- Slog.i(TAG, "#stopListening called");
- if (mService == null) {
- Slog.i(TAG, "Connection is not established yet");
- }
- }
-
- putMessage(Message.obtain(mHandler, MSG_STOP));
+ throw new UnsupportedOperationException();
}
/**
@@ -640,8 +489,7 @@
*/
@MainThread
public void cancel() {
- checkIsCalledFromMainThread();
- putMessage(Message.obtain(mHandler, MSG_CANCEL));
+ throw new UnsupportedOperationException();
}
/**
@@ -649,30 +497,15 @@
* {@link SpeechRecognizer#startListening(Intent)}.
*
* @param recognizerIntent contains parameters for the recognition to be performed. The intent
- * may also contain optional extras. See {@link RecognizerIntent} for the list of
- * supported extras, any unlisted extra might be ignored.
- * @param supportListener the listener on which to receive the support query results.
+ * may also contain optional extras. See {@link RecognizerIntent} for
+ * the list of supported extras, any unlisted extra might be ignored.
+ * @param supportListener the listener on which to receive the support query results.
*/
public void checkRecognitionSupport(
@NonNull Intent recognizerIntent,
@NonNull @CallbackExecutor Executor executor,
@NonNull RecognitionSupportCallback supportListener) {
- Objects.requireNonNull(recognizerIntent, "intent must not be null");
- Objects.requireNonNull(supportListener, "listener must not be null");
-
- if (DBG) {
- Slog.i(TAG, "#checkRecognitionSupport called");
- if (mService == null) {
- Slog.i(TAG, "Connection is not established yet");
- }
- }
-
- if (mService == null) {
- // First time connection: first establish a connection, then dispatch.
- connectToSystemService();
- }
- putMessage(Message.obtain(mHandler, MSG_CHECK_RECOGNITION_SUPPORT,
- new CheckRecognitionSupportArgs(recognizerIntent, executor, supportListener)));
+ throw new UnsupportedOperationException();
}
/**
@@ -681,23 +514,10 @@
* {@link #checkRecognitionSupport(Intent, Executor, RecognitionSupportCallback)}.
*
* @param recognizerIntent contains parameters for the recognition to be performed. The intent
- * may also contain optional extras, see {@link RecognizerIntent}.
+ * may also contain optional extras, see {@link RecognizerIntent}.
*/
public void triggerModelDownload(@NonNull Intent recognizerIntent) {
- Objects.requireNonNull(recognizerIntent, "intent must not be null");
- if (DBG) {
- Slog.i(TAG, "#triggerModelDownload without a listener called");
- if (mService == null) {
- Slog.i(TAG, "Connection is not established yet");
- }
- }
- if (mService == null) {
- // First time connection: first establish a connection, then dispatch.
- connectToSystemService();
- }
- putMessage(Message.obtain(
- mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
- new ModelDownloadListenerArgs(recognizerIntent, null, null)));
+ throw new UnsupportedOperationException();
}
/**
@@ -725,28 +545,15 @@
* {@link ModelDownloadListener#onError(int)} will be called.
*
* @param recognizerIntent contains parameters for the recognition to be performed. The intent
- * may also contain optional extras, see {@link RecognizerIntent}.
- * @param executor for dispatching listener callbacks
- * @param listener on which to receive updates about the model download request.
+ * may also contain optional extras, see {@link RecognizerIntent}.
+ * @param executor for dispatching listener callbacks
+ * @param listener on which to receive updates about the model download request.
*/
public void triggerModelDownload(
@NonNull Intent recognizerIntent,
@NonNull @CallbackExecutor Executor executor,
@NonNull ModelDownloadListener listener) {
- Objects.requireNonNull(recognizerIntent, "intent must not be null");
- if (DBG) {
- Slog.i(TAG, "#triggerModelDownload with a listener called");
- if (mService == null) {
- Slog.i(TAG, "Connection is not established yet");
- }
- }
- if (mService == null) {
- // First time connection: first establish a connection, then dispatch.
- connectToSystemService();
- }
- putMessage(Message.obtain(
- mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
- new ModelDownloadListenerArgs(recognizerIntent, executor, listener)));
+ throw new UnsupportedOperationException();
}
/**
@@ -755,479 +562,19 @@
* <p>This is only expected to be called in tests, system would reject calls from client apps.
*
* @param componentName name of the component to set temporary replace speech recognizer. {@code
- * null} value resets the recognizer to default.
- *
+ * null} value resets the recognizer to default.
* @hide
*/
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_SPEECH_RECOGNITION)
public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) {
- mHandler.sendMessage(
- Message.obtain(mHandler, MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT, componentName));
+ throw new UnsupportedOperationException();
}
- private static void checkIsCalledFromMainThread() {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new RuntimeException(
- "SpeechRecognizer should be used only from the application's main thread");
- }
- }
-
- private void putMessage(Message msg) {
- if (mService == null) {
- mPendingTasks.offer(msg);
- } else {
- mHandler.sendMessage(msg);
- }
- }
-
- /** sends the actual message to the service */
- private void handleStartListening(Intent recognizerIntent) {
- if (!checkOpenConnection()) {
- return;
- }
- try {
- mService.startListening(recognizerIntent, mListener, mContext.getAttributionSource());
- if (DBG) Log.d(TAG, "service start listening command succeeded");
- } catch (final Exception e) {
- Log.e(TAG, "startListening() failed", e);
- mListener.onError(ERROR_CLIENT);
- }
- }
-
- /** sends the actual message to the service */
- private void handleStopMessage() {
- if (!checkOpenConnection()) {
- return;
- }
- try {
- mService.stopListening(mListener);
- if (DBG) Log.d(TAG, "service stop listening command succeeded");
- } catch (final Exception e) {
- Log.e(TAG, "stopListening() failed", e);
- mListener.onError(ERROR_CLIENT);
- }
- }
-
- /** sends the actual message to the service */
- private void handleCancelMessage() {
- if (!checkOpenConnection()) {
- return;
- }
- try {
- mService.cancel(mListener, /*isShutdown*/ false);
- if (DBG) Log.d(TAG, "service cancel command succeeded");
- } catch (final Exception e) {
- Log.e(TAG, "cancel() failed", e);
- mListener.onError(ERROR_CLIENT);
- }
- }
-
- private void handleSetTemporaryComponent(ComponentName componentName) {
- if (DBG) {
- Log.d(TAG, "handleSetTemporaryComponent, componentName=" + componentName);
- }
-
- if (!maybeInitializeManagerService()) {
- return;
- }
-
- try {
- mManagerService.setTemporaryComponent(componentName);
- } catch (final RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- private void handleCheckRecognitionSupport(
- Intent recognizerIntent,
- Executor callbackExecutor,
- RecognitionSupportCallback recognitionSupportCallback) {
- if (!maybeInitializeManagerService() || !checkOpenConnection()) {
- return;
- }
- try {
- mService.checkRecognitionSupport(
- recognizerIntent,
- mContext.getAttributionSource(),
- new InternalSupportCallback(callbackExecutor, recognitionSupportCallback));
- if (DBG) Log.d(TAG, "service support command succeeded");
- } catch (final Exception e) {
- Log.e(TAG, "checkRecognitionSupport() failed", e);
- callbackExecutor.execute(() -> recognitionSupportCallback.onError(ERROR_CLIENT));
- }
- }
-
- private void handleTriggerModelDownload(
- Intent recognizerIntent,
- @Nullable Executor callbackExecutor,
- @Nullable ModelDownloadListener modelDownloadListener) {
- if (!maybeInitializeManagerService() || !checkOpenConnection()) {
- return;
- }
-
- // Trigger model download without a listener.
- if (modelDownloadListener == null) {
- try {
- mService.triggerModelDownload(
- recognizerIntent, mContext.getAttributionSource(), null);
- if (DBG) Log.d(TAG, "triggerModelDownload() without a listener");
- } catch (final Exception e) {
- Log.e(TAG, "triggerModelDownload() without a listener failed", e);
- mListener.onError(ERROR_CLIENT);
- }
- }
- // Trigger model download with a listener.
- else {
- try {
- mService.triggerModelDownload(
- recognizerIntent, mContext.getAttributionSource(),
- new InternalModelDownloadListener(callbackExecutor, modelDownloadListener));
- if (DBG) Log.d(TAG, "triggerModelDownload() with a listener");
- } catch (final Exception e) {
- Log.e(TAG, "triggerModelDownload() with a listener failed", e);
- callbackExecutor.execute(() -> modelDownloadListener.onError(ERROR_CLIENT));
- }
- }
- }
-
- private boolean checkOpenConnection() {
- if (mService != null && mService.asBinder().isBinderAlive()) {
- return true;
- }
- mListener.onError(ERROR_CLIENT);
- Log.e(TAG, "not connected to the recognition service");
- return false;
- }
-
- /** changes the listener */
- private void handleChangeListener(RecognitionListener listener) {
- if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener);
- mListener.mInternalListener = listener;
- }
-
- /** Destroys the {@code SpeechRecognizer} object. */
+ /**
+ * Destroys the {@code SpeechRecognizer} object.
+ */
public void destroy() {
- try {
- if (mService != null) {
- try {
- mService.cancel(mListener, /*isShutdown*/ true);
- } catch (final Exception e) {
- // Not important
- }
- }
-
- mService = null;
- mPendingTasks.clear();
- mListener.mInternalListener = null;
- mCloseGuard.close();
- } finally {
- Reference.reachabilityFence(this);
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- mCloseGuard.warnIfOpen();
- destroy();
- } finally {
- super.finalize();
- }
- }
-
- /** Establishes a connection to system server proxy and initializes the session. */
- private void connectToSystemService() {
- if (!maybeInitializeManagerService()) {
- return;
- }
-
- ComponentName componentName = getSpeechRecognizerComponentName();
-
- if (!mOnDevice && componentName == null) {
- mListener.onError(ERROR_CLIENT);
- return;
- }
-
- try {
- mManagerService.createSession(
- componentName,
- mClientToken,
- mOnDevice,
- new IRecognitionServiceManagerCallback.Stub(){
- @Override
- public void onSuccess(IRecognitionService service) throws RemoteException {
- if (DBG) {
- Log.i(TAG, "Connected to speech recognition service");
- }
- mService = service;
- while (!mPendingTasks.isEmpty()) {
- mHandler.sendMessage(mPendingTasks.poll());
- }
- }
-
- @Override
- public void onError(int errorCode) throws RemoteException {
- Log.e(TAG, "Bind to system recognition service failed with error "
- + errorCode);
- mListener.onError(errorCode);
- }
- });
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- private synchronized boolean maybeInitializeManagerService() {
- if (DBG) {
- Log.i(TAG, "#maybeInitializeManagerService found = " + mManagerService);
- }
- if (mManagerService != null) {
- return true;
- }
-
- IBinder service = ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE);
- if (service == null && mOnDevice) {
- service = (IBinder) mContext.getSystemService(Context.SPEECH_RECOGNITION_SERVICE);
- }
- mManagerService = IRecognitionServiceManager.Stub.asInterface(service);
-
- if (mManagerService == null) {
- if (mListener != null) {
- mListener.onError(ERROR_CLIENT);
- }
- return false;
- }
- return true;
- }
-
- /**
- * Returns the component name to be used for establishing a connection, based on the parameters
- * used during initialization.
- *
- * <p>Note the 3 different scenarios:
- * <ol>
- * <li>On-device speech recognizer which is determined by the manufacturer and not
- * changeable by the user
- * <li>Default user-selected speech recognizer as specified by
- * {@code Settings.Secure.VOICE_RECOGNITION_SERVICE}
- * <li>Custom speech recognizer supplied by the client.
- */
- private ComponentName getSpeechRecognizerComponentName() {
- if (mOnDevice) {
- return null;
- }
-
- if (mServiceComponent != null) {
- return mServiceComponent;
- }
-
- String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.VOICE_RECOGNITION_SERVICE);
-
- if (TextUtils.isEmpty(serviceComponent)) {
- Log.e(TAG, "no selected voice recognition service");
- mListener.onError(ERROR_CLIENT);
- return null;
- }
-
- return ComponentName.unflattenFromString(serviceComponent);
- }
-
- private static class CheckRecognitionSupportArgs {
- final Intent mIntent;
- final Executor mCallbackExecutor;
- final RecognitionSupportCallback mCallback;
-
- private CheckRecognitionSupportArgs(
- Intent intent,
- Executor callbackExecutor,
- RecognitionSupportCallback callback) {
- mIntent = intent;
- mCallbackExecutor = callbackExecutor;
- mCallback = callback;
- }
- }
-
- private static class ModelDownloadListenerArgs {
- final Intent mIntent;
- final Executor mExecutor;
- final ModelDownloadListener mModelDownloadListener;
-
- private ModelDownloadListenerArgs(Intent intent, Executor executor,
- ModelDownloadListener modelDownloadListener) {
- mIntent = intent;
- mExecutor = executor;
- mModelDownloadListener = modelDownloadListener;
- }
- }
-
- /**
- * Internal wrapper of IRecognitionListener which will propagate the results to
- * RecognitionListener
- */
- private static class InternalRecognitionListener extends IRecognitionListener.Stub {
- private RecognitionListener mInternalListener;
-
- private static final int MSG_BEGINNING_OF_SPEECH = 1;
- private static final int MSG_BUFFER_RECEIVED = 2;
- private static final int MSG_END_OF_SPEECH = 3;
- private static final int MSG_ERROR = 4;
- private static final int MSG_READY_FOR_SPEECH = 5;
- private static final int MSG_RESULTS = 6;
- private static final int MSG_PARTIAL_RESULTS = 7;
- private static final int MSG_RMS_CHANGED = 8;
- private static final int MSG_ON_EVENT = 9;
- private static final int MSG_SEGMENT_RESULTS = 10;
- private static final int MSG_SEGMENT_END_SESSION = 11;
- private static final int MSG_LANGUAGE_DETECTION = 12;
-
- private final Handler mInternalHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (mInternalListener == null) {
- return;
- }
- switch (msg.what) {
- case MSG_BEGINNING_OF_SPEECH:
- mInternalListener.onBeginningOfSpeech();
- break;
- case MSG_BUFFER_RECEIVED:
- mInternalListener.onBufferReceived((byte[]) msg.obj);
- break;
- case MSG_END_OF_SPEECH:
- mInternalListener.onEndOfSpeech();
- break;
- case MSG_ERROR:
- mInternalListener.onError((Integer) msg.obj);
- break;
- case MSG_READY_FOR_SPEECH:
- mInternalListener.onReadyForSpeech((Bundle) msg.obj);
- break;
- case MSG_RESULTS:
- mInternalListener.onResults((Bundle) msg.obj);
- break;
- case MSG_PARTIAL_RESULTS:
- mInternalListener.onPartialResults((Bundle) msg.obj);
- break;
- case MSG_RMS_CHANGED:
- mInternalListener.onRmsChanged((Float) msg.obj);
- break;
- case MSG_ON_EVENT:
- mInternalListener.onEvent(msg.arg1, (Bundle) msg.obj);
- break;
- case MSG_SEGMENT_RESULTS:
- mInternalListener.onSegmentResults((Bundle) msg.obj);
- break;
- case MSG_SEGMENT_END_SESSION:
- mInternalListener.onEndOfSegmentedSession();
- break;
- case MSG_LANGUAGE_DETECTION:
- mInternalListener.onLanguageDetection((Bundle) msg.obj);
- break;
- }
- }
- };
-
- public void onBeginningOfSpeech() {
- Message.obtain(mInternalHandler, MSG_BEGINNING_OF_SPEECH).sendToTarget();
- }
-
- public void onBufferReceived(final byte[] buffer) {
- Message.obtain(mInternalHandler, MSG_BUFFER_RECEIVED, buffer).sendToTarget();
- }
-
- public void onEndOfSpeech() {
- Message.obtain(mInternalHandler, MSG_END_OF_SPEECH).sendToTarget();
- }
-
- public void onError(final int error) {
- Message.obtain(mInternalHandler, MSG_ERROR, error).sendToTarget();
- }
-
- public void onReadyForSpeech(final Bundle noiseParams) {
- Message.obtain(mInternalHandler, MSG_READY_FOR_SPEECH, noiseParams).sendToTarget();
- }
-
- public void onResults(final Bundle results) {
- Message.obtain(mInternalHandler, MSG_RESULTS, results).sendToTarget();
- }
-
- public void onPartialResults(final Bundle results) {
- Message.obtain(mInternalHandler, MSG_PARTIAL_RESULTS, results).sendToTarget();
- }
-
- public void onRmsChanged(final float rmsdB) {
- Message.obtain(mInternalHandler, MSG_RMS_CHANGED, rmsdB).sendToTarget();
- }
-
- public void onSegmentResults(final Bundle bundle) {
- Message.obtain(mInternalHandler, MSG_SEGMENT_RESULTS, bundle).sendToTarget();
- }
-
- public void onEndOfSegmentedSession() {
- Message.obtain(mInternalHandler, MSG_SEGMENT_END_SESSION).sendToTarget();
- }
-
- public void onLanguageDetection(final Bundle results) {
- Message.obtain(mInternalHandler, MSG_LANGUAGE_DETECTION, results).sendToTarget();
- }
-
- public void onEvent(final int eventType, final Bundle params) {
- Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
- .sendToTarget();
- }
- }
-
- private static class InternalSupportCallback extends IRecognitionSupportCallback.Stub {
- private final Executor mExecutor;
- private final RecognitionSupportCallback mCallback;
-
- private InternalSupportCallback(Executor executor, RecognitionSupportCallback callback) {
- this.mExecutor = executor;
- this.mCallback = callback;
- }
-
- @Override
- public void onSupportResult(RecognitionSupport recognitionSupport) throws RemoteException {
- mExecutor.execute(() -> mCallback.onSupportResult(recognitionSupport));
- }
-
- @Override
- public void onError(int errorCode) throws RemoteException {
- mExecutor.execute(() -> mCallback.onError(errorCode));
- }
- }
-
- private static class InternalModelDownloadListener extends IModelDownloadListener.Stub {
- private final Executor mExecutor;
- private final ModelDownloadListener mModelDownloadListener;
-
- private InternalModelDownloadListener(
- Executor executor,
- @NonNull ModelDownloadListener modelDownloadListener) {
- mExecutor = executor;
- mModelDownloadListener = modelDownloadListener;
- }
-
- @Override
- public void onProgress(int completedPercent) throws RemoteException {
- mExecutor.execute(() -> mModelDownloadListener.onProgress(completedPercent));
- }
-
- @Override
- public void onSuccess() throws RemoteException {
- mExecutor.execute(() -> mModelDownloadListener.onSuccess());
- }
-
- @Override
- public void onScheduled() throws RemoteException {
- mExecutor.execute(() -> mModelDownloadListener.onScheduled());
- }
-
- @Override
- public void onError(int error) throws RemoteException {
- mExecutor.execute(() -> mModelDownloadListener.onError(error));
- }
+ throw new UnsupportedOperationException();
}
}
diff --git a/core/java/android/speech/SpeechRecognizerImpl.java b/core/java/android/speech/SpeechRecognizerImpl.java
new file mode 100644
index 0000000..6c00874
--- /dev/null
+++ b/core/java/android/speech/SpeechRecognizerImpl.java
@@ -0,0 +1,745 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.speech;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+
+import java.util.Objects;
+import java.util.Queue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * @hide
+ */
+class SpeechRecognizerImpl extends SpeechRecognizer {
+ /** DEBUG value to enable verbose debug prints */
+ private static final boolean DBG = false;
+
+ /** Log messages identifier */
+ private static final String TAG = "SpeechRecognizer";
+
+ /** action codes */
+ private static final int MSG_START = 1;
+ private static final int MSG_STOP = 2;
+ private static final int MSG_CANCEL = 3;
+ private static final int MSG_CHANGE_LISTENER = 4;
+ private static final int MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT = 5;
+ private static final int MSG_CHECK_RECOGNITION_SUPPORT = 6;
+ private static final int MSG_TRIGGER_MODEL_DOWNLOAD = 7;
+
+ /** The actual RecognitionService endpoint */
+ private IRecognitionService mService;
+
+ /** Context with which the manager was created */
+ private final Context mContext;
+
+ /** Component to direct service intent to */
+ private final ComponentName mServiceComponent;
+
+ /** Whether to use on-device speech recognizer. */
+ private final boolean mOnDevice;
+
+ private IRecognitionServiceManager mManagerService;
+
+ /** Handler that will execute the main tasks */
+ private Handler mHandler = new Handler(Looper.getMainLooper()) {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START:
+ handleStartListening((Intent) msg.obj);
+ break;
+ case MSG_STOP:
+ handleStopMessage();
+ break;
+ case MSG_CANCEL:
+ handleCancelMessage();
+ break;
+ case MSG_CHANGE_LISTENER:
+ handleChangeListener((RecognitionListener) msg.obj);
+ break;
+ case MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT:
+ handleSetTemporaryComponent((ComponentName) msg.obj);
+ break;
+ case MSG_CHECK_RECOGNITION_SUPPORT:
+ CheckRecognitionSupportArgs args = (CheckRecognitionSupportArgs) msg.obj;
+ handleCheckRecognitionSupport(
+ args.mIntent, args.mCallbackExecutor, args.mCallback);
+ break;
+ case MSG_TRIGGER_MODEL_DOWNLOAD:
+ ModelDownloadListenerArgs modelDownloadListenerArgs =
+ (ModelDownloadListenerArgs) msg.obj;
+ handleTriggerModelDownload(
+ modelDownloadListenerArgs.mIntent,
+ modelDownloadListenerArgs.mExecutor,
+ modelDownloadListenerArgs.mModelDownloadListener);
+ break;
+ }
+ }
+ };
+
+ /**
+ * Temporary queue, saving the messages until the connection will be established, afterwards,
+ * only mHandler will receive the messages
+ */
+ private final Queue<Message> mPendingTasks = new LinkedBlockingQueue<>();
+
+ /** The Listener that will receive all the callbacks */
+ private final InternalRecognitionListener mListener = new InternalRecognitionListener();
+
+ private final IBinder mClientToken = new Binder();
+
+ /**
+ * The right way to create a {@code SpeechRecognizer} is by using
+ * {@link #createSpeechRecognizer} static factory method
+ */
+ /* package */ SpeechRecognizerImpl(
+ final Context context,
+ final ComponentName serviceComponent) {
+ this(context, serviceComponent, false);
+ }
+
+ /**
+ * The right way to create a {@code SpeechRecognizer} is by using
+ * {@link #createOnDeviceSpeechRecognizer} static factory method
+ */
+ /* package */ SpeechRecognizerImpl(final Context context, boolean onDevice) {
+ this(context, null, onDevice);
+ }
+
+ private SpeechRecognizerImpl(
+ final Context context,
+ final ComponentName serviceComponent,
+ final boolean onDevice) {
+ mContext = context;
+ mServiceComponent = serviceComponent;
+ mOnDevice = onDevice;
+ }
+
+ @NonNull
+ @MainThread
+ /* package */ static SpeechRecognizerImpl lenientlyCreateOnDeviceSpeechRecognizer(
+ @NonNull final Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("Context cannot be null");
+ }
+ checkIsCalledFromMainThread();
+ return new SpeechRecognizerImpl(context, /* onDevice */ true);
+ }
+
+ @Override
+ @MainThread
+ public void setRecognitionListener(RecognitionListener listener) {
+ checkIsCalledFromMainThread();
+ if (mListener.mInternalListener == null) {
+ // This shortcut is needed because otherwise, if there's an error connecting, it never
+ // gets delivered. I.e., the onSuccess callback set up in connectToSystemService does
+ // not get called, MSG_CHANGE_LISTENER does not get executed, so the onError in the same
+ // place does not get forwarded anywhere.
+ // Thread-wise, this is safe as both this method and the handler are on the UI thread.
+ handleChangeListener(listener);
+ } else {
+ putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener));
+ }
+ }
+
+ @Override
+ @MainThread
+ public void startListening(final Intent recognizerIntent) {
+ if (recognizerIntent == null) {
+ throw new IllegalArgumentException("intent must not be null");
+ }
+ checkIsCalledFromMainThread();
+
+ if (DBG) {
+ Slog.i(TAG, "#startListening called");
+ if (mService == null) {
+ Slog.i(TAG, "Connection is not established yet");
+ }
+ }
+
+ if (mService == null) {
+ // First time connection: first establish a connection, then dispatch #startListening.
+ connectToSystemService();
+ }
+ putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent));
+ }
+
+ @Override
+ @MainThread
+ public void stopListening() {
+ checkIsCalledFromMainThread();
+
+ if (DBG) {
+ Slog.i(TAG, "#stopListening called");
+ if (mService == null) {
+ Slog.i(TAG, "Connection is not established yet");
+ }
+ }
+
+ putMessage(Message.obtain(mHandler, MSG_STOP));
+ }
+
+ @Override
+ @MainThread
+ public void cancel() {
+ checkIsCalledFromMainThread();
+ putMessage(Message.obtain(mHandler, MSG_CANCEL));
+ }
+
+ @Override
+ public void checkRecognitionSupport(
+ @NonNull Intent recognizerIntent,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull RecognitionSupportCallback supportListener) {
+ Objects.requireNonNull(recognizerIntent, "intent must not be null");
+ Objects.requireNonNull(supportListener, "listener must not be null");
+
+ if (DBG) {
+ Slog.i(TAG, "#checkRecognitionSupport called");
+ if (mService == null) {
+ Slog.i(TAG, "Connection is not established yet");
+ }
+ }
+
+ if (mService == null) {
+ // First time connection: first establish a connection, then dispatch.
+ connectToSystemService();
+ }
+ putMessage(Message.obtain(mHandler, MSG_CHECK_RECOGNITION_SUPPORT,
+ new CheckRecognitionSupportArgs(recognizerIntent, executor, supportListener)));
+ }
+
+ @Override
+ public void triggerModelDownload(@NonNull Intent recognizerIntent) {
+ Objects.requireNonNull(recognizerIntent, "intent must not be null");
+ if (DBG) {
+ Slog.i(TAG, "#triggerModelDownload without a listener called");
+ if (mService == null) {
+ Slog.i(TAG, "Connection is not established yet");
+ }
+ }
+ if (mService == null) {
+ // First time connection: first establish a connection, then dispatch.
+ connectToSystemService();
+ }
+ putMessage(Message.obtain(
+ mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
+ new ModelDownloadListenerArgs(recognizerIntent, null, null)));
+ }
+
+ @Override
+ public void triggerModelDownload(
+ @NonNull Intent recognizerIntent,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull ModelDownloadListener listener) {
+ Objects.requireNonNull(recognizerIntent, "intent must not be null");
+ if (DBG) {
+ Slog.i(TAG, "#triggerModelDownload with a listener called");
+ if (mService == null) {
+ Slog.i(TAG, "Connection is not established yet");
+ }
+ }
+ if (mService == null) {
+ // First time connection: first establish a connection, then dispatch.
+ connectToSystemService();
+ }
+ putMessage(Message.obtain(
+ mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
+ new ModelDownloadListenerArgs(recognizerIntent, executor, listener)));
+ }
+
+ @Override
+ @RequiresPermission(Manifest.permission.MANAGE_SPEECH_RECOGNITION)
+ public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) {
+ mHandler.sendMessage(
+ Message.obtain(mHandler, MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT, componentName));
+ }
+
+ /* package */ static void checkIsCalledFromMainThread() {
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ throw new RuntimeException(
+ "SpeechRecognizer should be used only from the application's main thread");
+ }
+ }
+
+ private void putMessage(Message msg) {
+ if (mService == null) {
+ mPendingTasks.offer(msg);
+ } else {
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ /** sends the actual message to the service */
+ private void handleStartListening(Intent recognizerIntent) {
+ if (!checkOpenConnection()) {
+ return;
+ }
+ try {
+ mService.startListening(recognizerIntent, mListener, mContext.getAttributionSource());
+ if (DBG) Log.d(TAG, "service start listening command succeeded");
+ } catch (final Exception e) {
+ Log.e(TAG, "startListening() failed", e);
+ mListener.onError(ERROR_CLIENT);
+ }
+ }
+
+ /** sends the actual message to the service */
+ private void handleStopMessage() {
+ if (!checkOpenConnection()) {
+ return;
+ }
+ try {
+ mService.stopListening(mListener);
+ if (DBG) Log.d(TAG, "service stop listening command succeeded");
+ } catch (final Exception e) {
+ Log.e(TAG, "stopListening() failed", e);
+ mListener.onError(ERROR_CLIENT);
+ }
+ }
+
+ /** sends the actual message to the service */
+ private void handleCancelMessage() {
+ if (!checkOpenConnection()) {
+ return;
+ }
+ try {
+ mService.cancel(mListener, /*isShutdown*/ false);
+ if (DBG) Log.d(TAG, "service cancel command succeeded");
+ } catch (final Exception e) {
+ Log.e(TAG, "cancel() failed", e);
+ mListener.onError(ERROR_CLIENT);
+ }
+ }
+
+ private void handleSetTemporaryComponent(ComponentName componentName) {
+ if (DBG) {
+ Log.d(TAG, "handleSetTemporaryComponent, componentName=" + componentName);
+ }
+
+ if (!maybeInitializeManagerService()) {
+ return;
+ }
+
+ try {
+ mManagerService.setTemporaryComponent(componentName);
+ } catch (final RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ private void handleCheckRecognitionSupport(
+ Intent recognizerIntent,
+ Executor callbackExecutor,
+ RecognitionSupportCallback recognitionSupportCallback) {
+ if (!maybeInitializeManagerService() || !checkOpenConnection()) {
+ return;
+ }
+ try {
+ mService.checkRecognitionSupport(
+ recognizerIntent,
+ mContext.getAttributionSource(),
+ new InternalSupportCallback(callbackExecutor, recognitionSupportCallback));
+ if (DBG) Log.d(TAG, "service support command succeeded");
+ } catch (final Exception e) {
+ Log.e(TAG, "checkRecognitionSupport() failed", e);
+ callbackExecutor.execute(() -> recognitionSupportCallback.onError(ERROR_CLIENT));
+ }
+ }
+
+ private void handleTriggerModelDownload(
+ Intent recognizerIntent,
+ @Nullable Executor callbackExecutor,
+ @Nullable ModelDownloadListener modelDownloadListener) {
+ if (!maybeInitializeManagerService() || !checkOpenConnection()) {
+ return;
+ }
+
+ if (modelDownloadListener == null) {
+ // Trigger model download without a listener.
+ try {
+ mService.triggerModelDownload(
+ recognizerIntent, mContext.getAttributionSource(), null);
+ if (DBG) Log.d(TAG, "triggerModelDownload() without a listener");
+ } catch (final Exception e) {
+ Log.e(TAG, "triggerModelDownload() without a listener failed", e);
+ mListener.onError(ERROR_CLIENT);
+ }
+ } else {
+ // Trigger model download with a listener.
+ try {
+ mService.triggerModelDownload(
+ recognizerIntent, mContext.getAttributionSource(),
+ new InternalModelDownloadListener(callbackExecutor, modelDownloadListener));
+ if (DBG) Log.d(TAG, "triggerModelDownload() with a listener");
+ } catch (final Exception e) {
+ Log.e(TAG, "triggerModelDownload() with a listener failed", e);
+ callbackExecutor.execute(() -> modelDownloadListener.onError(ERROR_CLIENT));
+ }
+ }
+ }
+
+ private boolean checkOpenConnection() {
+ if (mService != null && mService.asBinder().isBinderAlive()) {
+ return true;
+ }
+ mListener.onError(ERROR_CLIENT);
+ Log.e(TAG, "not connected to the recognition service");
+ return false;
+ }
+
+ /** changes the listener */
+ private void handleChangeListener(RecognitionListener listener) {
+ if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener);
+ mListener.mInternalListener = listener;
+ }
+
+ @Override
+ public void destroy() {
+ if (mService != null) {
+ try {
+ mService.cancel(mListener, /*isShutdown*/ true);
+ } catch (final Exception e) {
+ // Not important
+ }
+ }
+
+ mService = null;
+ mPendingTasks.clear();
+ mListener.mInternalListener = null;
+ }
+
+ /** Establishes a connection to system server proxy and initializes the session. */
+ private void connectToSystemService() {
+ if (!maybeInitializeManagerService()) {
+ return;
+ }
+
+ ComponentName componentName = getSpeechRecognizerComponentName();
+
+ if (!mOnDevice && componentName == null) {
+ mListener.onError(ERROR_CLIENT);
+ return;
+ }
+
+ try {
+ mManagerService.createSession(
+ componentName,
+ mClientToken,
+ mOnDevice,
+ new IRecognitionServiceManagerCallback.Stub(){
+ @Override
+ public void onSuccess(IRecognitionService service) throws RemoteException {
+ if (DBG) {
+ Log.i(TAG, "Connected to speech recognition service");
+ }
+ mService = service;
+ while (!mPendingTasks.isEmpty()) {
+ mHandler.sendMessage(mPendingTasks.poll());
+ }
+ }
+
+ @Override
+ public void onError(int errorCode) throws RemoteException {
+ Log.e(TAG, "Bind to system recognition service failed with error "
+ + errorCode);
+ mListener.onError(errorCode);
+ }
+ });
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ private synchronized boolean maybeInitializeManagerService() {
+ if (DBG) {
+ Log.i(TAG, "#maybeInitializeManagerService found = " + mManagerService);
+ }
+ if (mManagerService != null) {
+ return true;
+ }
+
+ IBinder service = ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE);
+ if (service == null && mOnDevice) {
+ service = (IBinder) mContext.getSystemService(Context.SPEECH_RECOGNITION_SERVICE);
+ }
+ mManagerService = IRecognitionServiceManager.Stub.asInterface(service);
+
+ if (mManagerService == null) {
+ if (mListener != null) {
+ mListener.onError(ERROR_CLIENT);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the component name to be used for establishing a connection, based on the parameters
+ * used during initialization.
+ *
+ * <p>Note the 3 different scenarios:
+ * <ol>
+ * <li>On-device speech recognizer which is determined by the manufacturer and not
+ * changeable by the user
+ * <li>Default user-selected speech recognizer as specified by
+ * {@code Settings.Secure.VOICE_RECOGNITION_SERVICE}
+ * <li>Custom speech recognizer supplied by the client.
+ * </ol>
+ */
+ @SuppressWarnings("NonUserGetterCalled")
+ private ComponentName getSpeechRecognizerComponentName() {
+ if (mOnDevice) {
+ return null;
+ }
+
+ if (mServiceComponent != null) {
+ return mServiceComponent;
+ }
+
+ String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.VOICE_RECOGNITION_SERVICE);
+
+ if (TextUtils.isEmpty(serviceComponent)) {
+ Log.e(TAG, "no selected voice recognition service");
+ mListener.onError(ERROR_CLIENT);
+ return null;
+ }
+
+ return ComponentName.unflattenFromString(serviceComponent);
+ }
+
+ private static class CheckRecognitionSupportArgs {
+ final Intent mIntent;
+ final Executor mCallbackExecutor;
+ final RecognitionSupportCallback mCallback;
+
+ private CheckRecognitionSupportArgs(
+ Intent intent,
+ Executor callbackExecutor,
+ RecognitionSupportCallback callback) {
+ mIntent = intent;
+ mCallbackExecutor = callbackExecutor;
+ mCallback = callback;
+ }
+ }
+
+ private static class ModelDownloadListenerArgs {
+ final Intent mIntent;
+ final Executor mExecutor;
+ final ModelDownloadListener mModelDownloadListener;
+
+ private ModelDownloadListenerArgs(Intent intent, Executor executor,
+ ModelDownloadListener modelDownloadListener) {
+ mIntent = intent;
+ mExecutor = executor;
+ mModelDownloadListener = modelDownloadListener;
+ }
+ }
+
+ /**
+ * Internal wrapper of IRecognitionListener which will propagate the results to
+ * RecognitionListener
+ */
+ private static class InternalRecognitionListener extends IRecognitionListener.Stub {
+ private RecognitionListener mInternalListener;
+
+ private static final int MSG_BEGINNING_OF_SPEECH = 1;
+ private static final int MSG_BUFFER_RECEIVED = 2;
+ private static final int MSG_END_OF_SPEECH = 3;
+ private static final int MSG_ERROR = 4;
+ private static final int MSG_READY_FOR_SPEECH = 5;
+ private static final int MSG_RESULTS = 6;
+ private static final int MSG_PARTIAL_RESULTS = 7;
+ private static final int MSG_RMS_CHANGED = 8;
+ private static final int MSG_ON_EVENT = 9;
+ private static final int MSG_SEGMENT_RESULTS = 10;
+ private static final int MSG_SEGMENT_END_SESSION = 11;
+ private static final int MSG_LANGUAGE_DETECTION = 12;
+
+ private final Handler mInternalHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (mInternalListener == null) {
+ return;
+ }
+ switch (msg.what) {
+ case MSG_BEGINNING_OF_SPEECH:
+ mInternalListener.onBeginningOfSpeech();
+ break;
+ case MSG_BUFFER_RECEIVED:
+ mInternalListener.onBufferReceived((byte[]) msg.obj);
+ break;
+ case MSG_END_OF_SPEECH:
+ mInternalListener.onEndOfSpeech();
+ break;
+ case MSG_ERROR:
+ mInternalListener.onError((Integer) msg.obj);
+ break;
+ case MSG_READY_FOR_SPEECH:
+ mInternalListener.onReadyForSpeech((Bundle) msg.obj);
+ break;
+ case MSG_RESULTS:
+ mInternalListener.onResults((Bundle) msg.obj);
+ break;
+ case MSG_PARTIAL_RESULTS:
+ mInternalListener.onPartialResults((Bundle) msg.obj);
+ break;
+ case MSG_RMS_CHANGED:
+ mInternalListener.onRmsChanged((Float) msg.obj);
+ break;
+ case MSG_ON_EVENT:
+ mInternalListener.onEvent(msg.arg1, (Bundle) msg.obj);
+ break;
+ case MSG_SEGMENT_RESULTS:
+ mInternalListener.onSegmentResults((Bundle) msg.obj);
+ break;
+ case MSG_SEGMENT_END_SESSION:
+ mInternalListener.onEndOfSegmentedSession();
+ break;
+ case MSG_LANGUAGE_DETECTION:
+ mInternalListener.onLanguageDetection((Bundle) msg.obj);
+ break;
+ }
+ }
+ };
+
+ public void onBeginningOfSpeech() {
+ Message.obtain(mInternalHandler, MSG_BEGINNING_OF_SPEECH).sendToTarget();
+ }
+
+ public void onBufferReceived(final byte[] buffer) {
+ Message.obtain(mInternalHandler, MSG_BUFFER_RECEIVED, buffer).sendToTarget();
+ }
+
+ public void onEndOfSpeech() {
+ Message.obtain(mInternalHandler, MSG_END_OF_SPEECH).sendToTarget();
+ }
+
+ public void onError(final int error) {
+ Message.obtain(mInternalHandler, MSG_ERROR, error).sendToTarget();
+ }
+
+ public void onReadyForSpeech(final Bundle noiseParams) {
+ Message.obtain(mInternalHandler, MSG_READY_FOR_SPEECH, noiseParams).sendToTarget();
+ }
+
+ public void onResults(final Bundle results) {
+ Message.obtain(mInternalHandler, MSG_RESULTS, results).sendToTarget();
+ }
+
+ public void onPartialResults(final Bundle results) {
+ Message.obtain(mInternalHandler, MSG_PARTIAL_RESULTS, results).sendToTarget();
+ }
+
+ public void onRmsChanged(final float rmsdB) {
+ Message.obtain(mInternalHandler, MSG_RMS_CHANGED, rmsdB).sendToTarget();
+ }
+
+ public void onSegmentResults(final Bundle bundle) {
+ Message.obtain(mInternalHandler, MSG_SEGMENT_RESULTS, bundle).sendToTarget();
+ }
+
+ public void onEndOfSegmentedSession() {
+ Message.obtain(mInternalHandler, MSG_SEGMENT_END_SESSION).sendToTarget();
+ }
+
+ public void onLanguageDetection(final Bundle results) {
+ Message.obtain(mInternalHandler, MSG_LANGUAGE_DETECTION, results).sendToTarget();
+ }
+
+ public void onEvent(final int eventType, final Bundle params) {
+ Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
+ .sendToTarget();
+ }
+ }
+
+ private static class InternalSupportCallback extends IRecognitionSupportCallback.Stub {
+ private final Executor mExecutor;
+ private final RecognitionSupportCallback mCallback;
+
+ private InternalSupportCallback(Executor executor, RecognitionSupportCallback callback) {
+ this.mExecutor = executor;
+ this.mCallback = callback;
+ }
+
+ @Override
+ public void onSupportResult(RecognitionSupport recognitionSupport) throws RemoteException {
+ mExecutor.execute(() -> mCallback.onSupportResult(recognitionSupport));
+ }
+
+ @Override
+ public void onError(int errorCode) throws RemoteException {
+ mExecutor.execute(() -> mCallback.onError(errorCode));
+ }
+ }
+
+ private static class InternalModelDownloadListener extends IModelDownloadListener.Stub {
+ private final Executor mExecutor;
+ private final ModelDownloadListener mModelDownloadListener;
+
+ private InternalModelDownloadListener(
+ Executor executor,
+ @NonNull ModelDownloadListener modelDownloadListener) {
+ mExecutor = executor;
+ mModelDownloadListener = modelDownloadListener;
+ }
+
+ @Override
+ public void onProgress(int completedPercent) throws RemoteException {
+ mExecutor.execute(() -> mModelDownloadListener.onProgress(completedPercent));
+ }
+
+ @Override
+ public void onSuccess() throws RemoteException {
+ mExecutor.execute(() -> mModelDownloadListener.onSuccess());
+ }
+
+ @Override
+ public void onScheduled() throws RemoteException {
+ mExecutor.execute(() -> mModelDownloadListener.onScheduled());
+ }
+
+ @Override
+ public void onError(int error) throws RemoteException {
+ mExecutor.execute(() -> mModelDownloadListener.onError(error));
+ }
+ }
+}
diff --git a/core/java/android/speech/SpeechRecognizerProxy.java b/core/java/android/speech/SpeechRecognizerProxy.java
new file mode 100644
index 0000000..be9be9a
--- /dev/null
+++ b/core/java/android/speech/SpeechRecognizerProxy.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.speech;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.util.CloseGuard;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.lang.ref.Reference;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+class SpeechRecognizerProxy extends SpeechRecognizer {
+
+ private final CloseGuard mCloseGuard = new CloseGuard();
+
+ private final SpeechRecognizer mDelegate;
+
+ SpeechRecognizerProxy(final SpeechRecognizer delegate) {
+ mDelegate = delegate;
+ mCloseGuard.open("SpeechRecognizer#destroy()");
+ }
+
+ @Override
+ public void setRecognitionListener(RecognitionListener listener) {
+ mDelegate.setRecognitionListener(listener);
+ }
+
+ @Override
+ public void startListening(Intent recognizerIntent) {
+ mDelegate.startListening(recognizerIntent);
+ }
+
+ @Override
+ public void stopListening() {
+ mDelegate.stopListening();
+ }
+
+ @Override
+ public void cancel() {
+ mDelegate.cancel();
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ mCloseGuard.close();
+ mDelegate.destroy();
+ } finally {
+ Reference.reachabilityFence(this);
+ }
+ }
+
+ @Override
+ public void checkRecognitionSupport(
+ @NonNull Intent recognizerIntent,
+ @NonNull Executor executor,
+ @NonNull RecognitionSupportCallback supportListener) {
+ mDelegate.checkRecognitionSupport(recognizerIntent, executor, supportListener);
+ }
+
+ @Override
+ public void triggerModelDownload(@NonNull Intent recognizerIntent) {
+ mDelegate.triggerModelDownload(recognizerIntent);
+ }
+
+ @Override
+ public void triggerModelDownload(
+ @NonNull Intent recognizerIntent,
+ @NonNull Executor executor,
+ @NonNull ModelDownloadListener listener) {
+ mDelegate.triggerModelDownload(recognizerIntent, executor, listener);
+ }
+
+ @Override
+ public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) {
+ mDelegate.setTemporaryOnDeviceRecognizer(componentName);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 47c29d9..89aceb9 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -3913,7 +3913,6 @@
* @see Layout.Builder
*/
@NonNull
- @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
public final CharSequence getText() {
return mText;
}
diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS
index 079d4c5..2ebe2e9 100644
--- a/core/java/android/tracing/OWNERS
+++ b/core/java/android/tracing/OWNERS
@@ -1,3 +1,6 @@
carmenjackson@google.com
kevinjeon@google.com
+pablogamito@google.com
+natanieljr@google.com
+keanmariotti@google.com
include platform/external/perfetto:/OWNERS
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index 4b4f6d6..c6e8844 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -5,4 +5,11 @@
namespace: "windowing_tools"
description: "Move transition tracing to Perfetto"
bug: "309630341"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "perfetto_protolog"
+ namespace: "windowing_tools"
+ description: "Migrate protolog to Perfetto"
+ bug: "276432490"
+}
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index fd5517d..f28574e 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -27,9 +27,6 @@
import com.android.window.flags.Flags;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-
/**
* Provides an interface to the root-Surface of a View Hierarchy or Window. This
* is used in combination with the {@link android.view.SurfaceControl} API to enable
@@ -197,42 +194,6 @@
}
/**
- * Add a trusted presentation listener on the SurfaceControl associated with this window.
- *
- * @param t Transaction that the trusted presentation listener is added on. This should
- * be applied by the caller.
- * @param thresholds The {@link SurfaceControl.TrustedPresentationThresholds} that will specify
- * when the to invoke the callback.
- * @param executor The {@link Executor} where the callback will be invoked on.
- * @param listener The {@link Consumer} that will receive the callbacks when entered or
- * exited the threshold.
- *
- * @see SurfaceControl.Transaction#setTrustedPresentationCallback(SurfaceControl,
- * SurfaceControl.TrustedPresentationThresholds, Executor, Consumer)
- *
- * @hide b/287076178 un-hide with API bump
- */
- default void addTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
- @NonNull SurfaceControl.TrustedPresentationThresholds thresholds,
- @NonNull Executor executor, @NonNull Consumer<Boolean> listener) {
- }
-
- /**
- * Remove a trusted presentation listener on the SurfaceControl associated with this window.
- *
- * @param t Transaction that the trusted presentation listener removed on. This should
- * be applied by the caller.
- * @param listener The {@link Consumer} that was previously registered with
- * addTrustedPresentationCallback that should be removed.
- *
- * @see SurfaceControl.Transaction#clearTrustedPresentationCallback(SurfaceControl)
- * @hide b/287076178 un-hide with API bump
- */
- default void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
- @NonNull Consumer<Boolean> listener) {
- }
-
- /**
* Transfer the currently in progress touch gesture from the host to the requested
* {@link SurfaceControlViewHost.SurfacePackage}. This requires that the
* SurfaceControlViewHost was created with the current host's inputToken.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 17bbee6d0..36b74e3 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -73,6 +73,8 @@
import android.window.ITaskFpsCallback;
import android.window.ScreenCapture;
import android.window.WindowContextInfo;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
/**
* System private interface to the window manager.
@@ -1075,4 +1077,10 @@
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MONITOR_INPUT)")
void unregisterDecorViewGestureListener(IDecorViewGestureListener listener, int displayId);
+
+ void registerTrustedPresentationListener(in IBinder window, in ITrustedPresentationListener listener,
+ in TrustedPresentationThresholds thresholds, int id);
+
+
+ void unregisterTrustedPresentationListener(in ITrustedPresentationListener listener, int id);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9d2ab1f..d27f787 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -123,6 +123,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.database.ContentObserver;
import android.graphics.BLASTBufferQueue;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -392,6 +393,9 @@
*/
private CompatOnBackInvokedCallback mCompatOnBackInvokedCallback;
+ @Nullable
+ private ContentObserver mForceInvertObserver;
+
/**
* Callback for notifying about global configuration changes.
*/
@@ -1597,6 +1601,24 @@
| DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED,
mBasePackageName);
+
+ if (forceInvertColor()) {
+ if (mForceInvertObserver == null) {
+ mForceInvertObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateForceDarkMode();
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED
+ ),
+ false,
+ mForceInvertObserver,
+ UserHandle.myUserId());
+ }
+ }
}
/**
@@ -1610,6 +1632,14 @@
DisplayManagerGlobal
.getInstance()
.unregisterDisplayListener(mDisplayListener);
+
+ if (forceInvertColor()) {
+ if (mForceInvertObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mForceInvertObserver);
+ mForceInvertObserver = null;
+ }
+ }
+
if (mExtraDisplayListenerLogging) {
Slog.w(mTag, "Unregister listeners: " + mBasePackageName, new Throwable());
}
@@ -2182,8 +2212,14 @@
}
}
- void notifyInsetsAnimationRunningStateChanged(boolean running) {
- mInsetsAnimationRunning = running;
+ /**
+ * Notify the when the running state of a insets animation changed.
+ */
+ @VisibleForTesting
+ public void notifyInsetsAnimationRunningStateChanged(boolean running) {
+ if (sToolkitSetFrameRateReadOnlyFlagValue) {
+ mInsetsAnimationRunning = running;
+ }
}
@Override
@@ -2443,6 +2479,19 @@
if (updateBoundsLayer(t)) {
applyTransactionOnDraw(t);
}
+
+ // Set the frame rate selection strategy to FRAME_RATE_SELECTION_STRATEGY_SELF
+ // This strategy ensures that the frame rate specifications do not cascade down to
+ // the descendant layers. This is particularly important for applications like Chrome,
+ // where child surfaces should adhere to default behavior instead of no preference
+ if (sToolkitSetFrameRateReadOnlyFlagValue) {
+ try {
+ mFrameRateTransaction.setFrameRateSelectionStrategy(sc,
+ sc.FRAME_RATE_SELECTION_STRATEGY_SELF).applyAsyncUnsafe();
+ } catch (Exception e) {
+ Log.e(mTag, "Unable to set frame rate selection strategy ", e);
+ }
+ }
}
private void destroySurface() {
@@ -11924,18 +11973,6 @@
scheduleTraversals();
}
- @Override
- public void addTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
- @NonNull SurfaceControl.TrustedPresentationThresholds thresholds,
- @NonNull Executor executor, @NonNull Consumer<Boolean> listener) {
- t.setTrustedPresentationCallback(getSurfaceControl(), thresholds, executor, listener);
- }
-
- @Override
- public void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
- @NonNull Consumer<Boolean> listener) {
- t.clearTrustedPresentationCallback(getSurfaceControl());
- }
private void logAndTrace(String msg) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
@@ -11949,7 +11986,7 @@
return;
}
- int frameRateCategory = mIsFrameRateBoosting
+ int frameRateCategory = mIsFrameRateBoosting || mInsetsAnimationRunning
? FRAME_RATE_CATEGORY_HIGH : preferredFrameRateCategory;
try {
@@ -12063,6 +12100,14 @@
}
/**
+ * Get the value of mLastPreferredFrameRateCategory
+ */
+ @VisibleForTesting
+ public int getLastPreferredFrameRateCategory() {
+ return mLastPreferredFrameRateCategory;
+ }
+
+ /**
* Get the value of mPreferredFrameRate
*/
@VisibleForTesting
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 046ea77..f668088 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -122,7 +122,9 @@
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.window.ITrustedPresentationListener;
import android.window.TaskFpsCallback;
+import android.window.TrustedPresentationThresholds;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -5884,4 +5886,35 @@
default boolean replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * Add a trusted presentation listener associated with a window. If the listener has already
+ * been registered, an AndroidRuntimeException will be thrown.
+ *
+ * @param window The Window to add the trusted presentation listener for
+ * @param thresholds The {@link TrustedPresentationThresholds} that will specify
+ * when the to invoke the callback.
+ * @param executor The {@link Executor} where the callback will be invoked on.
+ * @param listener The {@link ITrustedPresentationListener} that will receive the callbacks
+ * when entered or exited trusted presentation per the thresholds.
+ *
+ * @hide b/287076178 un-hide with API bump
+ */
+ default void registerTrustedPresentationListener(@NonNull IBinder window,
+ @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor,
+ @NonNull Consumer<Boolean> listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Removes a presentation listener associated with a window. If the listener was not previously
+ * registered, the call will be a noop.
+ *
+ * @hide
+ * @see #registerTrustedPresentationListener(IBinder,
+ * TrustedPresentationThresholds, Executor, Consumer)
+ */
+ default void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 214f1ec..a7d814e 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -30,9 +30,13 @@
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.view.inputmethod.InputMethodManager;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
import com.android.internal.util.FastPrintWriter;
@@ -43,6 +47,7 @@
import java.util.ArrayList;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
import java.util.function.IntConsumer;
/**
@@ -143,6 +148,9 @@
private Runnable mSystemPropertyUpdater;
+ private final TrustedPresentationListener mTrustedPresentationListener =
+ new TrustedPresentationListener();
+
private WindowManagerGlobal() {
}
@@ -324,7 +332,7 @@
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
- & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+ & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
@@ -482,7 +490,7 @@
if (who != null) {
WindowLeaked leak = new WindowLeaked(
what + " " + who + " has leaked window "
- + root.getView() + " that was originally added here");
+ + root.getView() + " that was originally added here");
leak.setStackTrace(root.getLocation().getStackTrace());
Log.e(TAG, "", leak);
}
@@ -790,6 +798,86 @@
}
}
+ public void registerTrustedPresentationListener(@NonNull IBinder window,
+ @NonNull TrustedPresentationThresholds thresholds, Executor executor,
+ @NonNull Consumer<Boolean> listener) {
+ mTrustedPresentationListener.addListener(window, thresholds, listener, executor);
+ }
+
+ public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+ mTrustedPresentationListener.removeListener(listener);
+ }
+
+ private final class TrustedPresentationListener extends
+ ITrustedPresentationListener.Stub {
+ private static int sId = 0;
+ private final ArrayMap<Consumer<Boolean>, Pair<Integer, Executor>> mListeners =
+ new ArrayMap<>();
+
+ private final Object mTplLock = new Object();
+
+ private void addListener(IBinder window, TrustedPresentationThresholds thresholds,
+ Consumer<Boolean> listener, Executor executor) {
+ synchronized (mTplLock) {
+ if (mListeners.containsKey(listener)) {
+ throw new AndroidRuntimeException("Trying to add duplicate listener");
+ }
+ int id = sId++;
+ mListeners.put(listener, new Pair<>(id, executor));
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .registerTrustedPresentationListener(window, this, thresholds, id);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+ }
+
+ private void removeListener(Consumer<Boolean> listener) {
+ synchronized (mTplLock) {
+ var removedListener = mListeners.remove(listener);
+ if (removedListener == null) {
+ Log.i(TAG, "listener " + listener + " does not exist.");
+ return;
+ }
+
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .unregisterTrustedPresentationListener(this, removedListener.first);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+ }
+
+ @Override
+ public void onTrustedPresentationChanged(int[] inTrustedStateListenerIds,
+ int[] outOfTrustedStateListenerIds) {
+ ArrayList<Runnable> firedListeners = new ArrayList<>();
+ synchronized (mTplLock) {
+ mListeners.forEach((listener, idExecutorPair) -> {
+ final var listenerId = idExecutorPair.first;
+ final var executor = idExecutorPair.second;
+ for (int id : inTrustedStateListenerIds) {
+ if (listenerId == id) {
+ firedListeners.add(() -> executor.execute(
+ () -> listener.accept(/*presentationState*/true)));
+ }
+ }
+ for (int id : outOfTrustedStateListenerIds) {
+ if (listenerId == id) {
+ firedListeners.add(() -> executor.execute(
+ () -> listener.accept(/*presentationState*/false)));
+ }
+ }
+ });
+ }
+ for (int i = 0; i < firedListeners.size(); i++) {
+ firedListeners.get(i).run();
+ }
+ }
+ }
+
/** @hide */
public void addWindowlessRoot(ViewRootImpl impl) {
synchronized (mLock) {
@@ -801,7 +889,7 @@
public void removeWindowlessRoot(ViewRootImpl impl) {
synchronized (mLock) {
mWindowlessRoots.remove(impl);
- }
+ }
}
public void setRecentsAppBehindSystemBars(boolean behindSystemBars) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d7b74b3..b4b1fde 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -37,6 +37,7 @@
import android.util.Log;
import android.window.ITaskFpsCallback;
import android.window.TaskFpsCallback;
+import android.window.TrustedPresentationThresholds;
import android.window.WindowContext;
import android.window.WindowMetricsController;
import android.window.WindowProvider;
@@ -508,4 +509,17 @@
}
return false;
}
+
+ @Override
+ public void registerTrustedPresentationListener(@NonNull IBinder window,
+ @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor,
+ @NonNull Consumer<Boolean> listener) {
+ mGlobal.registerTrustedPresentationListener(window, thresholds, executor, listener);
+ }
+
+ @Override
+ public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+ mGlobal.unregisterTrustedPresentationListener(listener);
+
+ }
}
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index aa4275d6..b299678 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -34,7 +34,7 @@
namespace: "accessibility"
name: "flash_notification_system_api"
description: "Makes flash notification APIs as system APIs for calling from mainline module"
- bug: "282821643"
+ bug: "303131332"
}
flag {
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 6884e63..6963237 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -91,7 +91,6 @@
private final WeakReference<Context> mContext;
private final Resources mResources;
- private final WeakReference<WindowManager> mWindowManager;
private final IAccessibilityManager mAccessibilityManagerService;
private final INotificationManager mNotificationManager;
private final String mPackageName;
@@ -104,7 +103,6 @@
INotificationManager notificationManager, String packageName) {
mContext = new WeakReference<>(context);
mResources = context.getResources();
- mWindowManager = new WeakReference<>(context.getSystemService(WindowManager.class));
mNotificationManager = notificationManager;
mPackageName = packageName;
mContextPackageName = context.getPackageName();
@@ -274,7 +272,7 @@
public void hide(@Nullable ITransientNotificationCallback callback) {
checkState(mView != null, "No toast to hide.");
- final WindowManager windowManager = mWindowManager.get();
+ final WindowManager windowManager = getWindowManager(mView);
if (mView.getParent() != null && windowManager != null) {
windowManager.removeViewImmediate(mView);
}
@@ -295,6 +293,17 @@
mToken = null;
}
+ private WindowManager getWindowManager(View view) {
+ Context context = mContext.get();
+ if (context == null && view != null) {
+ context = view.getContext();
+ }
+ if (context != null) {
+ return context.getSystemService(WindowManager.class);
+ }
+ return null;
+ }
+
/**
* Sends {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} event if accessibility is
* enabled.
@@ -331,7 +340,7 @@
}
private void addToastView() {
- final WindowManager windowManager = mWindowManager.get();
+ final WindowManager windowManager = getWindowManager(mView);
if (windowManager == null) {
return;
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/core/java/android/window/ITrustedPresentationListener.aidl
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to core/java/android/window/ITrustedPresentationListener.aidl
index 4098987..b33128a 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/core/java/android/window/ITrustedPresentationListener.aidl
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package android.window;
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
-
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+/**
+ * @hide
+ */
+oneway interface ITrustedPresentationListener {
+ void onTrustedPresentationChanged(in int[] enteredTrustedStateIds, in int[] exitedTrustedStateIds);
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/core/java/android/window/TrustedPresentationListener.java
similarity index 62%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to core/java/android/window/TrustedPresentationListener.java
index 4098987..02fd6d9 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/core/java/android/window/TrustedPresentationListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright 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.
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package android.window;
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+/**
+ * @hide
+ */
+public interface TrustedPresentationListener {
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+ void onTrustedPresentationChanged(boolean inTrustedPresentationState);
+
+}
diff --git a/core/java/android/window/TrustedPresentationThresholds.aidl b/core/java/android/window/TrustedPresentationThresholds.aidl
new file mode 100644
index 0000000..d7088bf
--- /dev/null
+++ b/core/java/android/window/TrustedPresentationThresholds.aidl
@@ -0,0 +1,3 @@
+package android.window;
+
+parcelable TrustedPresentationThresholds;
diff --git a/core/java/android/window/TrustedPresentationThresholds.java b/core/java/android/window/TrustedPresentationThresholds.java
new file mode 100644
index 0000000..801d35c
--- /dev/null
+++ b/core/java/android/window/TrustedPresentationThresholds.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 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.window;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.SurfaceControl;
+
+import androidx.annotation.NonNull;
+
+/**
+ * @hide
+ */
+public final class TrustedPresentationThresholds implements Parcelable {
+ /**
+ * The min alpha the {@link SurfaceControl} is required to have to be considered inside the
+ * threshold.
+ */
+ @FloatRange(from = 0f, fromInclusive = false, to = 1f)
+ public final float mMinAlpha;
+
+ /**
+ * The min fraction of the SurfaceControl that was presented to the user to be considered
+ * inside the threshold.
+ */
+ @FloatRange(from = 0f, fromInclusive = false, to = 1f)
+ public final float mMinFractionRendered;
+
+ /**
+ * The time in milliseconds required for the {@link SurfaceControl} to be in the threshold.
+ */
+ @IntRange(from = 1)
+ public final int mStabilityRequirementMs;
+
+ private void checkValid() {
+ if (mMinAlpha <= 0 || mMinFractionRendered <= 0 || mStabilityRequirementMs < 1) {
+ throw new IllegalArgumentException(
+ "TrustedPresentationThresholds values are invalid");
+ }
+ }
+
+ /**
+ * Creates a new TrustedPresentationThresholds.
+ *
+ * @param minAlpha The min alpha the {@link SurfaceControl} is required to
+ * have to be considered inside the
+ * threshold.
+ * @param minFractionRendered The min fraction of the SurfaceControl that was presented
+ * to the user to be considered
+ * inside the threshold.
+ * @param stabilityRequirementMs The time in milliseconds required for the
+ * {@link SurfaceControl} to be in the threshold.
+ */
+ public TrustedPresentationThresholds(
+ @FloatRange(from = 0f, fromInclusive = false, to = 1f) float minAlpha,
+ @FloatRange(from = 0f, fromInclusive = false, to = 1f) float minFractionRendered,
+ @IntRange(from = 1) int stabilityRequirementMs) {
+ this.mMinAlpha = minAlpha;
+ this.mMinFractionRendered = minFractionRendered;
+ this.mStabilityRequirementMs = stabilityRequirementMs;
+ checkValid();
+ }
+
+ @Override
+ public String toString() {
+ return "TrustedPresentationThresholds { "
+ + "minAlpha = " + mMinAlpha + ", "
+ + "minFractionRendered = " + mMinFractionRendered + ", "
+ + "stabilityRequirementMs = " + mStabilityRequirementMs
+ + " }";
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeFloat(mMinAlpha);
+ dest.writeFloat(mMinFractionRendered);
+ dest.writeInt(mStabilityRequirementMs);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * @hide
+ */
+ TrustedPresentationThresholds(@NonNull Parcel in) {
+ mMinAlpha = in.readFloat();
+ mMinFractionRendered = in.readFloat();
+ mStabilityRequirementMs = in.readInt();
+
+ checkValid();
+ }
+
+ /**
+ * @hide
+ */
+ public static final @NonNull Creator<TrustedPresentationThresholds> CREATOR =
+ new Creator<TrustedPresentationThresholds>() {
+ @Override
+ public TrustedPresentationThresholds[] newArray(int size) {
+ return new TrustedPresentationThresholds[size];
+ }
+
+ @Override
+ public TrustedPresentationThresholds createFromParcel(@NonNull Parcel in) {
+ return new TrustedPresentationThresholds(in);
+ }
+ };
+}
diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
index 9fe30df..727bff4 100644
--- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
+++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
@@ -14,4 +14,12 @@
description: "Make it possible to move cutout across edges through device config"
bug: "302387383"
is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+ name: "density_390_api"
+ namespace: "large_screen_experiences_app_compat"
+ description: "Whether the API DisplayMetrics.DENSITY_390 is available"
+ bug: "297550533"
+ is_fixed_read_only: true
+}
diff --git a/core/java/com/android/internal/app/NfcResolverActivity.java b/core/java/com/android/internal/app/NfcResolverActivity.java
new file mode 100644
index 0000000..402192a
--- /dev/null
+++ b/core/java/com/android/internal/app/NfcResolverActivity.java
@@ -0,0 +1,59 @@
+/*
+ * 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.internal.app;
+
+import static android.service.chooser.CustomChoosers.EXTRA_RESOLVE_INFOS;
+import static android.service.chooser.Flags.supportNfcResolver;
+
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+
+/**
+ * Caller-customizable variant of {@link ResolverActivity} to support the
+ * {@link CustomChoosers#showNfcResolver()} API.
+ */
+public class NfcResolverActivity extends ResolverActivity {
+
+ @Override
+ @SuppressWarnings("MissingSuperCall") // Called indirectly via `super_onCreate()`.
+ protected void onCreate(Bundle savedInstanceState) {
+ if (!supportNfcResolver()) {
+ super_onCreate(savedInstanceState);
+ finish();
+ return;
+ }
+
+ Intent intent = getIntent();
+ Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
+ ArrayList<ResolveInfo> rList =
+ intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS, ResolveInfo.class);
+ CharSequence title = intent.getExtras().getCharSequence(
+ Intent.EXTRA_TITLE,
+ getResources().getText(com.android.internal.R.string.chooseActivity));
+
+ super.onCreate(
+ savedInstanceState,
+ target,
+ title,
+ /* initialIntents=*/ null,
+ rList,
+ /* supportsAlwaysUseOption=*/ false);
+ }
+}
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 4bb7c33..8c2a525 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -93,6 +93,7 @@
WM_DEBUG_DREAM(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM),
WM_DEBUG_DIMMER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM),
+ WM_DEBUG_TPL(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM),
TEST_GROUP(true, true, false, "WindowManagerProtoLogTest");
private final boolean mEnabled;
diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java
index 9c632ea..2a10918 100644
--- a/core/java/com/android/server/LocalServices.java
+++ b/core/java/com/android/server/LocalServices.java
@@ -29,6 +29,7 @@
*
* {@hide}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class LocalServices {
private LocalServices() {}
@@ -69,4 +70,14 @@
sLocalServiceObjects.remove(type);
}
}
+
+ /**
+ * Remove all known service instances, must be only used in tests.
+ */
+ @VisibleForTesting
+ public static void removeAllServicesForTest() {
+ synchronized (sLocalServiceObjects) {
+ sLocalServiceObjects.clear();
+ }
+ }
}
diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp
index 95bf49f..aebe7ea 100644
--- a/core/jni/android_os_PerformanceHintManager.cpp
+++ b/core/jni/android_os_PerformanceHintManager.cpp
@@ -16,15 +16,16 @@
#define LOG_TAG "PerfHint-jni"
-#include "jni.h"
-
+#include <android/performance_hint.h>
#include <dlfcn.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <utils/Log.h>
+
#include <vector>
#include "core_jni_helpers.h"
+#include "jni.h"
namespace android {
@@ -44,6 +45,11 @@
typedef int (*APH_setThreads)(APerformanceHintSession*, const pid_t*, size_t);
typedef void (*APH_getThreadIds)(APerformanceHintSession*, int32_t* const, size_t* const);
typedef void (*APH_setPreferPowerEfficiency)(APerformanceHintSession*, bool);
+typedef void (*APH_reportActualWorkDuration2)(APerformanceHintSession*, AWorkDuration*);
+
+typedef AWorkDuration* (*AWD_create)();
+typedef void (*AWD_setTimeNanos)(AWorkDuration*, int64_t);
+typedef void (*AWD_release)(AWorkDuration*);
bool gAPerformanceHintBindingInitialized = false;
APH_getManager gAPH_getManagerFn = nullptr;
@@ -56,6 +62,14 @@
APH_setThreads gAPH_setThreadsFn = nullptr;
APH_getThreadIds gAPH_getThreadIdsFn = nullptr;
APH_setPreferPowerEfficiency gAPH_setPreferPowerEfficiencyFn = nullptr;
+APH_reportActualWorkDuration2 gAPH_reportActualWorkDuration2Fn = nullptr;
+
+AWD_create gAWD_createFn = nullptr;
+AWD_setTimeNanos gAWD_setWorkPeriodStartTimestampNanosFn = nullptr;
+AWD_setTimeNanos gAWD_setActualTotalDurationNanosFn = nullptr;
+AWD_setTimeNanos gAWD_setActualCpuDurationNanosFn = nullptr;
+AWD_setTimeNanos gAWD_setActualGpuDurationNanosFn = nullptr;
+AWD_release gAWD_releaseFn = nullptr;
void ensureAPerformanceHintBindingInitialized() {
if (gAPerformanceHintBindingInitialized) return;
@@ -112,9 +126,46 @@
(APH_setPreferPowerEfficiency)dlsym(handle_,
"APerformanceHint_setPreferPowerEfficiency");
LOG_ALWAYS_FATAL_IF(gAPH_setPreferPowerEfficiencyFn == nullptr,
- "Failed to find required symbol"
+ "Failed to find required symbol "
"APerformanceHint_setPreferPowerEfficiency!");
+ gAPH_reportActualWorkDuration2Fn =
+ (APH_reportActualWorkDuration2)dlsym(handle_,
+ "APerformanceHint_reportActualWorkDuration2");
+ LOG_ALWAYS_FATAL_IF(gAPH_reportActualWorkDuration2Fn == nullptr,
+ "Failed to find required symbol "
+ "APerformanceHint_reportActualWorkDuration2!");
+
+ gAWD_createFn = (AWD_create)dlsym(handle_, "AWorkDuration_create");
+ LOG_ALWAYS_FATAL_IF(gAWD_createFn == nullptr,
+ "Failed to find required symbol AWorkDuration_create!");
+
+ gAWD_setWorkPeriodStartTimestampNanosFn =
+ (AWD_setTimeNanos)dlsym(handle_, "AWorkDuration_setWorkPeriodStartTimestampNanos");
+ LOG_ALWAYS_FATAL_IF(gAWD_setWorkPeriodStartTimestampNanosFn == nullptr,
+ "Failed to find required symbol "
+ "AWorkDuration_setWorkPeriodStartTimestampNanos!");
+
+ gAWD_setActualTotalDurationNanosFn =
+ (AWD_setTimeNanos)dlsym(handle_, "AWorkDuration_setActualTotalDurationNanos");
+ LOG_ALWAYS_FATAL_IF(gAWD_setActualTotalDurationNanosFn == nullptr,
+ "Failed to find required symbol "
+ "AWorkDuration_setActualTotalDurationNanos!");
+
+ gAWD_setActualCpuDurationNanosFn =
+ (AWD_setTimeNanos)dlsym(handle_, "AWorkDuration_setActualCpuDurationNanos");
+ LOG_ALWAYS_FATAL_IF(gAWD_setActualCpuDurationNanosFn == nullptr,
+ "Failed to find required symbol AWorkDuration_setActualCpuDurationNanos!");
+
+ gAWD_setActualGpuDurationNanosFn =
+ (AWD_setTimeNanos)dlsym(handle_, "AWorkDuration_setActualGpuDurationNanos");
+ LOG_ALWAYS_FATAL_IF(gAWD_setActualGpuDurationNanosFn == nullptr,
+ "Failed to find required symbol AWorkDuration_setActualGpuDurationNanos!");
+
+ gAWD_releaseFn = (AWD_release)dlsym(handle_, "AWorkDuration_release");
+ LOG_ALWAYS_FATAL_IF(gAWD_releaseFn == nullptr,
+ "Failed to find required symbol AWorkDuration_release!");
+
gAPerformanceHintBindingInitialized = true;
}
@@ -238,6 +289,25 @@
enabled);
}
+static void nativeReportActualWorkDuration2(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
+ jlong workPeriodStartTimestampNanos,
+ jlong actualTotalDurationNanos,
+ jlong actualCpuDurationNanos,
+ jlong actualGpuDurationNanos) {
+ ensureAPerformanceHintBindingInitialized();
+
+ AWorkDuration* workDuration = gAWD_createFn();
+ gAWD_setWorkPeriodStartTimestampNanosFn(workDuration, workPeriodStartTimestampNanos);
+ gAWD_setActualTotalDurationNanosFn(workDuration, actualTotalDurationNanos);
+ gAWD_setActualCpuDurationNanosFn(workDuration, actualCpuDurationNanos);
+ gAWD_setActualGpuDurationNanosFn(workDuration, actualGpuDurationNanos);
+
+ gAPH_reportActualWorkDuration2Fn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
+ workDuration);
+
+ gAWD_releaseFn(workDuration);
+}
+
static const JNINativeMethod gPerformanceHintMethods[] = {
{"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
{"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
@@ -249,6 +319,7 @@
{"nativeSetThreads", "(J[I)V", (void*)nativeSetThreads},
{"nativeGetThreadIds", "(J)[I", (void*)nativeGetThreadIds},
{"nativeSetPreferPowerEfficiency", "(JZ)V", (void*)nativeSetPreferPowerEfficiency},
+ {"nativeReportActualWorkDuration", "(JJJJJ)V", (void*)nativeReportActualWorkDuration2},
};
int register_android_os_PerformanceHintManager(JNIEnv* env) {
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 17ca7c8..a2978be 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -359,6 +359,8 @@
optional PeopleType allow_messages_from = 18;
optional ConversationType allow_conversations_from = 19;
+
+ optional ChannelType allow_channels = 20;
}
// Enum identifying the type of rule that changed; values set to match ones used in the
@@ -368,3 +370,11 @@
RULE_TYPE_MANUAL = 1;
RULE_TYPE_AUTOMATIC = 2;
}
+
+// Enum used in DNDPolicyProto to indicate the type of channels permitted to
+// break through DND. Mirrors values in ZenPolicy.
+enum ChannelType {
+ CHANNEL_TYPE_UNSET = 0;
+ CHANNEL_TYPE_PRIORITY = 1;
+ CHANNEL_TYPE_NONE = 2;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cf41a06..38fde3d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7469,6 +7469,13 @@
<permission android:name="android.permission.SIGNAL_REBOOT_READINESS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows the holder to launch an Intent Resolver flow with custom presentation
+ and/or targets.
+ @FlaggedApi("android.service.chooser.support_nfc_resolver")
+ @hide -->
+ <permission android:name="android.permission.SHOW_CUSTOMIZED_RESOLVER"
+ android:protectionLevel="signature|privileged" />
+
<!-- @hide Allows an application to get a People Tile preview for a given shortcut. -->
<permission android:name="android.permission.GET_PEOPLE_TILE_PREVIEW"
android:protectionLevel="signature|recents" />
@@ -7891,6 +7898,18 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+ <activity android:name="com.android.internal.app.NfcResolverActivity"
+ android:theme="@style/Theme.Dialog.Alert"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:multiprocess="true"
+ android:permission="android.permission.SHOW_CUSTOMIZED_RESOLVER"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.service.chooser.action.SHOW_CUSTOMIZED_RESOLVER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<activity android:name="com.android.internal.app.IntentForwarderActivity"
android:finishOnCloseSystemDialogs="true"
android:theme="@style/Theme.DeviceDefault.Resolver"
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
index 20ba427..9b4dec4 100644
--- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
@@ -182,4 +182,42 @@
s.setPreferPowerEfficiency(true);
s.setPreferPowerEfficiency(true);
}
+
+ @Test
+ public void testReportActualWorkDurationWithWorkDurationClass() {
+ Session s = createSession();
+ assumeNotNull(s);
+ s.updateTargetWorkDuration(16);
+ s.reportActualWorkDuration(new WorkDuration(1, 12, 8, 6));
+ s.reportActualWorkDuration(new WorkDuration(1, 33, 14, 20));
+ s.reportActualWorkDuration(new WorkDuration(1, 14, 10, 6));
+ }
+
+ @Test
+ public void testReportActualWorkDurationWithWorkDurationClass_IllegalArgument() {
+ Session s = createSession();
+ assumeNotNull(s);
+ s.updateTargetWorkDuration(16);
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(-1, 12, 8, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(0, 12, 8, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(1, -1, 8, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(1, 0, 8, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(1, 12, -1, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(1, 12, 0, 6));
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ s.reportActualWorkDuration(new WorkDuration(1, 12, 8, -1));
+ });
+ }
}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index e0e3a35..6172622 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -628,6 +628,42 @@
});
}
+ /**
+ * We should boost the frame rate if the value of mInsetsAnimationRunning is true.
+ */
+ @Test
+ @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
+ public void votePreferredFrameRate_insetsAnimation() {
+ View view = new View(sContext);
+ WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
+
+ sInstrumentation.runOnMainSync(() -> {
+ WindowManager wm = sContext.getSystemService(WindowManager.class);
+ Display display = wm.getDefaultDisplay();
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ wmlp.width = (int) (metrics.widthPixels * 0.9);
+ wmlp.height = (int) (metrics.heightPixels * 0.9);
+ wm.addView(view, wmlp);
+ });
+ sInstrumentation.waitForIdleSync();
+
+ ViewRootImpl viewRootImpl = view.getViewRootImpl();
+ sInstrumentation.runOnMainSync(() -> {
+ view.invalidate();
+ assertEquals(viewRootImpl.getLastPreferredFrameRateCategory(),
+ FRAME_RATE_CATEGORY_NORMAL);
+ viewRootImpl.notifyInsetsAnimationRunningStateChanged(true);
+ view.invalidate();
+ });
+ sInstrumentation.waitForIdleSync();
+
+ sInstrumentation.runOnMainSync(() -> {
+ assertEquals(viewRootImpl.getLastPreferredFrameRateCategory(),
+ FRAME_RATE_CATEGORY_HIGH);
+ });
+ }
@Test
public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1f08955..3cf28c9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -383,6 +383,8 @@
<!-- Permission required for ShortcutManagerUsageTest CTS test. -->
<permission name="android.permission.ACCESS_SHORTCUTS"/>
<permission name="android.permission.REBOOT"/>
+ <!-- Permission required for NfcResolverActivity CTS tests. -->
+ <permission name="android.permission.SHOW_CUSTOMIZED_RESOLVER"/>
<!-- Permission required for access VIBRATOR_STATE. -->
<permission name="android.permission.ACCESS_VIBRATOR_STATE"/>
<!-- Permission required for UsageStatsTest CTS test. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 2237ba1..1912821 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -595,6 +595,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1518132958": {
+ "message": "fractionRendered boundsOverSource=%f",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"-1517908912": {
"message": "requestScrollCapture: caught exception dispatching to window.token=%s",
"level": "WARN",
@@ -961,6 +967,12 @@
"group": "WM_DEBUG_CONTENT_RECORDING",
"at": "com\/android\/server\/wm\/ContentRecorder.java"
},
+ "-1209762265": {
+ "message": "Registering listener=%s with id=%d for window=%s with %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"-1209252064": {
"message": "Clear animatingExit: reason=clearAnimatingFlags win=%s",
"level": "DEBUG",
@@ -1333,6 +1345,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-888703350": {
+ "message": "Skipping %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"-883738232": {
"message": "Adding more than one toast window for UID at a time.",
"level": "WARN",
@@ -2803,6 +2821,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "360319850": {
+ "message": "fractionRendered scale=%f",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"364992694": {
"message": "freezeDisplayRotation: current rotation=%d, new rotation=%d, caller=%s",
"level": "VERBOSE",
@@ -2983,6 +3007,12 @@
"group": "WM_DEBUG_BACK_PREVIEW",
"at": "com\/android\/server\/wm\/BackNavigationController.java"
},
+ "532771960": {
+ "message": "Adding untrusted state listener=%s with id=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"535103992": {
"message": "Wallpaper may change! Adjusting",
"level": "VERBOSE",
@@ -3061,6 +3091,12 @@
"group": "WM_DEBUG_DREAM",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "605179032": {
+ "message": "checkIfInThreshold fractionRendered=%f alpha=%f currTimeMs=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"608694300": {
"message": " NEW SURFACE SESSION %s",
"level": "INFO",
@@ -3289,6 +3325,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "824532141": {
+ "message": "lastState=%s newState=%s alpha=%f minAlpha=%f fractionRendered=%f minFractionRendered=%f",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"829434921": {
"message": "Draw state now committed in %s",
"level": "VERBOSE",
@@ -3583,6 +3625,12 @@
"group": "WM_SHOW_SURFACE_ALLOC",
"at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
},
+ "1090378847": {
+ "message": "Checking %d windows",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1100065297": {
"message": "Attempted to get IME policy of a display that does not exist: %d",
"level": "WARN",
@@ -3715,6 +3763,12 @@
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1251721200": {
+ "message": "unregister failed, couldn't find deathRecipient for %s with id=%d",
+ "level": "ERROR",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1252594551": {
"message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d",
"level": "WARN",
@@ -3853,6 +3907,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/TaskDisplayArea.java"
},
+ "1382634842": {
+ "message": "Unregistering listener=%s with id=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1393721079": {
"message": "Starting remote display change: from [rot = %d], to [%dx%d, rot = %d]",
"level": "VERBOSE",
@@ -3901,6 +3961,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1445704347": {
+ "message": "coveredRegionsAbove updated with %s frame:%s region:%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1448683958": {
"message": "Override pending remote transitionSet=%b adapter=%s",
"level": "INFO",
@@ -4201,6 +4267,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
+ "1786463281": {
+ "message": "Adding trusted state listener=%s with id=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1789321832": {
"message": "Then token:%s is invalid. It might be removed",
"level": "WARN",
@@ -4375,6 +4447,12 @@
"group": "WM_DEBUG_TASKS",
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
},
+ "1955470028": {
+ "message": "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s scale=%f,%f",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TPL",
+ "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+ },
"1964565370": {
"message": "Starting remote animation",
"level": "INFO",
@@ -4659,6 +4737,9 @@
"WM_DEBUG_TASKS": {
"tag": "WindowManager"
},
+ "WM_DEBUG_TPL": {
+ "tag": "WindowManager"
+ },
"WM_DEBUG_WALLPAPER": {
"tag": "WindowManager"
},
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 4982f37..231fa48 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -618,7 +618,7 @@
* @see #isMgf1DigestsSpecified()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
if (mMgf1Digests.isEmpty()) {
throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -633,7 +633,7 @@
* @see #getMgf1Digests()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public boolean isMgf1DigestsSpecified() {
return !mMgf1Digests.isEmpty();
}
@@ -1292,7 +1292,7 @@
* <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) {
mMgf1Digests = Set.of(mgf1Digests);
return this;
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 7b6b2d1..c1e3bab 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -401,7 +401,7 @@
* @see #isMgf1DigestsSpecified()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
if (mMgf1Digests.isEmpty()) {
throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -416,7 +416,7 @@
* @see #getMgf1Digests()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public boolean isMgf1DigestsSpecified() {
return !mMgf1Digests.isEmpty();
}
@@ -799,7 +799,7 @@
* <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi("MGF1_DIGEST_SETTER")
public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
mMgf1Digests = Set.of(mgf1Digests);
return this;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 02efc2f..ed4b485 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -28,7 +28,6 @@
import android.hardware.security.keymint.Tag;
import android.os.Build;
import android.os.StrictMode;
-import android.security.Flags;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore2;
import android.security.KeyStoreException;
@@ -854,22 +853,6 @@
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest
));
});
-
- /* If the MGF1 Digest setter is not set, fall back to the previous behaviour:
- * Add, as MGF1 Digest function, all the primary digests.
- * Avoid adding the default MGF1 digest as it will have been included in the
- * mKeymasterMgf1Digests field.
- */
- if (!Flags.mgf1DigestSetter()) {
- final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster(
- DEFAULT_MGF1_DIGEST);
- ArrayUtils.forEach(mKeymasterDigests, (digest) -> {
- if (digest != defaultMgf1Digest) {
- params.add(KeyStore2ParameterUtils.makeEnum(
- KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest));
- }
- });
- }
}
});
ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 4f65884..ddbd93e 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -25,7 +25,6 @@
import android.hardware.security.keymint.KeyParameter;
import android.hardware.security.keymint.SecurityLevel;
import android.os.StrictMode;
-import android.security.Flags;
import android.security.GateKeeper;
import android.security.KeyStore2;
import android.security.KeyStoreParameter;
@@ -538,31 +537,11 @@
/* Because of default MGF1 digest is SHA-1. It has to be added in Key
* characteristics. Otherwise, crypto operations will fail with Incompatible
* MGF1 digest.
- * If the MGF1 Digest setter flag isn't set, then the condition in the
- * if clause above must be false (cannot have MGF1 digests specified if the
- * flag was off). In that case, in addition to adding the default MGF1
- * digest, we have to add all the other digests as MGF1 Digests.
- *
*/
importArgs.add(KeyStore2ParameterUtils.makeEnum(
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
));
- if (!Flags.mgf1DigestSetter()) {
- final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster(
- DEFAULT_MGF1_DIGEST);
- for (String digest : spec.getDigests()) {
- int digestToAddAsMgf1Digest = KeyProperties.Digest.toKeymaster(
- digest);
- // Do not add the default MGF1 digest as it has been added above.
- if (digestToAddAsMgf1Digest != defaultMgf1Digest) {
- importArgs.add(KeyStore2ParameterUtils.makeEnum(
- KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
- digestToAddAsMgf1Digest
- ));
- }
- }
- }
}
}
}
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index fd4522e..5ad144d 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -160,6 +160,7 @@
"kotlinx-coroutines-core",
"iconloader_base",
"com_android_wm_shell_flags_lib",
+ "com.android.window.flags.window-aconfig-java",
"WindowManager-Shell-proto",
"dagger2",
"jsr330",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index baa52a0..5d16196 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -397,6 +397,9 @@
* the screen and the size of the elements around it (e.g. padding, pointer, manage button).
*/
public int getMaxExpandedViewHeight(boolean isOverflow) {
+ if (mDeviceConfig.isLargeScreen() && !mDeviceConfig.isSmallTablet() && !isOverflow) {
+ return getExpandedViewHeightForLargeScreen();
+ }
// Subtract top insets because availableRect.height would account for that
int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
int paddingTop = showBubblesVertically()
@@ -414,6 +417,16 @@
- bottomPadding;
}
+ private int getExpandedViewHeightForLargeScreen() {
+ // the expanded view height on large tablets is calculated based on the shortest screen
+ // size and is the same in both portrait and landscape
+ int maxVerticalInset = Math.max(mInsets.top, mInsets.bottom);
+ int shortestScreenSide = Math.min(getScreenRect().height(), getScreenRect().width());
+ // Subtract pointer size because it's laid out in LinearLayout with the expanded view.
+ return shortestScreenSide - maxVerticalInset * 2
+ - mManageButtonHeight - mPointerWidth - mExpandedViewPadding * 2;
+ }
+
/**
* Determines the height for the bubble, ensuring a minimum height. If the height should be as
* big as available, returns {@link #MAX_HEIGHT}.
@@ -424,15 +437,6 @@
// overflow in landscape on phone is max
return MAX_HEIGHT;
}
-
- if (mDeviceConfig.isLargeScreen() && !mDeviceConfig.isSmallTablet() && !isOverflow) {
- // the expanded view height on large tablets is calculated based on the shortest screen
- // size and is the same in both portrait and landscape
- int maxVerticalInset = Math.max(mInsets.top, mInsets.bottom);
- int shortestScreenSide = Math.min(mScreenRect.height(), mScreenRect.width());
- return shortestScreenSide - 2 * maxVerticalInset - mManageButtonHeight;
- }
-
float desiredHeight = isOverflow
? mOverflowHeight
: ((Bubble) bubble).getDesiredHeight(mContext);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 91a8ce7..ff4da85 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1510,6 +1510,11 @@
updateExpandedView();
}
setUpManageMenu();
+ if (mShowingManage) {
+ // the manage menu location depends on the manage button location which may need a
+ // layout pass, so post this to the looper
+ post(() -> showManageMenu(true));
+ }
}
@Override
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 79f188a..50e1f73 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
@@ -67,6 +67,7 @@
private boolean mIsOverflow;
private BubbleTaskViewHelper mBubbleTaskViewHelper;
private BubbleBarMenuViewController mMenuViewController;
+ private BubbleBarExpandedViewDragController mDragController;
private @Nullable Supplier<Rect> mLayerBoundsSupplier;
private @Nullable Listener mListener;
@@ -180,6 +181,8 @@
mHandleView.setOnClickListener(view -> {
mMenuViewController.showMenu(true /* animated */);
});
+
+ mDragController = new BubbleBarExpandedViewDragController(this);
}
public BubbleBarHandleView getHandleView() {
@@ -386,4 +389,11 @@
setContentVisibility(mIsContentVisible);
}
}
+
+ /**
+ * Check whether the view is animating
+ */
+ public boolean isAnimating() {
+ return mIsAnimating;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
new file mode 100644
index 0000000..933794b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.wm.shell.bubbles.bar
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.graphics.PointF
+import android.view.MotionEvent
+import android.view.View
+import com.android.wm.shell.animation.Interpolators
+import com.android.wm.shell.common.bubbles.RelativeTouchListener
+
+/** Controller for handling drag interactions with [BubbleBarExpandedView] */
+class BubbleBarExpandedViewDragController(private val expandedView: BubbleBarExpandedView) {
+
+ init {
+ expandedView.handleView.setOnTouchListener(HandleDragListener())
+ }
+
+ private fun resetExpandedViewPosition(initialX: Float, initialY: Float) {
+ val listener = object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator) {
+ expandedView.isAnimating = true
+ }
+
+ override fun onAnimationEnd(animation: Animator) {
+ expandedView.isAnimating = false
+ }
+ }
+ expandedView.animate()
+ .translationX(initialX)
+ .translationY(initialY)
+ .setDuration(RESET_POSITION_ANIM_DURATION)
+ .setInterpolator(Interpolators.EMPHASIZED_DECELERATE)
+ .setListener(listener)
+ .start()
+ }
+
+ private inner class HandleDragListener : RelativeTouchListener() {
+
+ private val expandedViewRestPosition = PointF()
+
+ override fun onDown(v: View, ev: MotionEvent): Boolean {
+ // While animating, don't allow new touch events
+ if (expandedView.isAnimating) {
+ return false
+ }
+ expandedViewRestPosition.x = expandedView.translationX
+ expandedViewRestPosition.y = expandedView.translationY
+ return true
+ }
+
+ override fun onMove(
+ v: View,
+ ev: MotionEvent,
+ viewInitialX: Float,
+ viewInitialY: Float,
+ dx: Float,
+ dy: Float
+ ) {
+ expandedView.translationX = expandedViewRestPosition.x + dx
+ expandedView.translationY = expandedViewRestPosition.y + dy
+ }
+
+ override fun onUp(
+ v: View,
+ ev: MotionEvent,
+ viewInitialX: Float,
+ viewInitialY: Float,
+ dx: Float,
+ dy: Float,
+ velX: Float,
+ velY: Float
+ ) {
+ resetExpandedViewPosition(expandedViewRestPosition.x, expandedViewRestPosition.y)
+ }
+
+ override fun onCancel(v: View, ev: MotionEvent, viewInitialX: Float, viewInitialY: Float) {
+ resetExpandedViewPosition(expandedViewRestPosition.x, expandedViewRestPosition.y)
+ }
+ }
+
+ companion object {
+ const val RESET_POSITION_ANIM_DURATION = 300L
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/RelativeTouchListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/RelativeTouchListener.kt
index d45e126..4e55ba2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/RelativeTouchListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/RelativeTouchListener.kt
@@ -78,8 +78,15 @@
velY: Float
)
+ open fun onCancel(
+ v: View,
+ ev: MotionEvent,
+ viewInitialX: Float,
+ viewInitialY: Float
+ ) {}
+
/** The raw coordinates of the last ACTION_DOWN event. */
- private val touchDown = PointF()
+ private var touchDown: PointF? = null
/** The coordinates of the view, at the time of the last ACTION_DOWN event. */
private val viewPositionOnTouchDown = PointF()
@@ -91,12 +98,11 @@
private var performedLongClick = false
- @Suppress("UNCHECKED_CAST")
override fun onTouch(v: View, ev: MotionEvent): Boolean {
addMovement(ev)
- val dx = ev.rawX - touchDown.x
- val dy = ev.rawY - touchDown.y
+ val dx = touchDown?.let { ev.rawX - it.x } ?: 0f
+ val dy = touchDown?.let { ev.rawY - it.y } ?: 0f
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
@@ -108,7 +114,7 @@
// last gesture.
touchSlop = ViewConfiguration.get(v.context).scaledTouchSlop
- touchDown.set(ev.rawX, ev.rawY)
+ touchDown = PointF(ev.rawX, ev.rawY)
viewPositionOnTouchDown.set(v.translationX, v.translationY)
performedLongClick = false
@@ -120,6 +126,7 @@
}
MotionEvent.ACTION_MOVE -> {
+ if (touchDown == null) return false
if (!movedEnough && hypot(dx, dy) > touchSlop && !performedLongClick) {
movedEnough = true
v.handler?.removeCallbacksAndMessages(null)
@@ -131,6 +138,7 @@
}
MotionEvent.ACTION_UP -> {
+ if (touchDown == null) return false
if (movedEnough) {
velocityTracker.computeCurrentVelocity(1000 /* units */)
onUp(v, ev, viewPositionOnTouchDown.x, viewPositionOnTouchDown.y, dx, dy,
@@ -143,12 +151,16 @@
velocityTracker.clear()
movedEnough = false
+ touchDown = null
}
MotionEvent.ACTION_CANCEL -> {
+ if (touchDown == null) return false
v.handler?.removeCallbacksAndMessages(null)
velocityTracker.clear()
movedEnough = false
+ touchDown = null
+ onCancel(v, ev, viewPositionOnTouchDown.x, viewPositionOnTouchDown.y)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index b158f88..3c6bc17 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -324,13 +324,16 @@
@WMSingleton
@Provides
- static SystemPerformanceHinter provideSystemPerformanceHinter(Context context,
+ static Optional<SystemPerformanceHinter> provideSystemPerformanceHinter(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
RootTaskDisplayAreaOrganizer rootTdaOrganizer) {
+ if (!com.android.window.flags.Flags.explicitRefreshRateHints()) {
+ return Optional.empty();
+ }
final PerfHintController perfHintController =
new PerfHintController(context, shellInit, shellCommandHandler, rootTdaOrganizer);
- return perfHintController.getHinter();
+ return Optional.of(perfHintController.getHinter());
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index fdd3044..c1164fc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -123,7 +123,7 @@
private static final int EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS =
SystemProperties.getInt(
- "persist.wm.debug.extra_content_overlay_fade_out_delay_ms", 450);
+ "persist.wm.debug.extra_content_overlay_fade_out_delay_ms", 400);
private final Context mContext;
private final SyncTransactionQueue mSyncTransactionQueue;
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 36e0eb4..be685b5 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
@@ -2210,7 +2210,7 @@
* create a top-bottom split.
*/
boolean isLeftRightSplit() {
- return mSplitLayout.isLeftRightSplit();
+ return mSplitLayout != null && mSplitLayout.isLeftRightSplit();
}
/**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
index 835ebe2..e5ae6e5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
@@ -16,10 +16,15 @@
package com.android.wm.shell.bubbles;
+import static com.android.wm.shell.bubbles.BubblePositioner.MAX_HEIGHT;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static org.mockito.Mockito.mock;
+
import android.content.Intent;
+import android.content.pm.ShortcutInfo;
import android.graphics.Insets;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -226,7 +231,7 @@
}
@Test
- public void testExpandedViewHeight_onLargeTablet() {
+ public void testGetExpandedViewHeight_max() {
Insets insets = Insets.of(10, 20, 5, 15);
Rect screenBounds = new Rect(0, 0, 1800, 2600);
@@ -240,10 +245,91 @@
Intent intent = new Intent(Intent.ACTION_VIEW).setPackage(mContext.getPackageName());
Bubble bubble = Bubble.createAppBubble(intent, new UserHandle(1), null, directExecutor());
+ assertThat(mPositioner.getExpandedViewHeight(bubble)).isEqualTo(MAX_HEIGHT);
+ }
+
+ @Test
+ public void testGetExpandedViewHeight_customHeight_valid() {
+ Insets insets = Insets.of(10, 20, 5, 15);
+ Rect screenBounds = new Rect(0, 0, 1800, 2600);
+
+ DeviceConfig deviceConfig = new ConfigBuilder()
+ .setLargeScreen()
+ .setInsets(insets)
+ .setScreenBounds(screenBounds)
+ .build();
+ mPositioner.update(deviceConfig);
+
+ final int minHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.bubble_expanded_default_height);
+ Bubble bubble = new Bubble("key",
+ mock(ShortcutInfo.class),
+ minHeight + 100 /* desiredHeight */,
+ 0 /* desiredHeightResId */,
+ "title",
+ 0 /* taskId */,
+ null /* locus */,
+ true /* isDismissable */,
+ directExecutor(),
+ mock(Bubbles.BubbleMetadataFlagListener.class));
+
+ // Ensure the height is the same as the desired value
+ assertThat(mPositioner.getExpandedViewHeight(bubble)).isEqualTo(
+ bubble.getDesiredHeight(mContext));
+ }
+
+
+ @Test
+ public void testGetExpandedViewHeight_customHeight_tooSmall() {
+ Insets insets = Insets.of(10, 20, 5, 15);
+ Rect screenBounds = new Rect(0, 0, 1800, 2600);
+
+ DeviceConfig deviceConfig = new ConfigBuilder()
+ .setLargeScreen()
+ .setInsets(insets)
+ .setScreenBounds(screenBounds)
+ .build();
+ mPositioner.update(deviceConfig);
+
+ Bubble bubble = new Bubble("key",
+ mock(ShortcutInfo.class),
+ 10 /* desiredHeight */,
+ 0 /* desiredHeightResId */,
+ "title",
+ 0 /* taskId */,
+ null /* locus */,
+ true /* isDismissable */,
+ directExecutor(),
+ mock(Bubbles.BubbleMetadataFlagListener.class));
+
+ // Ensure the height is the same as the minimum value
+ final int minHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.bubble_expanded_default_height);
+ assertThat(mPositioner.getExpandedViewHeight(bubble)).isEqualTo(minHeight);
+ }
+
+ @Test
+ public void testGetMaxExpandedViewHeight_onLargeTablet() {
+ Insets insets = Insets.of(10, 20, 5, 15);
+ Rect screenBounds = new Rect(0, 0, 1800, 2600);
+
+ DeviceConfig deviceConfig = new ConfigBuilder()
+ .setLargeScreen()
+ .setInsets(insets)
+ .setScreenBounds(screenBounds)
+ .build();
+ mPositioner.update(deviceConfig);
+
int manageButtonHeight =
mContext.getResources().getDimensionPixelSize(R.dimen.bubble_manage_button_height);
- float expectedHeight = 1800 - 2 * 20 - manageButtonHeight;
- assertThat(mPositioner.getExpandedViewHeight(bubble)).isWithin(0.1f).of(expectedHeight);
+ int pointerWidth = mContext.getResources().getDimensionPixelSize(
+ R.dimen.bubble_pointer_width);
+ int expandedViewPadding = mContext.getResources().getDimensionPixelSize(R
+ .dimen.bubble_expanded_view_padding);
+ float expectedHeight = 1800 - 2 * 20 - manageButtonHeight - pointerWidth
+ - expandedViewPadding * 2;
+ assertThat(((float) mPositioner.getMaxExpandedViewHeight(false /* isOverflow */)))
+ .isWithin(0.1f).of(expectedHeight);
}
/**
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 47a7f35..2f28363 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -63,15 +63,21 @@
"AssetsProvider.cpp",
"AttributeResolution.cpp",
"BigBuffer.cpp",
+ "BigBufferStream.cpp",
"ChunkIterator.cpp",
"ConfigDescription.cpp",
+ "FileStream.cpp",
"Idmap.cpp",
"LoadedArsc.cpp",
"Locale.cpp",
"LocaleData.cpp",
"misc.cpp",
+ "NinePatch.cpp",
"ObbFile.cpp",
"PosixUtils.cpp",
+ "Png.cpp",
+ "PngChunkFilter.cpp",
+ "PngCrunch.cpp",
"ResourceTimer.cpp",
"ResourceTypes.cpp",
"ResourceUtils.cpp",
@@ -84,7 +90,10 @@
],
export_include_dirs: ["include"],
export_shared_lib_headers: ["libz"],
- static_libs: ["libincfs-utils"],
+ static_libs: [
+ "libincfs-utils",
+ "libpng",
+ ],
whole_static_libs: [
"libandroidfw_pathutils",
"libincfs-utils",
@@ -198,9 +207,11 @@
"tests/ConfigDescription_test.cpp",
"tests/ConfigLocale_test.cpp",
"tests/DynamicRefTable_test.cpp",
+ "tests/FileStream_test.cpp",
"tests/Idmap_test.cpp",
"tests/LoadedArsc_test.cpp",
"tests/Locale_test.cpp",
+ "tests/NinePatch_test.cpp",
"tests/ResourceTimer_test.cpp",
"tests/ResourceUtils_test.cpp",
"tests/ResTable_test.cpp",
diff --git a/tools/aapt2/io/BigBufferStream.cpp b/libs/androidfw/BigBufferStream.cpp
similarity index 69%
rename from tools/aapt2/io/BigBufferStream.cpp
rename to libs/androidfw/BigBufferStream.cpp
index 9704caa..f18199c 100644
--- a/tools/aapt2/io/BigBufferStream.cpp
+++ b/libs/androidfw/BigBufferStream.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "io/BigBufferStream.h"
+#include "androidfw/BigBufferStream.h"
-namespace aapt {
-namespace io {
+#include <algorithm>
+
+namespace android {
//
// BigBufferInputStream
@@ -76,6 +77,34 @@
return buffer_->size();
}
+bool BigBufferInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
+ if (byte_count == 0) {
+ return true;
+ }
+ if (offset < 0) {
+ return false;
+ }
+ if (offset > std::numeric_limits<off64_t>::max() - byte_count) {
+ return false;
+ }
+ if (offset + byte_count > buffer_->size()) {
+ return false;
+ }
+ auto p = reinterpret_cast<uint8_t*>(data);
+ for (auto iter = buffer_->begin(); iter != buffer_->end() && byte_count > 0; ++iter) {
+ if (offset < iter->size) {
+ size_t to_read = std::min(byte_count, (size_t)(iter->size - offset));
+ memcpy(p, iter->buffer.get() + offset, to_read);
+ byte_count -= to_read;
+ p += to_read;
+ offset = 0;
+ } else {
+ offset -= iter->size;
+ }
+ }
+ return byte_count == 0;
+}
+
//
// BigBufferOutputStream
//
@@ -97,5 +126,4 @@
return false;
}
-} // namespace io
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/io/FileStream.cpp b/libs/androidfw/FileStream.cpp
similarity index 95%
rename from tools/aapt2/io/FileStream.cpp
rename to libs/androidfw/FileStream.cpp
index 27529bc..b86c9cb 100644
--- a/tools/aapt2/io/FileStream.cpp
+++ b/libs/androidfw/FileStream.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "io/FileStream.h"
+#include "androidfw/FileStream.h"
#include <errno.h> // for errno
#include <fcntl.h> // for O_RDONLY
@@ -34,8 +34,7 @@
using ::android::base::SystemErrorCodeToString;
using ::android::base::unique_fd;
-namespace aapt {
-namespace io {
+namespace android {
FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity)
: buffer_capacity_(buffer_capacity) {
@@ -108,6 +107,10 @@
return error_;
}
+bool FileInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
+ return base::ReadFullyAtOffset(fd_, data, byte_count, offset);
+}
+
FileOutputStream::FileOutputStream(const std::string& path, size_t buffer_capacity)
: buffer_capacity_(buffer_capacity) {
int mode = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
@@ -199,5 +202,4 @@
return error_;
}
-} // namespace io
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/compile/NinePatch.cpp b/libs/androidfw/NinePatch.cpp
similarity index 80%
rename from tools/aapt2/compile/NinePatch.cpp
rename to libs/androidfw/NinePatch.cpp
index 4538ecc..1fdbebf 100644
--- a/tools/aapt2/compile/NinePatch.cpp
+++ b/libs/androidfw/NinePatch.cpp
@@ -14,20 +14,17 @@
* limitations under the License.
*/
-#include "compile/Image.h"
-
#include <sstream>
#include <string>
#include <vector>
+#include "androidfw/Image.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-#include "util/Util.h"
-
using android::StringPiece;
-namespace aapt {
+namespace android {
// Colors in the format 0xAARRGGBB (the way 9-patch expects it).
constexpr static const uint32_t kColorOpaqueWhite = 0xffffffffu;
@@ -90,10 +87,8 @@
// };
//
template <typename ImageLine>
-static bool FillRanges(const ImageLine* image_line,
- const ColorValidator* color_validator,
- std::vector<Range>* primary_ranges,
- std::vector<Range>* secondary_ranges,
+static bool FillRanges(const ImageLine* image_line, const ColorValidator* color_validator,
+ std::vector<Range>* primary_ranges, std::vector<Range>* secondary_ranges,
std::string* out_err) {
const int32_t length = image_line->GetLength();
@@ -133,11 +128,13 @@
*/
class HorizontalImageLine {
public:
- explicit HorizontalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset,
- int32_t length)
- : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {}
+ explicit HorizontalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t length)
+ : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {
+ }
- inline int32_t GetLength() const { return length_; }
+ inline int32_t GetLength() const {
+ return length_;
+ }
inline uint32_t GetColor(int32_t idx) const {
return NinePatch::PackRGBA(rows_[yoffset_] + (idx + xoffset_) * 4);
@@ -156,11 +153,13 @@
*/
class VerticalImageLine {
public:
- explicit VerticalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset,
- int32_t length)
- : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {}
+ explicit VerticalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t length)
+ : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {
+ }
- inline int32_t GetLength() const { return length_; }
+ inline int32_t GetLength() const {
+ return length_;
+ }
inline uint32_t GetColor(int32_t idx) const {
return NinePatch::PackRGBA(rows_[yoffset_ + idx] + (xoffset_ * 4));
@@ -175,20 +174,22 @@
class DiagonalImageLine {
public:
- explicit DiagonalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset,
- int32_t xstep, int32_t ystep, int32_t length)
+ explicit DiagonalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t xstep,
+ int32_t ystep, int32_t length)
: rows_(rows),
xoffset_(xoffset),
yoffset_(yoffset),
xstep_(xstep),
ystep_(ystep),
- length_(length) {}
+ length_(length) {
+ }
- inline int32_t GetLength() const { return length_; }
+ inline int32_t GetLength() const {
+ return length_;
+ }
inline uint32_t GetColor(int32_t idx) const {
- return NinePatch::PackRGBA(rows_[yoffset_ + (idx * ystep_)] +
- ((idx + xoffset_) * xstep_) * 4);
+ return NinePatch::PackRGBA(rows_[yoffset_ + (idx * ystep_)] + ((idx + xoffset_) * xstep_) * 4);
}
private:
@@ -243,8 +244,7 @@
if (layout_bounds.size() > 2) {
std::stringstream err_stream;
- err_stream << "too many layout bounds sections on " << edge_name
- << " border";
+ err_stream << "too many layout bounds sections on " << edge_name << " border";
*out_err = err_stream.str();
return false;
}
@@ -258,8 +258,7 @@
// end at length.
if (range.start != 0 && range.end != length) {
std::stringstream err_stream;
- err_stream << "layout bounds on " << edge_name
- << " border must start at edge";
+ err_stream << "layout bounds on " << edge_name << " border must start at edge";
*out_err = err_stream.str();
return false;
}
@@ -269,8 +268,7 @@
const Range& range = layout_bounds.back();
if (range.end != length) {
std::stringstream err_stream;
- err_stream << "layout bounds on " << edge_name
- << " border must start at edge";
+ err_stream << "layout bounds on " << edge_name << " border must start at edge";
*out_err = err_stream.str();
return false;
}
@@ -280,8 +278,7 @@
return true;
}
-static int32_t CalculateSegmentCount(const std::vector<Range>& stretch_regions,
- int32_t length) {
+static int32_t CalculateSegmentCount(const std::vector<Range>& stretch_regions, int32_t length) {
if (stretch_regions.size() == 0) {
return 0;
}
@@ -299,8 +296,7 @@
static uint32_t GetRegionColor(uint8_t** rows, const Bounds& region) {
// Sample the first pixel to compare against.
- const uint32_t expected_color =
- NinePatch::PackRGBA(rows[region.top] + region.left * 4);
+ const uint32_t expected_color = NinePatch::PackRGBA(rows[region.top] + region.left * 4);
for (int32_t y = region.top; y < region.bottom; y++) {
const uint8_t* row = rows[y];
for (int32_t x = region.left; x < region.right; x++) {
@@ -336,10 +332,11 @@
// the indices must be offset by 1.
//
// width and height also include the 9-patch 1px border.
-static void CalculateRegionColors(
- uint8_t** rows, const std::vector<Range>& horizontal_stretch_regions,
- const std::vector<Range>& vertical_stretch_regions, const int32_t width,
- const int32_t height, std::vector<uint32_t>* out_colors) {
+static void CalculateRegionColors(uint8_t** rows,
+ const std::vector<Range>& horizontal_stretch_regions,
+ const std::vector<Range>& vertical_stretch_regions,
+ const int32_t width, const int32_t height,
+ std::vector<uint32_t>* out_colors) {
int32_t next_top = 0;
Bounds bounds;
auto row_iter = vertical_stretch_regions.begin();
@@ -401,8 +398,7 @@
// alpha value begins
// (on both sides).
template <typename ImageLine>
-static void FindOutlineInsets(const ImageLine* image_line, int32_t* out_start,
- int32_t* out_end) {
+static void FindOutlineInsets(const ImageLine* image_line, int32_t* out_start, int32_t* out_end) {
*out_start = 0;
*out_end = 0;
@@ -455,10 +451,8 @@
return (pixel[3] << 24) | (pixel[0] << 16) | (pixel[1] << 8) | pixel[2];
}
-std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows,
- const int32_t width,
- const int32_t height,
- std::string* out_err) {
+std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, const int32_t width,
+ const int32_t height, std::string* out_err) {
if (width < 3 || height < 3) {
*out_err = "image must be at least 3x3 (1x1 image with 1 pixel border)";
return {};
@@ -472,12 +466,11 @@
std::unique_ptr<ColorValidator> color_validator;
if (rows[0][3] == 0) {
- color_validator = util::make_unique<TransparentNeutralColorValidator>();
+ color_validator = std::make_unique<TransparentNeutralColorValidator>();
} else if (PackRGBA(rows[0]) == kColorOpaqueWhite) {
- color_validator = util::make_unique<WhiteNeutralColorValidator>();
+ color_validator = std::make_unique<WhiteNeutralColorValidator>();
} else {
- *out_err =
- "top-left corner pixel must be either opaque white or transparent";
+ *out_err = "top-left corner pixel must be either opaque white or transparent";
return {};
}
@@ -485,9 +478,8 @@
auto nine_patch = std::unique_ptr<NinePatch>(new NinePatch());
HorizontalImageLine top_row(rows, 0, 0, width);
- if (!FillRanges(&top_row, color_validator.get(),
- &nine_patch->horizontal_stretch_regions, &unexpected_ranges,
- out_err)) {
+ if (!FillRanges(&top_row, color_validator.get(), &nine_patch->horizontal_stretch_regions,
+ &unexpected_ranges, out_err)) {
return {};
}
@@ -501,9 +493,8 @@
}
VerticalImageLine left_col(rows, 0, 0, height);
- if (!FillRanges(&left_col, color_validator.get(),
- &nine_patch->vertical_stretch_regions, &unexpected_ranges,
- out_err)) {
+ if (!FillRanges(&left_col, color_validator.get(), &nine_patch->vertical_stretch_regions,
+ &unexpected_ranges, out_err)) {
return {};
}
@@ -522,32 +513,28 @@
}
if (!PopulateBounds(horizontal_padding, horizontal_layout_bounds,
- nine_patch->horizontal_stretch_regions, width - 2,
- &nine_patch->padding.left, &nine_patch->padding.right,
- &nine_patch->layout_bounds.left,
+ nine_patch->horizontal_stretch_regions, width - 2, &nine_patch->padding.left,
+ &nine_patch->padding.right, &nine_patch->layout_bounds.left,
&nine_patch->layout_bounds.right, "bottom", out_err)) {
return {};
}
VerticalImageLine right_col(rows, width - 1, 0, height);
- if (!FillRanges(&right_col, color_validator.get(), &vertical_padding,
- &vertical_layout_bounds, out_err)) {
+ if (!FillRanges(&right_col, color_validator.get(), &vertical_padding, &vertical_layout_bounds,
+ out_err)) {
return {};
}
if (!PopulateBounds(vertical_padding, vertical_layout_bounds,
- nine_patch->vertical_stretch_regions, height - 2,
- &nine_patch->padding.top, &nine_patch->padding.bottom,
- &nine_patch->layout_bounds.top,
+ nine_patch->vertical_stretch_regions, height - 2, &nine_patch->padding.top,
+ &nine_patch->padding.bottom, &nine_patch->layout_bounds.top,
&nine_patch->layout_bounds.bottom, "right", out_err)) {
return {};
}
// Fill the region colors of the 9-patch.
- const int32_t num_rows =
- CalculateSegmentCount(nine_patch->horizontal_stretch_regions, width - 2);
- const int32_t num_cols =
- CalculateSegmentCount(nine_patch->vertical_stretch_regions, height - 2);
+ const int32_t num_rows = CalculateSegmentCount(nine_patch->horizontal_stretch_regions, width - 2);
+ const int32_t num_cols = CalculateSegmentCount(nine_patch->vertical_stretch_regions, height - 2);
if ((int64_t)num_rows * (int64_t)num_cols > 0x7f) {
*out_err = "too many regions in 9-patch";
return {};
@@ -555,40 +542,35 @@
nine_patch->region_colors.reserve(num_rows * num_cols);
CalculateRegionColors(rows, nine_patch->horizontal_stretch_regions,
- nine_patch->vertical_stretch_regions, width - 2,
- height - 2, &nine_patch->region_colors);
+ nine_patch->vertical_stretch_regions, width - 2, height - 2,
+ &nine_patch->region_colors);
// Compute the outline based on opacity.
// Find left and right extent of 9-patch content on center row.
HorizontalImageLine mid_row(rows, 1, height / 2, width - 2);
- FindOutlineInsets(&mid_row, &nine_patch->outline.left,
- &nine_patch->outline.right);
+ FindOutlineInsets(&mid_row, &nine_patch->outline.left, &nine_patch->outline.right);
// Find top and bottom extent of 9-patch content on center column.
VerticalImageLine mid_col(rows, width / 2, 1, height - 2);
- FindOutlineInsets(&mid_col, &nine_patch->outline.top,
- &nine_patch->outline.bottom);
+ FindOutlineInsets(&mid_col, &nine_patch->outline.top, &nine_patch->outline.bottom);
- const int32_t outline_width =
- (width - 2) - nine_patch->outline.left - nine_patch->outline.right;
+ const int32_t outline_width = (width - 2) - nine_patch->outline.left - nine_patch->outline.right;
const int32_t outline_height =
(height - 2) - nine_patch->outline.top - nine_patch->outline.bottom;
// Find the largest alpha value within the outline area.
- HorizontalImageLine outline_mid_row(
- rows, 1 + nine_patch->outline.left,
- 1 + nine_patch->outline.top + (outline_height / 2), outline_width);
- VerticalImageLine outline_mid_col(
- rows, 1 + nine_patch->outline.left + (outline_width / 2),
- 1 + nine_patch->outline.top, outline_height);
+ HorizontalImageLine outline_mid_row(rows, 1 + nine_patch->outline.left,
+ 1 + nine_patch->outline.top + (outline_height / 2),
+ outline_width);
+ VerticalImageLine outline_mid_col(rows, 1 + nine_patch->outline.left + (outline_width / 2),
+ 1 + nine_patch->outline.top, outline_height);
nine_patch->outline_alpha =
std::max(FindMaxAlpha(&outline_mid_row), FindMaxAlpha(&outline_mid_col));
// Assuming the image is a round rect, compute the radius by marching
// diagonally from the top left corner towards the center.
- DiagonalImageLine diagonal(rows, 1 + nine_patch->outline.left,
- 1 + nine_patch->outline.top, 1, 1,
+ DiagonalImageLine diagonal(rows, 1 + nine_patch->outline.left, 1 + nine_patch->outline.top, 1, 1,
std::min(outline_width, outline_height));
int32_t top_left, bottom_right;
FindOutlineInsets(&diagonal, &top_left, &bottom_right);
@@ -614,10 +596,9 @@
data.paddingBottom = padding.bottom;
auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[data.serializedSize()]);
- android::Res_png_9patch::serialize(
- data, (const int32_t*)horizontal_stretch_regions.data(),
- (const int32_t*)vertical_stretch_regions.data(), region_colors.data(),
- buffer.get());
+ android::Res_png_9patch::serialize(data, (const int32_t*)horizontal_stretch_regions.data(),
+ (const int32_t*)vertical_stretch_regions.data(),
+ region_colors.data(), buffer.get());
// Convert to file endianness.
reinterpret_cast<android::Res_png_9patch*>(buffer.get())->deviceToFile();
@@ -625,8 +606,7 @@
return buffer;
}
-std::unique_ptr<uint8_t[]> NinePatch::SerializeLayoutBounds(
- size_t* out_len) const {
+std::unique_ptr<uint8_t[]> NinePatch::SerializeLayoutBounds(size_t* out_len) const {
size_t chunk_len = sizeof(uint32_t) * 4;
auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[chunk_len]);
uint8_t* cursor = buffer.get();
@@ -647,8 +627,7 @@
return buffer;
}
-std::unique_ptr<uint8_t[]> NinePatch::SerializeRoundedRectOutline(
- size_t* out_len) const {
+std::unique_ptr<uint8_t[]> NinePatch::SerializeRoundedRectOutline(size_t* out_len) const {
size_t chunk_len = sizeof(uint32_t) * 6;
auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[chunk_len]);
uint8_t* cursor = buffer.get();
@@ -679,20 +658,25 @@
}
::std::ostream& operator<<(::std::ostream& out, const Bounds& bounds) {
- return out << "l=" << bounds.left << " t=" << bounds.top
- << " r=" << bounds.right << " b=" << bounds.bottom;
+ return out << "l=" << bounds.left << " t=" << bounds.top << " r=" << bounds.right
+ << " b=" << bounds.bottom;
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
+ for (int i = 0; i < v.size(); ++i) {
+ os << v[i];
+ if (i != v.size() - 1) os << " ";
+ }
+ return os;
}
::std::ostream& operator<<(::std::ostream& out, const NinePatch& nine_patch) {
- return out << "horizontalStretch:"
- << util::Joiner(nine_patch.horizontal_stretch_regions, " ")
- << " verticalStretch:"
- << util::Joiner(nine_patch.vertical_stretch_regions, " ")
- << " padding: " << nine_patch.padding
- << ", bounds: " << nine_patch.layout_bounds
- << ", outline: " << nine_patch.outline
- << " rad=" << nine_patch.outline_radius
+ return out << "horizontalStretch:" << nine_patch.horizontal_stretch_regions
+ << " verticalStretch:" << nine_patch.vertical_stretch_regions
+ << " padding: " << nine_patch.padding << ", bounds: " << nine_patch.layout_bounds
+ << ", outline: " << nine_patch.outline << " rad=" << nine_patch.outline_radius
<< " alpha=" << nine_patch.outline_alpha;
}
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/compile/Png.cpp b/libs/androidfw/Png.cpp
similarity index 77%
rename from tools/aapt2/compile/Png.cpp
rename to libs/androidfw/Png.cpp
index 76db815..fb45cd9 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/libs/androidfw/Png.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Png.h"
+#include "androidfw/Png.h"
#include <png.h>
#include <zlib.h>
@@ -24,13 +24,12 @@
#include <string>
#include <vector>
+#include "android-base/strings.h"
#include "androidfw/BigBuffer.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Source.h"
-#include "trace/TraceBuffer.h"
-#include "util/Util.h"
-namespace aapt {
+namespace android {
constexpr bool kDebug = false;
@@ -47,9 +46,8 @@
}
void* serialize9Patch() {
- void* serialized = android::Res_png_9patch::serialize(info9Patch, xDivs,
- yDivs, colors.data());
- reinterpret_cast<android::Res_png_9patch*>(serialized)->deviceToFile();
+ void* serialized = Res_png_9patch::serialize(info9Patch, xDivs, yDivs, colors.data());
+ reinterpret_cast<Res_png_9patch*>(serialized)->deviceToFile();
return serialized;
}
@@ -58,7 +56,7 @@
std::vector<png_bytep> rows;
bool is9Patch = false;
- android::Res_png_9patch info9Patch;
+ Res_png_9patch info9Patch;
int32_t* xDivs = nullptr;
int32_t* yDivs = nullptr;
std::vector<uint32_t> colors;
@@ -79,34 +77,30 @@
uint8_t outlineAlpha;
};
-static void readDataFromStream(png_structp readPtr, png_bytep data,
- png_size_t length) {
- std::istream* input =
- reinterpret_cast<std::istream*>(png_get_io_ptr(readPtr));
+static void readDataFromStream(png_structp readPtr, png_bytep data, png_size_t length) {
+ std::istream* input = reinterpret_cast<std::istream*>(png_get_io_ptr(readPtr));
if (!input->read(reinterpret_cast<char*>(data), length)) {
png_error(readPtr, strerror(errno));
}
}
-static void writeDataToStream(png_structp writePtr, png_bytep data,
- png_size_t length) {
- android::BigBuffer* outBuffer = reinterpret_cast<android::BigBuffer*>(png_get_io_ptr(writePtr));
+static void writeDataToStream(png_structp writePtr, png_bytep data, png_size_t length) {
+ BigBuffer* outBuffer = reinterpret_cast<BigBuffer*>(png_get_io_ptr(writePtr));
png_bytep buf = outBuffer->NextBlock<png_byte>(length);
memcpy(buf, data, length);
}
-static void flushDataToStream(png_structp /*writePtr*/) {}
-
-static void logWarning(png_structp readPtr, png_const_charp warningMessage) {
- android::IDiagnostics* diag =
- reinterpret_cast<android::IDiagnostics*>(png_get_error_ptr(readPtr));
- diag->Warn(android::DiagMessage() << warningMessage);
+static void flushDataToStream(png_structp /*writePtr*/) {
}
-static bool readPng(android::IDiagnostics* diag, png_structp readPtr, png_infop infoPtr,
- PngInfo* outInfo) {
+static void logWarning(png_structp readPtr, png_const_charp warningMessage) {
+ IDiagnostics* diag = reinterpret_cast<IDiagnostics*>(png_get_error_ptr(readPtr));
+ diag->Warn(DiagMessage() << warningMessage);
+}
+
+static bool readPng(IDiagnostics* diag, png_structp readPtr, png_infop infoPtr, PngInfo* outInfo) {
if (setjmp(png_jmpbuf(readPtr))) {
- diag->Error(android::DiagMessage() << "failed reading png");
+ diag->Error(DiagMessage() << "failed reading png");
return false;
}
@@ -114,8 +108,8 @@
png_read_info(readPtr, infoPtr);
int colorType, bitDepth, interlaceType, compressionType;
- png_get_IHDR(readPtr, infoPtr, &outInfo->width, &outInfo->height, &bitDepth,
- &colorType, &interlaceType, &compressionType, nullptr);
+ png_get_IHDR(readPtr, infoPtr, &outInfo->width, &outInfo->height, &bitDepth, &colorType,
+ &interlaceType, &compressionType, nullptr);
if (colorType == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(readPtr);
@@ -137,8 +131,7 @@
png_set_add_alpha(readPtr, 0xFF, PNG_FILLER_AFTER);
}
- if (colorType == PNG_COLOR_TYPE_GRAY ||
- colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(readPtr);
}
@@ -156,12 +149,11 @@
return true;
}
-static void checkNinePatchSerialization(android::Res_png_9patch* inPatch,
- void* data) {
+static void checkNinePatchSerialization(Res_png_9patch* inPatch, void* data) {
size_t patchSize = inPatch->serializedSize();
void* newData = malloc(patchSize);
memcpy(newData, data, patchSize);
- android::Res_png_9patch* outPatch = inPatch->deserialize(newData);
+ Res_png_9patch* outPatch = inPatch->deserialize(newData);
outPatch->fileToDevice();
// deserialization is done in place, so outPatch == newData
assert(outPatch == newData);
@@ -244,10 +236,9 @@
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define ABS(a) ((a) < 0 ? -(a) : (a))
-static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo,
- int grayscaleTolerance, png_colorp rgbPalette, png_bytep alphaPalette,
- int* paletteEntries, bool* hasTransparency, int* colorType,
- png_bytepp outRows) {
+static void analyze_image(IDiagnostics* diag, const PngInfo& imageInfo, int grayscaleTolerance,
+ png_colorp rgbPalette, png_bytep alphaPalette, int* paletteEntries,
+ bool* hasTransparency, int* colorType, png_bytepp outRows) {
int w = imageInfo.width;
int h = imageInfo.height;
int i, j, rr, gg, bb, aa, idx;
@@ -284,8 +275,8 @@
maxGrayDeviation = MAX(ABS(bb - rr), maxGrayDeviation);
if (maxGrayDeviation > odev) {
if (kDebug) {
- printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n",
- maxGrayDeviation, i, j, rr, gg, bb, aa);
+ printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", maxGrayDeviation, i, j,
+ rr, gg, bb, aa);
}
}
@@ -293,8 +284,7 @@
if (isGrayscale) {
if (rr != gg || rr != bb) {
if (kDebug) {
- printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", i, j,
- rr, gg, bb, aa);
+ printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", i, j, rr, gg, bb, aa);
}
isGrayscale = false;
}
@@ -304,8 +294,7 @@
if (isOpaque) {
if (aa != 0xff) {
if (kDebug) {
- printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", i, j,
- rr, gg, bb, aa);
+ printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", i, j, rr, gg, bb, aa);
}
isOpaque = false;
}
@@ -349,10 +338,9 @@
printf("isGrayscale = %s\n", isGrayscale ? "true" : "false");
printf("isOpaque = %s\n", isOpaque ? "true" : "false");
printf("isPalette = %s\n", isPalette ? "true" : "false");
- printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", paletteSize,
- 2 * w * h, bpp * w * h);
- printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation,
- grayscaleTolerance);
+ printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", paletteSize, 2 * w * h,
+ bpp * w * h);
+ printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, grayscaleTolerance);
}
// Choose the best color type for the image.
@@ -381,8 +369,8 @@
*colorType = PNG_COLOR_TYPE_PALETTE;
} else {
if (maxGrayDeviation <= grayscaleTolerance) {
- diag->Note(android::DiagMessage()
- << "forcing image to gray (max deviation = " << maxGrayDeviation << ")");
+ diag->Note(DiagMessage() << "forcing image to gray (max deviation = " << maxGrayDeviation
+ << ")");
*colorType = isOpaque ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_GRAY_ALPHA;
} else {
*colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA;
@@ -404,8 +392,7 @@
rgbPalette[idx].blue = (png_byte)((col >> 8) & 0xff);
alphaPalette[idx] = (png_byte)(col & 0xff);
}
- } else if (*colorType == PNG_COLOR_TYPE_GRAY ||
- *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ } else if (*colorType == PNG_COLOR_TYPE_GRAY || *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
// If the image is gray or gray + alpha, compact the pixels into outRows
for (j = 0; j < h; j++) {
const png_byte* row = imageInfo.rows[j];
@@ -429,10 +416,10 @@
}
}
-static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_infop infoPtr,
- PngInfo* info, int grayScaleTolerance) {
+static bool writePng(IDiagnostics* diag, png_structp writePtr, png_infop infoPtr, PngInfo* info,
+ int grayScaleTolerance) {
if (setjmp(png_jmpbuf(writePtr))) {
- diag->Error(android::DiagMessage() << "failed to write png");
+ diag->Error(DiagMessage() << "failed to write png");
return false;
}
@@ -444,8 +431,7 @@
unknowns[1].data = nullptr;
unknowns[2].data = nullptr;
- png_bytepp outRows =
- (png_bytepp)malloc((int)info->height * sizeof(png_bytep));
+ png_bytepp outRows = (png_bytepp)malloc((int)info->height * sizeof(png_bytep));
if (outRows == (png_bytepp)0) {
printf("Can't allocate output buffer!\n");
exit(1);
@@ -461,8 +447,7 @@
png_set_compression_level(writePtr, Z_BEST_COMPRESSION);
if (kDebug) {
- diag->Note(android::DiagMessage()
- << "writing image: w = " << info->width << ", h = " << info->height);
+ diag->Note(DiagMessage() << "writing image: w = " << info->width << ", h = " << info->height);
}
png_color rgbPalette[256];
@@ -470,48 +455,45 @@
bool hasTransparency;
int paletteEntries;
- analyze_image(diag, *info, grayScaleTolerance, rgbPalette, alphaPalette,
- &paletteEntries, &hasTransparency, &colorType, outRows);
+ analyze_image(diag, *info, grayScaleTolerance, rgbPalette, alphaPalette, &paletteEntries,
+ &hasTransparency, &colorType, outRows);
// If the image is a 9-patch, we need to preserve it as a ARGB file to make
// sure the pixels will not be pre-dithered/clamped until we decide they are
- if (info->is9Patch &&
- (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY ||
- colorType == PNG_COLOR_TYPE_PALETTE)) {
+ if (info->is9Patch && (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY ||
+ colorType == PNG_COLOR_TYPE_PALETTE)) {
colorType = PNG_COLOR_TYPE_RGB_ALPHA;
}
if (kDebug) {
switch (colorType) {
case PNG_COLOR_TYPE_PALETTE:
- diag->Note(android::DiagMessage() << "has " << paletteEntries << " colors"
- << (hasTransparency ? " (with alpha)" : "")
- << ", using PNG_COLOR_TYPE_PALLETTE");
+ diag->Note(DiagMessage() << "has " << paletteEntries << " colors"
+ << (hasTransparency ? " (with alpha)" : "")
+ << ", using PNG_COLOR_TYPE_PALLETTE");
break;
case PNG_COLOR_TYPE_GRAY:
- diag->Note(android::DiagMessage() << "is opaque gray, using PNG_COLOR_TYPE_GRAY");
+ diag->Note(DiagMessage() << "is opaque gray, using PNG_COLOR_TYPE_GRAY");
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
- diag->Note(android::DiagMessage() << "is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA");
+ diag->Note(DiagMessage() << "is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA");
break;
case PNG_COLOR_TYPE_RGB:
- diag->Note(android::DiagMessage() << "is opaque RGB, using PNG_COLOR_TYPE_RGB");
+ diag->Note(DiagMessage() << "is opaque RGB, using PNG_COLOR_TYPE_RGB");
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
- diag->Note(android::DiagMessage() << "is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA");
+ diag->Note(DiagMessage() << "is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA");
break;
}
}
- png_set_IHDR(writePtr, infoPtr, info->width, info->height, 8, colorType,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
+ png_set_IHDR(writePtr, infoPtr, info->width, info->height, 8, colorType, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
if (colorType == PNG_COLOR_TYPE_PALETTE) {
png_set_PLTE(writePtr, infoPtr, rgbPalette, paletteEntries);
if (hasTransparency) {
- png_set_tRNS(writePtr, infoPtr, alphaPalette, paletteEntries,
- (png_color_16p)0);
+ png_set_tRNS(writePtr, infoPtr, alphaPalette, paletteEntries, (png_color_16p)0);
}
png_set_filter(writePtr, 0, PNG_NO_FILTERS);
} else {
@@ -526,13 +508,12 @@
// Chunks ordered thusly because older platforms depend on the base 9 patch
// data being last
- png_bytep chunkNames = info->haveLayoutBounds
- ? (png_bytep) "npOl\0npLb\0npTc\0"
- : (png_bytep) "npOl\0npTc";
+ png_bytep chunkNames =
+ info->haveLayoutBounds ? (png_bytep) "npOl\0npLb\0npTc\0" : (png_bytep) "npOl\0npTc";
// base 9 patch data
if (kDebug) {
- diag->Note(android::DiagMessage() << "adding 9-patch info..");
+ diag->Note(DiagMessage() << "adding 9-patch info..");
}
memcpy((char*)unknowns[pIndex].name, "npTc", 5);
unknowns[pIndex].data = (png_byte*)info->serialize9Patch();
@@ -563,8 +544,7 @@
for (int i = 0; i < chunkCount; i++) {
unknowns[i].location = PNG_HAVE_PLTE;
}
- png_set_keep_unknown_chunks(writePtr, PNG_HANDLE_CHUNK_ALWAYS, chunkNames,
- chunkCount);
+ png_set_keep_unknown_chunks(writePtr, PNG_HANDLE_CHUNK_ALWAYS, chunkNames, chunkCount);
png_set_unknown_chunks(writePtr, infoPtr, unknowns, chunkCount);
#if PNG_LIBPNG_VER < 10600
@@ -579,8 +559,7 @@
png_write_info(writePtr, infoPtr);
png_bytepp rows;
- if (colorType == PNG_COLOR_TYPE_RGB ||
- colorType == PNG_COLOR_TYPE_RGB_ALPHA) {
+ if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) {
if (colorType == PNG_COLOR_TYPE_RGB) {
png_set_filler(writePtr, 0, PNG_FILLER_AFTER);
}
@@ -605,14 +584,13 @@
free(unknowns[1].data);
free(unknowns[2].data);
- png_get_IHDR(writePtr, infoPtr, &width, &height, &bitDepth, &colorType,
- &interlaceType, &compressionType, nullptr);
+ png_get_IHDR(writePtr, infoPtr, &width, &height, &bitDepth, &colorType, &interlaceType,
+ &compressionType, nullptr);
if (kDebug) {
- diag->Note(android::DiagMessage()
- << "image written: w = " << width << ", h = " << height << ", d = " << bitDepth
- << ", colors = " << colorType << ", inter = " << interlaceType
- << ", comp = " << compressionType);
+ diag->Note(DiagMessage() << "image written: w = " << width << ", h = " << height
+ << ", d = " << bitDepth << ", colors = " << colorType
+ << ", inter = " << interlaceType << ", comp = " << compressionType);
}
return true;
}
@@ -673,9 +651,8 @@
enum class TickState { kStart, kInside1, kOutside1 };
-static bool getHorizontalTicks(png_bytep row, int width, bool transparent,
- bool required, int32_t* outLeft,
- int32_t* outRight, const char** outError,
+static bool getHorizontalTicks(png_bytep row, int width, bool transparent, bool required,
+ int32_t* outLeft, int32_t* outRight, const char** outError,
uint8_t* outDivs, bool multipleAllowed) {
*outLeft = *outRight = -1;
TickState state = TickState::kStart;
@@ -683,8 +660,7 @@
for (int i = 1; i < width - 1; i++) {
if (tickType(row + i * 4, transparent, outError) == TickType::kTick) {
- if (state == TickState::kStart ||
- (state == TickState::kOutside1 && multipleAllowed)) {
+ if (state == TickState::kStart || (state == TickState::kOutside1 && multipleAllowed)) {
*outLeft = i - 1;
*outRight = width - 2;
found = true;
@@ -719,18 +695,16 @@
return true;
}
-static bool getVerticalTicks(png_bytepp rows, int offset, int height,
- bool transparent, bool required, int32_t* outTop,
- int32_t* outBottom, const char** outError,
- uint8_t* outDivs, bool multipleAllowed) {
+static bool getVerticalTicks(png_bytepp rows, int offset, int height, bool transparent,
+ bool required, int32_t* outTop, int32_t* outBottom,
+ const char** outError, uint8_t* outDivs, bool multipleAllowed) {
*outTop = *outBottom = -1;
TickState state = TickState::kStart;
bool found = false;
for (int i = 1; i < height - 1; i++) {
if (tickType(rows[i] + offset, transparent, outError) == TickType::kTick) {
- if (state == TickState::kStart ||
- (state == TickState::kOutside1 && multipleAllowed)) {
+ if (state == TickState::kStart || (state == TickState::kOutside1 && multipleAllowed)) {
*outTop = i - 1;
*outBottom = height - 2;
found = true;
@@ -765,10 +739,8 @@
return true;
}
-static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width,
- bool transparent,
- bool /* required */,
- int32_t* outLeft, int32_t* outRight,
+static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width, bool transparent,
+ bool /* required */, int32_t* outLeft, int32_t* outRight,
const char** outError) {
*outLeft = *outRight = 0;
@@ -779,23 +751,20 @@
while (i < width - 1) {
(*outLeft)++;
i++;
- if (tickType(row + i * 4, transparent, outError) !=
- TickType::kLayoutBounds) {
+ if (tickType(row + i * 4, transparent, outError) != TickType::kLayoutBounds) {
break;
}
}
}
// Look for right tick
- if (tickType(row + (width - 2) * 4, transparent, outError) ==
- TickType::kLayoutBounds) {
+ if (tickType(row + (width - 2) * 4, transparent, outError) == TickType::kLayoutBounds) {
// Ending with a layout padding tick
int i = width - 2;
while (i > 1) {
(*outRight)++;
i--;
- if (tickType(row + i * 4, transparent, outError) !=
- TickType::kLayoutBounds) {
+ if (tickType(row + i * 4, transparent, outError) != TickType::kLayoutBounds) {
break;
}
}
@@ -803,38 +772,32 @@
return true;
}
-static bool getVerticalLayoutBoundsTicks(png_bytepp rows, int offset,
- int height, bool transparent,
- bool /* required */, int32_t* outTop,
- int32_t* outBottom,
+static bool getVerticalLayoutBoundsTicks(png_bytepp rows, int offset, int height, bool transparent,
+ bool /* required */, int32_t* outTop, int32_t* outBottom,
const char** outError) {
*outTop = *outBottom = 0;
// Look for top tick
- if (tickType(rows[1] + offset, transparent, outError) ==
- TickType::kLayoutBounds) {
+ if (tickType(rows[1] + offset, transparent, outError) == TickType::kLayoutBounds) {
// Starting with a layout padding tick
int i = 1;
while (i < height - 1) {
(*outTop)++;
i++;
- if (tickType(rows[i] + offset, transparent, outError) !=
- TickType::kLayoutBounds) {
+ if (tickType(rows[i] + offset, transparent, outError) != TickType::kLayoutBounds) {
break;
}
}
}
// Look for bottom tick
- if (tickType(rows[height - 2] + offset, transparent, outError) ==
- TickType::kLayoutBounds) {
+ if (tickType(rows[height - 2] + offset, transparent, outError) == TickType::kLayoutBounds) {
// Ending with a layout padding tick
int i = height - 2;
while (i > 1) {
(*outBottom)++;
i--;
- if (tickType(rows[i] + offset, transparent, outError) !=
- TickType::kLayoutBounds) {
+ if (tickType(rows[i] + offset, transparent, outError) != TickType::kLayoutBounds) {
break;
}
}
@@ -842,13 +805,12 @@
return true;
}
-static void findMaxOpacity(png_bytepp rows, int startX, int startY, int endX,
- int endY, int dX, int dY, int* outInset) {
+static void findMaxOpacity(png_bytepp rows, int startX, int startY, int endX, int endY, int dX,
+ int dY, int* outInset) {
uint8_t maxOpacity = 0;
int inset = 0;
*outInset = 0;
- for (int x = startX, y = startY; x != endX && y != endY;
- x += dX, y += dY, inset++) {
+ for (int x = startX, y = startY; x != endX && y != endY; x += dX, y += dY, inset++) {
png_byte* color = rows[y] + x * 4;
uint8_t opacity = color[3];
if (opacity > maxOpacity) {
@@ -868,8 +830,7 @@
return maxAlpha;
}
-static uint8_t maxAlphaOverCol(png_bytepp rows, int offsetX, int startY,
- int endY) {
+static uint8_t maxAlphaOverCol(png_bytepp rows, int offsetX, int startY, int endY) {
uint8_t maxAlpha = 0;
for (int y = startY; y < endY; y++) {
uint8_t alpha = (rows[y] + offsetX * 4)[3];
@@ -886,10 +847,8 @@
// find left and right extent of nine patch content on center row
if (image->width > 4) {
- findMaxOpacity(image->rows.data(), 1, midY, midX, -1, 1, 0,
- &image->outlineInsetsLeft);
- findMaxOpacity(image->rows.data(), endX, midY, midX, -1, -1, 0,
- &image->outlineInsetsRight);
+ findMaxOpacity(image->rows.data(), 1, midY, midX, -1, 1, 0, &image->outlineInsetsLeft);
+ findMaxOpacity(image->rows.data(), endX, midY, midX, -1, -1, 0, &image->outlineInsetsRight);
} else {
image->outlineInsetsLeft = 0;
image->outlineInsetsRight = 0;
@@ -897,10 +856,8 @@
// find top and bottom extent of nine patch content on center column
if (image->height > 4) {
- findMaxOpacity(image->rows.data(), midX, 1, -1, midY, 0, 1,
- &image->outlineInsetsTop);
- findMaxOpacity(image->rows.data(), midX, endY, -1, midY, 0, -1,
- &image->outlineInsetsBottom);
+ findMaxOpacity(image->rows.data(), midX, 1, -1, midY, 0, 1, &image->outlineInsetsTop);
+ findMaxOpacity(image->rows.data(), midX, endY, -1, midY, 0, -1, &image->outlineInsetsBottom);
} else {
image->outlineInsetsTop = 0;
image->outlineInsetsBottom = 0;
@@ -915,13 +872,13 @@
// assuming the image is a round rect, compute the radius by marching
// diagonally from the top left corner towards the center
- image->outlineAlpha = std::max(
- maxAlphaOverRow(image->rows[innerMidY], innerStartX, innerEndX),
- maxAlphaOverCol(image->rows.data(), innerMidX, innerStartY, innerStartY));
+ image->outlineAlpha =
+ std::max(maxAlphaOverRow(image->rows[innerMidY], innerStartX, innerEndX),
+ maxAlphaOverCol(image->rows.data(), innerMidX, innerStartY, innerStartY));
int diagonalInset = 0;
- findMaxOpacity(image->rows.data(), innerStartX, innerStartY, innerMidX,
- innerMidY, 1, 1, &diagonalInset);
+ findMaxOpacity(image->rows.data(), innerStartX, innerStartY, innerMidX, innerMidY, 1, 1,
+ &diagonalInset);
/* Determine source radius based upon inset:
* sqrt(r^2 + r^2) = sqrt(i^2 + i^2) + r
@@ -932,19 +889,17 @@
image->outlineRadius = 3.4142f * diagonalInset;
if (kDebug) {
- printf("outline insets %d %d %d %d, rad %f, alpha %x\n",
- image->outlineInsetsLeft, image->outlineInsetsTop,
- image->outlineInsetsRight, image->outlineInsetsBottom,
+ printf("outline insets %d %d %d %d, rad %f, alpha %x\n", image->outlineInsetsLeft,
+ image->outlineInsetsTop, image->outlineInsetsRight, image->outlineInsetsBottom,
image->outlineRadius, image->outlineAlpha);
}
}
-static uint32_t getColor(png_bytepp rows, int left, int top, int right,
- int bottom) {
+static uint32_t getColor(png_bytepp rows, int left, int top, int right, int bottom) {
png_bytep color = rows[top] + left * 4;
if (left > right || top > bottom) {
- return android::Res_png_9patch::TRANSPARENT_COLOR;
+ return Res_png_9patch::TRANSPARENT_COLOR;
}
while (top <= bottom) {
@@ -952,18 +907,17 @@
png_bytep p = rows[top] + i * 4;
if (color[3] == 0) {
if (p[3] != 0) {
- return android::Res_png_9patch::NO_COLOR;
+ return Res_png_9patch::NO_COLOR;
}
- } else if (p[0] != color[0] || p[1] != color[1] || p[2] != color[2] ||
- p[3] != color[3]) {
- return android::Res_png_9patch::NO_COLOR;
+ } else if (p[0] != color[0] || p[1] != color[1] || p[2] != color[2] || p[3] != color[3]) {
+ return Res_png_9patch::NO_COLOR;
}
}
top++;
}
if (color[3] == 0) {
- return android::Res_png_9patch::TRANSPARENT_COLOR;
+ return Res_png_9patch::TRANSPARENT_COLOR;
}
return (color[3] << 24) | (color[0] << 16) | (color[1] << 8) | color[2];
}
@@ -1014,23 +968,22 @@
}
// Validate frame...
- if (!transparent &&
- (p[0] != 0xFF || p[1] != 0xFF || p[2] != 0xFF || p[3] != 0xFF)) {
+ if (!transparent && (p[0] != 0xFF || p[1] != 0xFF || p[2] != 0xFF || p[3] != 0xFF)) {
errorMsg = "Must have one-pixel frame that is either transparent or white";
goto getout;
}
// Find left and right of sizing areas...
- if (!getHorizontalTicks(p, W, transparent, true, &xDivs[0], &xDivs[1],
- &errorMsg, &numXDivs, true)) {
+ if (!getHorizontalTicks(p, W, transparent, true, &xDivs[0], &xDivs[1], &errorMsg, &numXDivs,
+ true)) {
errorPixel = xDivs[0];
errorEdge = "top";
goto getout;
}
// Find top and bottom of sizing areas...
- if (!getVerticalTicks(image->rows.data(), 0, H, transparent, true, &yDivs[0],
- &yDivs[1], &errorMsg, &numYDivs, true)) {
+ if (!getVerticalTicks(image->rows.data(), 0, H, transparent, true, &yDivs[0], &yDivs[1],
+ &errorMsg, &numYDivs, true)) {
errorPixel = yDivs[0];
errorEdge = "left";
goto getout;
@@ -1041,10 +994,8 @@
image->info9Patch.numYDivs = numYDivs;
// Find left and right of padding area...
- if (!getHorizontalTicks(image->rows[H - 1], W, transparent, false,
- &image->info9Patch.paddingLeft,
- &image->info9Patch.paddingRight, &errorMsg, nullptr,
- false)) {
+ if (!getHorizontalTicks(image->rows[H - 1], W, transparent, false, &image->info9Patch.paddingLeft,
+ &image->info9Patch.paddingRight, &errorMsg, nullptr, false)) {
errorPixel = image->info9Patch.paddingLeft;
errorEdge = "bottom";
goto getout;
@@ -1052,9 +1003,8 @@
// Find top and bottom of padding area...
if (!getVerticalTicks(image->rows.data(), (W - 1) * 4, H, transparent, false,
- &image->info9Patch.paddingTop,
- &image->info9Patch.paddingBottom, &errorMsg, nullptr,
- false)) {
+ &image->info9Patch.paddingTop, &image->info9Patch.paddingBottom, &errorMsg,
+ nullptr, false)) {
errorPixel = image->info9Patch.paddingTop;
errorEdge = "right";
goto getout;
@@ -1062,22 +1012,18 @@
// Find left and right of layout padding...
getHorizontalLayoutBoundsTicks(image->rows[H - 1], W, transparent, false,
- &image->layoutBoundsLeft,
- &image->layoutBoundsRight, &errorMsg);
+ &image->layoutBoundsLeft, &image->layoutBoundsRight, &errorMsg);
- getVerticalLayoutBoundsTicks(image->rows.data(), (W - 1) * 4, H, transparent,
- false, &image->layoutBoundsTop,
- &image->layoutBoundsBottom, &errorMsg);
+ getVerticalLayoutBoundsTicks(image->rows.data(), (W - 1) * 4, H, transparent, false,
+ &image->layoutBoundsTop, &image->layoutBoundsBottom, &errorMsg);
- image->haveLayoutBounds =
- image->layoutBoundsLeft != 0 || image->layoutBoundsRight != 0 ||
- image->layoutBoundsTop != 0 || image->layoutBoundsBottom != 0;
+ image->haveLayoutBounds = image->layoutBoundsLeft != 0 || image->layoutBoundsRight != 0 ||
+ image->layoutBoundsTop != 0 || image->layoutBoundsBottom != 0;
if (image->haveLayoutBounds) {
if (kDebug) {
- printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft,
- image->layoutBoundsTop, image->layoutBoundsRight,
- image->layoutBoundsBottom);
+ printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop,
+ image->layoutBoundsRight, image->layoutBoundsBottom);
}
}
@@ -1189,7 +1135,7 @@
c = getColor(image->rows.data(), left, top, right - 1, bottom - 1);
image->colors[colorIndex++] = c;
if (kDebug) {
- if (c != android::Res_png_9patch::NO_COLOR) {
+ if (c != Res_png_9patch::NO_COLOR) {
hasColor = true;
}
}
@@ -1214,8 +1160,7 @@
if (errorEdge) {
err << "." << std::endl;
if (errorPixel >= 0) {
- err << "Found at pixel #" << errorPixel << " along " << errorEdge
- << " edge";
+ err << "Found at pixel #" << errorPixel << " along " << errorEdge << " edge";
} else {
err << "Found along " << errorEdge << " edge";
}
@@ -1226,20 +1171,19 @@
return true;
}
-bool Png::process(const android::Source& source, std::istream* input, android::BigBuffer* outBuffer,
+bool Png::process(const Source& source, std::istream* input, BigBuffer* outBuffer,
const PngOptions& options) {
- TRACE_CALL();
png_byte signature[kPngSignatureSize];
// Read the PNG signature first.
if (!input->read(reinterpret_cast<char*>(signature), kPngSignatureSize)) {
- mDiag->Error(android::DiagMessage() << strerror(errno));
+ mDiag->Error(DiagMessage() << strerror(errno));
return false;
}
// If the PNG signature doesn't match, bail early.
if (png_sig_cmp(signature, 0, kPngSignatureSize) != 0) {
- mDiag->Error(android::DiagMessage() << "not a valid png file");
+ mDiag->Error(DiagMessage() << "not a valid png file");
return false;
}
@@ -1252,18 +1196,17 @@
readPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr);
if (!readPtr) {
- mDiag->Error(android::DiagMessage() << "failed to allocate read ptr");
+ mDiag->Error(DiagMessage() << "failed to allocate read ptr");
goto bail;
}
infoPtr = png_create_info_struct(readPtr);
if (!infoPtr) {
- mDiag->Error(android::DiagMessage() << "failed to allocate info ptr");
+ mDiag->Error(DiagMessage() << "failed to allocate info ptr");
goto bail;
}
- png_set_error_fn(readPtr, reinterpret_cast<png_voidp>(mDiag), nullptr,
- logWarning);
+ png_set_error_fn(readPtr, reinterpret_cast<png_voidp>(mDiag), nullptr, logWarning);
// Set the read function to read from std::istream.
png_set_read_fn(readPtr, (png_voidp)input, readDataFromStream);
@@ -1272,35 +1215,32 @@
goto bail;
}
- if (util::EndsWith(source.path, ".9.png")) {
+ if (android::base::EndsWith(source.path, ".9.png")) {
std::string errorMsg;
if (!do9Patch(&pngInfo, &errorMsg)) {
- mDiag->Error(android::DiagMessage() << errorMsg);
+ mDiag->Error(DiagMessage() << errorMsg);
goto bail;
}
}
- writePtr =
- png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr);
+ writePtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr);
if (!writePtr) {
- mDiag->Error(android::DiagMessage() << "failed to allocate write ptr");
+ mDiag->Error(DiagMessage() << "failed to allocate write ptr");
goto bail;
}
writeInfoPtr = png_create_info_struct(writePtr);
if (!writeInfoPtr) {
- mDiag->Error(android::DiagMessage() << "failed to allocate write info ptr");
+ mDiag->Error(DiagMessage() << "failed to allocate write info ptr");
goto bail;
}
png_set_error_fn(writePtr, nullptr, nullptr, logWarning);
// Set the write function to write to std::ostream.
- png_set_write_fn(writePtr, (png_voidp)outBuffer, writeDataToStream,
- flushDataToStream);
+ png_set_write_fn(writePtr, (png_voidp)outBuffer, writeDataToStream, flushDataToStream);
- if (!writePng(mDiag, writePtr, writeInfoPtr, &pngInfo,
- options.grayscale_tolerance)) {
+ if (!writePng(mDiag, writePtr, writeInfoPtr, &pngInfo, options.grayscale_tolerance)) {
goto bail;
}
@@ -1316,4 +1256,4 @@
return result;
}
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/libs/androidfw/PngChunkFilter.cpp
similarity index 95%
rename from tools/aapt2/compile/PngChunkFilter.cpp
rename to libs/androidfw/PngChunkFilter.cpp
index 2e55d0c..331b948 100644
--- a/tools/aapt2/compile/PngChunkFilter.cpp
+++ b/libs/androidfw/PngChunkFilter.cpp
@@ -14,25 +14,22 @@
* limitations under the License.
*/
-#include "compile/Png.h"
-
#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "androidfw/Png.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
-#include "io/Io.h"
-
-using ::android::StringPiece;
using ::android::base::StringPrintf;
-namespace aapt {
+namespace android {
static constexpr const char* kPngSignature = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
// Useful helper function that encodes individual bytes into a uint32
// at compile time.
constexpr uint32_t u32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
- return (((uint32_t)a) << 24) | (((uint32_t)b) << 16) | (((uint32_t)c) << 8) |
- ((uint32_t)d);
+ return (((uint32_t)a) << 24) | (((uint32_t)b) << 16) | (((uint32_t)c) << 8) | ((uint32_t)d);
}
// Allow list of PNG chunk types that we want to keep in the resulting PNG.
@@ -71,7 +68,7 @@
}
PngChunkFilter::PngChunkFilter(StringPiece data) : data_(data) {
- if (util::StartsWith(data_, kPngSignature)) {
+ if (android::base::StartsWith(data_, kPngSignature)) {
window_start_ = 0;
window_end_ = kPngSignatureSize;
} else {
@@ -176,5 +173,4 @@
window_end_ = kPngSignatureSize;
return true;
}
-
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/compile/PngCrunch.cpp b/libs/androidfw/PngCrunch.cpp
similarity index 87%
rename from tools/aapt2/compile/PngCrunch.cpp
rename to libs/androidfw/PngCrunch.cpp
index 4ef87ba..cf3c0ee 100644
--- a/tools/aapt2/compile/PngCrunch.cpp
+++ b/libs/androidfw/PngCrunch.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "compile/Png.h"
-
#include <png.h>
#include <zlib.h>
@@ -26,16 +24,16 @@
#include "android-base/errors.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
+#include "androidfw/Png.h"
-#include "trace/TraceBuffer.h"
-
-namespace aapt {
+namespace android {
// Custom deleter that destroys libpng read and info structs.
class PngReadStructDeleter {
public:
PngReadStructDeleter(png_structp read_ptr, png_infop info_ptr)
- : read_ptr_(read_ptr), info_ptr_(info_ptr) {}
+ : read_ptr_(read_ptr), info_ptr_(info_ptr) {
+ }
~PngReadStructDeleter() {
png_destroy_read_struct(&read_ptr_, &info_ptr_, nullptr);
@@ -52,7 +50,8 @@
class PngWriteStructDeleter {
public:
PngWriteStructDeleter(png_structp write_ptr, png_infop info_ptr)
- : write_ptr_(write_ptr), info_ptr_(info_ptr) {}
+ : write_ptr_(write_ptr), info_ptr_(info_ptr) {
+ }
~PngWriteStructDeleter() {
png_destroy_write_struct(&write_ptr_, &info_ptr_);
@@ -83,7 +82,7 @@
}
static void ReadDataFromStream(png_structp png_ptr, png_bytep buffer, png_size_t len) {
- io::InputStream* in = (io::InputStream*)png_get_io_ptr(png_ptr);
+ InputStream* in = (InputStream*)png_get_io_ptr(png_ptr);
const void* in_buffer;
size_t in_len;
@@ -108,7 +107,7 @@
}
static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t len) {
- io::OutputStream* out = (io::OutputStream*)png_get_io_ptr(png_ptr);
+ OutputStream* out = (OutputStream*)png_get_io_ptr(png_ptr);
void* out_buffer;
size_t out_len;
@@ -143,28 +142,22 @@
}
}
-std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& source,
- io::InputStream* in) {
- TRACE_CALL();
- // Create a diagnostics that has the source information encoded.
- android::SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
-
+std::unique_ptr<Image> ReadPng(InputStream* in, IDiagnostics* diag) {
// Read the first 8 bytes of the file looking for the PNG signature.
// Bail early if it does not match.
const png_byte* signature;
size_t buffer_size;
if (!in->Next((const void**)&signature, &buffer_size)) {
if (in->HadError()) {
- source_diag.Error(android::DiagMessage()
- << "failed to read PNG signature: " << in->GetError());
+ diag->Error(android::DiagMessage() << "failed to read PNG signature: " << in->GetError());
} else {
- source_diag.Error(android::DiagMessage() << "not enough data for PNG signature");
+ diag->Error(android::DiagMessage() << "not enough data for PNG signature");
}
return {};
}
if (buffer_size < kPngSignatureSize || png_sig_cmp(signature, 0, kPngSignatureSize) != 0) {
- source_diag.Error(android::DiagMessage() << "file signature does not match PNG signature");
+ diag->Error(android::DiagMessage() << "file signature does not match PNG signature");
return {};
}
@@ -176,14 +169,14 @@
// version of libpng.
png_structp read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (read_ptr == nullptr) {
- source_diag.Error(android::DiagMessage() << "failed to create libpng read png_struct");
+ diag->Error(android::DiagMessage() << "failed to create libpng read png_struct");
return {};
}
// Create and initialize the memory for image header and data.
png_infop info_ptr = png_create_info_struct(read_ptr);
if (info_ptr == nullptr) {
- source_diag.Error(android::DiagMessage() << "failed to create libpng read png_info");
+ diag->Error(android::DiagMessage() << "failed to create libpng read png_info");
png_destroy_read_struct(&read_ptr, nullptr, nullptr);
return {};
}
@@ -199,7 +192,7 @@
}
// Handle warnings ourselves via IDiagnostics.
- png_set_error_fn(read_ptr, (png_voidp)&source_diag, LogError, LogWarning);
+ png_set_error_fn(read_ptr, (png_voidp)&diag, LogError, LogWarning);
// Set up the read functions which read from our custom data sources.
png_set_read_fn(read_ptr, (png_voidp)in, ReadDataFromStream);
@@ -213,8 +206,8 @@
// Extract image meta-data from the various chunk headers.
uint32_t width, height;
int bit_depth, color_type, interlace_method, compression_method, filter_method;
- png_get_IHDR(read_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
- &interlace_method, &compression_method, &filter_method);
+ png_get_IHDR(read_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method,
+ &compression_method, &filter_method);
// When the image is read, expand it so that it is in RGBA 8888 format
// so that image handling is uniform.
@@ -239,8 +232,7 @@
png_set_add_alpha(read_ptr, 0xFF, PNG_FILLER_AFTER);
}
- if (color_type == PNG_COLOR_TYPE_GRAY ||
- color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(read_ptr);
}
@@ -256,12 +248,12 @@
// something
// that can always be represented by 9-patch.
if (width > std::numeric_limits<int32_t>::max() || height > std::numeric_limits<int32_t>::max()) {
- source_diag.Error(android::DiagMessage()
- << "PNG image dimensions are too large: " << width << "x" << height);
+ diag->Error(android::DiagMessage()
+ << "PNG image dimensions are too large: " << width << "x" << height);
return {};
}
- std::unique_ptr<Image> output_image = util::make_unique<Image>();
+ std::unique_ptr<Image> output_image = std::make_unique<Image>();
output_image->width = static_cast<int32_t>(width);
output_image->height = static_cast<int32_t>(height);
@@ -272,7 +264,7 @@
output_image->data = std::unique_ptr<uint8_t[]>(new uint8_t[height * row_bytes]);
// Create an array of rows that index into the data block.
- output_image->rows = std::unique_ptr<uint8_t* []>(new uint8_t*[height]);
+ output_image->rows = std::unique_ptr<uint8_t*[]>(new uint8_t*[height]);
for (uint32_t h = 0; h < height; h++) {
output_image->rows[h] = output_image->data.get() + (h * row_bytes);
}
@@ -332,8 +324,7 @@
// This grayscale has alpha and can fit within a palette.
// See if it is worth fitting into a palette.
const size_t palette_threshold = palette_chunk_size + alpha_chunk_size +
- palette_data_chunk_size +
- kPaletteOverheadConstant;
+ palette_data_chunk_size + kPaletteOverheadConstant;
if (grayscale_alpha_data_chunk_size > palette_threshold) {
return PNG_COLOR_TYPE_PALETTE;
}
@@ -343,16 +334,14 @@
if (color_palette_size <= 256 && !has_nine_patch) {
// This image can fit inside a palette. Let's see if it is worth it.
- size_t total_size_with_palette =
- palette_data_chunk_size + palette_chunk_size;
+ size_t total_size_with_palette = palette_data_chunk_size + palette_chunk_size;
size_t total_size_without_palette = color_data_chunk_size;
if (alpha_palette_size > 0) {
total_size_with_palette += alpha_palette_size;
total_size_without_palette = color_alpha_data_chunk_size;
}
- if (total_size_without_palette >
- total_size_with_palette + kPaletteOverheadConstant) {
+ if (total_size_without_palette > total_size_with_palette + kPaletteOverheadConstant) {
return PNG_COLOR_TYPE_PALETTE;
}
}
@@ -482,26 +471,22 @@
png_set_unknown_chunks(write_ptr, write_info_ptr, unknown_chunks, index);
}
-bool WritePng(IAaptContext* context, const Image* image,
- const NinePatch* nine_patch, io::OutputStream* out,
- const PngOptions& options) {
- TRACE_CALL();
+bool WritePng(const Image* image, const NinePatch* nine_patch, OutputStream* out,
+ const PngOptions& options, IDiagnostics* diag, bool verbose) {
// Create and initialize the write png_struct with the default error and
// warning handlers.
// The header version is also passed in to ensure that this was built against the same
// version of libpng.
png_structp write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (write_ptr == nullptr) {
- context->GetDiagnostics()->Error(android::DiagMessage()
- << "failed to create libpng write png_struct");
+ diag->Error(android::DiagMessage() << "failed to create libpng write png_struct");
return false;
}
// Allocate memory to store image header data.
png_infop write_info_ptr = png_create_info_struct(write_ptr);
if (write_info_ptr == nullptr) {
- context->GetDiagnostics()->Error(android::DiagMessage()
- << "failed to create libpng write png_info");
+ diag->Error(android::DiagMessage() << "failed to create libpng write png_info");
png_destroy_write_struct(&write_ptr, nullptr);
return false;
}
@@ -516,7 +501,7 @@
}
// Handle warnings with our IDiagnostics.
- png_set_error_fn(write_ptr, (png_voidp)context->GetDiagnostics(), LogError, LogWarning);
+ png_set_error_fn(write_ptr, (png_voidp)&diag, LogError, LogWarning);
// Set up the write functions which write to our custom data sources.
png_set_write_fn(write_ptr, (png_voidp)out, WriteDataToStream, nullptr);
@@ -578,22 +563,21 @@
}
}
- if (context->IsVerbose()) {
+ if (verbose) {
android::DiagMessage msg;
- msg << " paletteSize=" << color_palette.size()
- << " alphaPaletteSize=" << alpha_palette.size()
+ msg << " paletteSize=" << color_palette.size() << " alphaPaletteSize=" << alpha_palette.size()
<< " maxGrayDeviation=" << max_gray_deviation
<< " grayScale=" << (grayscale ? "true" : "false");
- context->GetDiagnostics()->Note(msg);
+ diag->Note(msg);
}
const bool convertible_to_grayscale = max_gray_deviation <= options.grayscale_tolerance;
- const int new_color_type = PickColorType(
- image->width, image->height, grayscale, convertible_to_grayscale,
- nine_patch != nullptr, color_palette.size(), alpha_palette.size());
+ const int new_color_type =
+ PickColorType(image->width, image->height, grayscale, convertible_to_grayscale,
+ nine_patch != nullptr, color_palette.size(), alpha_palette.size());
- if (context->IsVerbose()) {
+ if (verbose) {
android::DiagMessage msg;
msg << "encoding PNG ";
if (nine_patch) {
@@ -619,12 +603,11 @@
msg << "unknown type " << new_color_type;
break;
}
- context->GetDiagnostics()->Note(msg);
+ diag->Note(msg);
}
- png_set_IHDR(write_ptr, write_info_ptr, image->width, image->height, 8,
- new_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
+ png_set_IHDR(write_ptr, write_info_ptr, image->width, image->height, 8, new_color_type,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
if (new_color_type & PNG_COLOR_MASK_PALETTE) {
// Assigns indices to the palette, and writes the encoded palette to the
@@ -666,11 +649,9 @@
}
png_write_row(write_ptr, out_row.get());
}
- } else if (new_color_type == PNG_COLOR_TYPE_GRAY ||
- new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ } else if (new_color_type == PNG_COLOR_TYPE_GRAY || new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
const size_t bpp = new_color_type == PNG_COLOR_TYPE_GRAY ? 1 : 2;
- auto out_row =
- std::unique_ptr<png_byte[]>(new png_byte[image->width * bpp]);
+ auto out_row = std::unique_ptr<png_byte[]>(new png_byte[image->width * bpp]);
for (int32_t y = 0; y < image->height; y++) {
png_const_bytep in_row = image->rows[y];
@@ -691,8 +672,7 @@
// The image is convertible to grayscale, use linear-luminance of
// sRGB colorspace:
// https://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-preserving.29_conversion_to_grayscale
- out_row[x * bpp] =
- (png_byte)(rr * 0.2126f + gg * 0.7152f + bb * 0.0722f);
+ out_row[x * bpp] = (png_byte)(rr * 0.2126f + gg * 0.7152f + bb * 0.0722f);
}
if (bpp == 2) {
@@ -747,4 +727,4 @@
return true;
}
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/io/BigBufferStream.h b/libs/androidfw/include/androidfw/BigBufferStream.h
similarity index 74%
rename from tools/aapt2/io/BigBufferStream.h
rename to libs/androidfw/include/androidfw/BigBufferStream.h
index 63a5e57..e55fe0d 100644
--- a/tools/aapt2/io/BigBufferStream.h
+++ b/libs/androidfw/include/androidfw/BigBufferStream.h
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-#ifndef AAPT_IO_BIGBUFFERSTREAM_H
-#define AAPT_IO_BIGBUFFERSTREAM_H
+#pragma once
-#include "androidfw/BigBuffer.h"
-#include "io/Io.h"
+#include "BigBuffer.h"
+#include "Streams.h"
-namespace aapt {
-namespace io {
+namespace android {
class BigBufferInputStream : public KnownSizeInputStream {
public:
- inline explicit BigBufferInputStream(const android::BigBuffer* buffer)
+ inline explicit BigBufferInputStream(const BigBuffer* buffer)
: buffer_(buffer), iter_(buffer->begin()) {
}
virtual ~BigBufferInputStream() = default;
@@ -44,18 +42,20 @@
size_t TotalSize() const override;
+ bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(BigBufferInputStream);
- const android::BigBuffer* buffer_;
- android::BigBuffer::const_iterator iter_;
+ const BigBuffer* buffer_;
+ BigBuffer::const_iterator iter_;
size_t offset_ = 0;
size_t bytes_read_ = 0;
};
class BigBufferOutputStream : public OutputStream {
public:
- inline explicit BigBufferOutputStream(android::BigBuffer* buffer) : buffer_(buffer) {
+ inline explicit BigBufferOutputStream(BigBuffer* buffer) : buffer_(buffer) {
}
virtual ~BigBufferOutputStream() = default;
@@ -70,10 +70,7 @@
private:
DISALLOW_COPY_AND_ASSIGN(BigBufferOutputStream);
- android::BigBuffer* buffer_;
+ BigBuffer* buffer_;
};
-} // namespace io
-} // namespace aapt
-
-#endif // AAPT_IO_BIGBUFFERSTREAM_H
+} // namespace android
\ No newline at end of file
diff --git a/tools/aapt2/io/FileStream.h b/libs/androidfw/include/androidfw/FileStream.h
similarity index 93%
rename from tools/aapt2/io/FileStream.h
rename to libs/androidfw/include/androidfw/FileStream.h
index 62d910f..fb84a91 100644
--- a/tools/aapt2/io/FileStream.h
+++ b/libs/androidfw/include/androidfw/FileStream.h
@@ -14,19 +14,16 @@
* limitations under the License.
*/
-#ifndef AAPT_IO_FILESTREAM_H
-#define AAPT_IO_FILESTREAM_H
-
-#include "io/Io.h"
+#pragma once
#include <memory>
#include <string>
+#include "Streams.h"
#include "android-base/macros.h"
#include "android-base/unique_fd.h"
-namespace aapt {
-namespace io {
+namespace android {
constexpr size_t kDefaultBufferCapacity = 4096u;
@@ -48,6 +45,8 @@
std::string GetError() const override;
+ bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(FileInputStream);
@@ -101,7 +100,4 @@
size_t total_byte_count_ = 0u;
};
-} // namespace io
-} // namespace aapt
-
-#endif // AAPT_IO_FILESTREAM_H
+} // namespace android
\ No newline at end of file
diff --git a/tools/aapt2/compile/Image.h b/libs/androidfw/include/androidfw/Image.h
similarity index 92%
rename from tools/aapt2/compile/Image.h
rename to libs/androidfw/include/androidfw/Image.h
index db0b945..c18c34c 100644
--- a/tools/aapt2/compile/Image.h
+++ b/libs/androidfw/include/androidfw/Image.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef AAPT_COMPILE_IMAGE_H
-#define AAPT_COMPILE_IMAGE_H
+#pragma once
#include <cstdint>
#include <memory>
@@ -24,7 +23,7 @@
#include "android-base/macros.h"
-namespace aapt {
+namespace android {
/**
* An in-memory image, loaded from disk, with pixels in RGBA_8888 format.
@@ -37,7 +36,7 @@
* A `height` sized array of pointers, where each element points to a
* `width` sized row of RGBA_8888 pixels.
*/
- std::unique_ptr<uint8_t* []> rows;
+ std::unique_ptr<uint8_t*[]> rows;
/**
* The width of the image in RGBA_8888 pixels. This is int32_t because of
@@ -72,7 +71,8 @@
int32_t end = 0;
explicit Range() = default;
- inline explicit Range(int32_t s, int32_t e) : start(s), end(e) {}
+ inline explicit Range(int32_t s, int32_t e) : start(s), end(e) {
+ }
};
inline bool operator==(const Range& left, const Range& right) {
@@ -93,7 +93,8 @@
explicit Bounds() = default;
inline explicit Bounds(int32_t l, int32_t t, int32_t r, int32_t b)
- : left(l), top(t), right(r), bottom(b) {}
+ : left(l), top(t), right(r), bottom(b) {
+ }
bool nonZero() const;
};
@@ -103,8 +104,8 @@
}
inline bool operator==(const Bounds& left, const Bounds& right) {
- return left.left == right.left && left.top == right.top &&
- left.right == right.right && left.bottom == right.bottom;
+ return left.left == right.left && left.top == right.top && left.right == right.right &&
+ left.bottom == right.bottom;
}
/**
@@ -115,8 +116,7 @@
class NinePatch {
public:
static std::unique_ptr<NinePatch> Create(uint8_t** rows, const int32_t width,
- const int32_t height,
- std::string* err_out);
+ const int32_t height, std::string* err_out);
/**
* Packs the RGBA_8888 data pointed to by pixel into a uint32_t
@@ -204,6 +204,4 @@
::std::ostream& operator<<(::std::ostream& out, const Bounds& bounds);
::std::ostream& operator<<(::std::ostream& out, const NinePatch& nine_patch);
-} // namespace aapt
-
-#endif /* AAPT_COMPILE_IMAGE_H */
+} // namespace android
\ No newline at end of file
diff --git a/tools/aapt2/compile/Png.h b/libs/androidfw/include/androidfw/Png.h
similarity index 62%
rename from tools/aapt2/compile/Png.h
rename to libs/androidfw/include/androidfw/Png.h
index a8b7dd1..2ece43e 100644
--- a/tools/aapt2/compile/Png.h
+++ b/libs/androidfw/include/androidfw/Png.h
@@ -14,22 +14,18 @@
* limitations under the License.
*/
-#ifndef AAPT_PNG_H
-#define AAPT_PNG_H
+#pragma once
-#include <iostream>
#include <string>
+#include "BigBuffer.h"
+#include "IDiagnostics.h"
+#include "Image.h"
+#include "Source.h"
+#include "Streams.h"
#include "android-base/macros.h"
-#include "androidfw/BigBuffer.h"
-#include "androidfw/IDiagnostics.h"
-#include "androidfw/Source.h"
-#include "compile/Image.h"
-#include "io/Io.h"
-#include "process/IResourceTableConsumer.h"
-namespace aapt {
-
+namespace android {
// Size in bytes of the PNG signature.
constexpr size_t kPngSignatureSize = 8u;
@@ -42,32 +38,36 @@
*/
class Png {
public:
- explicit Png(android::IDiagnostics* diag) : mDiag(diag) {
+ explicit Png(IDiagnostics* diag) : mDiag(diag) {
}
- bool process(const android::Source& source, std::istream* input, android::BigBuffer* outBuffer,
+ bool process(const Source& source, std::istream* input, BigBuffer* outBuffer,
const PngOptions& options);
private:
DISALLOW_COPY_AND_ASSIGN(Png);
- android::IDiagnostics* mDiag;
+ IDiagnostics* mDiag;
};
/**
* An InputStream that filters out unimportant PNG chunks.
*/
-class PngChunkFilter : public io::InputStream {
+class PngChunkFilter : public InputStream {
public:
- explicit PngChunkFilter(android::StringPiece data);
+ explicit PngChunkFilter(StringPiece data);
virtual ~PngChunkFilter() = default;
bool Next(const void** buffer, size_t* len) override;
void BackUp(size_t count) override;
- bool CanRewind() const override { return true; }
+ bool CanRewind() const override {
+ return true;
+ }
bool Rewind() override;
- size_t ByteCount() const override { return window_start_; }
+ size_t ByteCount() const override {
+ return window_start_;
+ }
bool HadError() const override {
return !error_msg_.empty();
@@ -81,26 +81,20 @@
bool ConsumeWindow(const void** buffer, size_t* len);
- android::StringPiece data_;
+ StringPiece data_;
size_t window_start_ = 0;
size_t window_end_ = 0;
std::string error_msg_;
};
-
/**
* Reads a PNG from the InputStream into memory as an RGBA Image.
*/
-std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& source,
- io::InputStream* in);
+std::unique_ptr<Image> ReadPng(InputStream* in, IDiagnostics* diag);
/**
* Writes the RGBA Image, with optional 9-patch meta-data, into the OutputStream
* as a PNG.
*/
-bool WritePng(IAaptContext* context, const Image* image,
- const NinePatch* nine_patch, io::OutputStream* out,
- const PngOptions& options);
-
-} // namespace aapt
-
-#endif // AAPT_PNG_H
+bool WritePng(const Image* image, const NinePatch* nine_patch, OutputStream* out,
+ const PngOptions& options, IDiagnostics* diag, bool verbose);
+} // namespace android
\ No newline at end of file
diff --git a/tools/aapt2/io/Io.h b/libs/androidfw/include/androidfw/Streams.h
similarity index 86%
rename from tools/aapt2/io/Io.h
rename to libs/androidfw/include/androidfw/Streams.h
index e1df23a6..2daf0e2 100644
--- a/tools/aapt2/io/Io.h
+++ b/libs/androidfw/include/androidfw/Streams.h
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-#ifndef AAPT_IO_IO_H
-#define AAPT_IO_IO_H
+#pragma once
#include <string>
+#include "android-base/off64_t.h"
-namespace aapt {
-namespace io {
+namespace android {
// InputStream interface that mimics protobuf's ZeroCopyInputStream,
// with added error handling methods to better report issues.
@@ -41,21 +40,34 @@
virtual void BackUp(size_t count) = 0;
// Returns true if this InputStream can rewind. If so, Rewind() can be called.
- virtual bool CanRewind() const { return false; };
+ virtual bool CanRewind() const {
+ return false;
+ };
// Rewinds the stream to the beginning so it can be read again.
// Returns true if the rewind succeeded.
// This does nothing if CanRewind() returns false.
- virtual bool Rewind() { return false; }
+ virtual bool Rewind() {
+ return false;
+ }
// Returns the number of bytes that have been read from the stream.
virtual size_t ByteCount() const = 0;
// Returns an error message if HadError() returned true.
- virtual std::string GetError() const { return {}; }
+ virtual std::string GetError() const {
+ return {};
+ }
// Returns true if an error occurred. Errors are permanent.
virtual bool HadError() const = 0;
+
+ virtual bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
+ (void)data;
+ (void)byte_count;
+ (void)offset;
+ return false;
+ }
};
// A sub-InputStream interface that knows the total size of its stream.
@@ -87,13 +99,12 @@
virtual size_t ByteCount() const = 0;
// Returns an error message if HadError() returned true.
- virtual std::string GetError() const { return {}; }
+ virtual std::string GetError() const {
+ return {};
+ }
// Returns true if an error occurred. Errors are permanent.
virtual bool HadError() const = 0;
};
-} // namespace io
-} // namespace aapt
-
-#endif /* AAPT_IO_IO_H */
+} // namespace android
\ No newline at end of file
diff --git a/tools/aapt2/io/FileStream_test.cpp b/libs/androidfw/tests/FileStream_test.cpp
similarity index 95%
rename from tools/aapt2/io/FileStream_test.cpp
rename to libs/androidfw/tests/FileStream_test.cpp
index cc9cd28..9785975 100644
--- a/tools/aapt2/io/FileStream_test.cpp
+++ b/libs/androidfw/tests/FileStream_test.cpp
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#include "io/FileStream.h"
+#include "androidfw/FileStream.h"
+#include "androidfw/StringPiece.h"
#include "android-base/file.h"
#include "android-base/macros.h"
-#include "test/Test.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
using ::android::StringPiece;
using ::testing::Eq;
using ::testing::NotNull;
using ::testing::StrEq;
-namespace aapt {
-namespace io {
+namespace android {
TEST(FileInputStreamTest, NextAndBackup) {
std::string input = "this is a cool string";
@@ -123,5 +124,4 @@
EXPECT_THAT(actual, StrEq(input));
}
-} // namespace io
-} // namespace aapt
+} // namespace android
diff --git a/tools/aapt2/compile/NinePatch_test.cpp b/libs/androidfw/tests/NinePatch_test.cpp
similarity index 69%
rename from tools/aapt2/compile/NinePatch_test.cpp
rename to libs/androidfw/tests/NinePatch_test.cpp
index f54bb2e..7ee8e9e 100644
--- a/tools/aapt2/compile/NinePatch_test.cpp
+++ b/libs/androidfw/tests/NinePatch_test.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "compile/Image.h"
+#include "androidfw/Image.h"
+#include "androidfw/ResourceTypes.h"
+#include "gtest/gtest.h"
-#include "test/Test.h"
-
-namespace aapt {
+namespace android {
// Pixels are in RGBA_8888 packing.
@@ -33,16 +33,19 @@
#define TRANS "\x00\x00\x00\x00"
static uint8_t* k2x2[] = {
- (uint8_t*)WHITE WHITE, (uint8_t*)WHITE WHITE,
+ (uint8_t*)WHITE WHITE,
+ (uint8_t*)WHITE WHITE,
};
static uint8_t* kMixedNeutralColor3x3[] = {
- (uint8_t*)WHITE BLACK TRANS, (uint8_t*)TRANS RED TRANS,
+ (uint8_t*)WHITE BLACK TRANS,
+ (uint8_t*)TRANS RED TRANS,
(uint8_t*)WHITE WHITE WHITE,
};
static uint8_t* kTransparentNeutralColor3x3[] = {
- (uint8_t*)TRANS BLACK TRANS, (uint8_t*)BLACK RED BLACK,
+ (uint8_t*)TRANS BLACK TRANS,
+ (uint8_t*)BLACK RED BLACK,
(uint8_t*)TRANS BLACK TRANS,
};
@@ -66,55 +69,44 @@
};
static uint8_t* kPadding6x5[] = {
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE BLACK,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE BLACK, (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE,
(uint8_t*)WHITE WHITE BLACK BLACK WHITE WHITE,
};
static uint8_t* kLayoutBoundsWrongEdge3x3[] = {
- (uint8_t*)WHITE RED WHITE, (uint8_t*)RED WHITE WHITE,
+ (uint8_t*)WHITE RED WHITE,
+ (uint8_t*)RED WHITE WHITE,
(uint8_t*)WHITE WHITE WHITE,
};
static uint8_t* kLayoutBoundsNotEdgeAligned5x5[] = {
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE RED, (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
(uint8_t*)WHITE WHITE RED WHITE WHITE,
};
static uint8_t* kLayoutBounds5x5[] = {
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED,
(uint8_t*)WHITE RED WHITE RED WHITE,
};
static uint8_t* kAsymmetricLayoutBounds5x5[] = {
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
(uint8_t*)WHITE RED WHITE WHITE WHITE,
};
static uint8_t* kPaddingAndLayoutBounds5x5[] = {
- (uint8_t*)WHITE WHITE WHITE WHITE WHITE,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
- (uint8_t*)WHITE WHITE WHITE WHITE BLACK,
- (uint8_t*)WHITE WHITE WHITE WHITE RED,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED,
+ (uint8_t*)WHITE WHITE WHITE WHITE BLACK, (uint8_t*)WHITE WHITE WHITE WHITE RED,
(uint8_t*)WHITE RED BLACK RED WHITE,
};
static uint8_t* kColorfulImage5x5[] = {
- (uint8_t*)WHITE BLACK WHITE BLACK WHITE,
- (uint8_t*)BLACK RED BLUE GREEN WHITE,
- (uint8_t*)BLACK RED GREEN GREEN WHITE,
- (uint8_t*)WHITE TRANS BLUE GREEN WHITE,
+ (uint8_t*)WHITE BLACK WHITE BLACK WHITE, (uint8_t*)BLACK RED BLUE GREEN WHITE,
+ (uint8_t*)BLACK RED GREEN GREEN WHITE, (uint8_t*)WHITE TRANS BLUE GREEN WHITE,
(uint8_t*)WHITE WHITE WHITE WHITE WHITE,
};
@@ -145,33 +137,21 @@
};
static uint8_t* kOutlineOffsetTranslucent12x10[] = {
- (uint8_t*)
- WHITE WHITE WHITE BLACK BLACK BLACK BLACK BLACK BLACK BLACK BLACK WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE,
- (uint8_t*)
- WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE,
- (uint8_t*)
- WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE,
+ (uint8_t*)WHITE WHITE WHITE BLACK BLACK BLACK BLACK BLACK BLACK BLACK BLACK WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE,
+ (uint8_t*)WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE,
+ (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE,
};
static uint8_t* kOutlineRadius5x5[] = {
- (uint8_t*)WHITE BLACK BLACK BLACK WHITE,
- (uint8_t*)BLACK TRANS GREEN TRANS WHITE,
- (uint8_t*)BLACK GREEN GREEN GREEN WHITE,
- (uint8_t*)BLACK TRANS GREEN TRANS WHITE,
+ (uint8_t*)WHITE BLACK BLACK BLACK WHITE, (uint8_t*)BLACK TRANS GREEN TRANS WHITE,
+ (uint8_t*)BLACK GREEN GREEN GREEN WHITE, (uint8_t*)BLACK TRANS GREEN TRANS WHITE,
(uint8_t*)WHITE WHITE WHITE WHITE WHITE,
};
@@ -195,14 +175,12 @@
TEST(NinePatchTest, TransparentNeutralColor) {
std::string err;
- EXPECT_NE(nullptr,
- NinePatch::Create(kTransparentNeutralColor3x3, 3, 3, &err));
+ EXPECT_NE(nullptr, NinePatch::Create(kTransparentNeutralColor3x3, 3, 3, &err));
}
TEST(NinePatchTest, SingleStretchRegion) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kSingleStretch7x6, 7, 6, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kSingleStretch7x6, 7, 6, &err);
ASSERT_NE(nullptr, nine_patch);
ASSERT_EQ(1u, nine_patch->horizontal_stretch_regions.size());
@@ -214,8 +192,7 @@
TEST(NinePatchTest, MultipleStretchRegions) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kMultipleStretch10x7, 10, 7, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kMultipleStretch10x7, 10, 7, &err);
ASSERT_NE(nullptr, nine_patch);
ASSERT_EQ(3u, nine_patch->horizontal_stretch_regions.size());
@@ -231,16 +208,14 @@
TEST(NinePatchTest, InferPaddingFromStretchRegions) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kMultipleStretch10x7, 10, 7, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kMultipleStretch10x7, 10, 7, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(1, 0, 1, 0), nine_patch->padding);
}
TEST(NinePatchTest, Padding) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kPadding6x5, 6, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kPadding6x5, 6, 5, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->padding);
}
@@ -253,15 +228,13 @@
TEST(NinePatchTest, LayoutBoundsMustTouchEdges) {
std::string err;
- EXPECT_EQ(nullptr,
- NinePatch::Create(kLayoutBoundsNotEdgeAligned5x5, 5, 5, &err));
+ EXPECT_EQ(nullptr, NinePatch::Create(kLayoutBoundsNotEdgeAligned5x5, 5, 5, &err));
EXPECT_FALSE(err.empty());
}
TEST(NinePatchTest, LayoutBounds) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kLayoutBounds5x5, 5, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kLayoutBounds5x5, 5, 5, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->layout_bounds);
@@ -272,8 +245,7 @@
TEST(NinePatchTest, PaddingAndLayoutBounds) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kPaddingAndLayoutBounds5x5, 5, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kPaddingAndLayoutBounds5x5, 5, 5, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->padding);
EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->layout_bounds);
@@ -281,25 +253,20 @@
TEST(NinePatchTest, RegionColorsAreCorrect) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kColorfulImage5x5, 5, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kColorfulImage5x5, 5, 5, &err);
ASSERT_NE(nullptr, nine_patch);
std::vector<uint32_t> expected_colors = {
- NinePatch::PackRGBA((uint8_t*)RED),
- (uint32_t)android::Res_png_9patch::NO_COLOR,
- NinePatch::PackRGBA((uint8_t*)GREEN),
- (uint32_t)android::Res_png_9patch::TRANSPARENT_COLOR,
- NinePatch::PackRGBA((uint8_t*)BLUE),
- NinePatch::PackRGBA((uint8_t*)GREEN),
+ NinePatch::PackRGBA((uint8_t*)RED), (uint32_t)android::Res_png_9patch::NO_COLOR,
+ NinePatch::PackRGBA((uint8_t*)GREEN), (uint32_t)android::Res_png_9patch::TRANSPARENT_COLOR,
+ NinePatch::PackRGBA((uint8_t*)BLUE), NinePatch::PackRGBA((uint8_t*)GREEN),
};
EXPECT_EQ(expected_colors, nine_patch->region_colors);
}
TEST(NinePatchTest, OutlineFromOpaqueImage) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kOutlineOpaque10x10, 10, 10, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineOpaque10x10, 10, 10, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(2, 2, 2, 2), nine_patch->outline);
EXPECT_EQ(0x000000ffu, nine_patch->outline_alpha);
@@ -308,8 +275,7 @@
TEST(NinePatchTest, OutlineFromTranslucentImage) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kOutlineTranslucent10x10, 10, 10, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineTranslucent10x10, 10, 10, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(3, 3, 3, 3), nine_patch->outline);
EXPECT_EQ(0x000000b3u, nine_patch->outline_alpha);
@@ -337,8 +303,7 @@
TEST(NinePatchTest, OutlineRadius) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kOutlineRadius5x5, 5, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineRadius5x5, 5, 5, &err);
ASSERT_NE(nullptr, nine_patch);
EXPECT_EQ(Bounds(0, 0, 0, 0), nine_patch->outline);
EXPECT_EQ(3.4142f, nine_patch->outline_radius);
@@ -353,8 +318,7 @@
TEST(NinePatchTest, SerializePngEndianness) {
std::string err;
- std::unique_ptr<NinePatch> nine_patch =
- NinePatch::Create(kStretchAndPadding5x5, 5, 5, &err);
+ std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kStretchAndPadding5x5, 5, 5, &err);
ASSERT_NE(nullptr, nine_patch);
size_t len;
@@ -374,4 +338,4 @@
EXPECT_TRUE(BigEndianOne(cursor + 12));
}
-} // namespace aapt
+} // namespace android
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp
index e59bc95..37a7d74 100644
--- a/libs/hwui/Mesh.cpp
+++ b/libs/hwui/Mesh.cpp
@@ -90,8 +90,8 @@
FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount);
}
- SkASSERT(!fICount);
- SkASSERT(!fIOffset);
+ LOG_ALWAYS_FATAL_IF(mIndexCount != 0);
+ LOG_ALWAYS_FATAL_IF(mIndexOffset != 0);
}
if (!sm.ok()) {
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index c55066a..0275e4f 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -2,6 +2,7 @@
#include "SkStream.h"
#include "YuvToJpegEncoder.h"
#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
#include <hardware/hardware.h>
#include "graphics_jni_helpers.h"
@@ -295,7 +296,7 @@
}
///////////////////////////////////////////////////////////////////////////////
-using namespace android::ultrahdr;
+using namespace ultrahdr;
ultrahdr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
switch (aDataSpace & ADataSpace::STANDARD_MASK) {
diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h
index a3a3224..629f1e6 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.h
+++ b/libs/hwui/jni/YuvToJpegEncoder.h
@@ -108,7 +108,7 @@
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
+ static ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
/** Map data space (defined in DataSpace.java and data_space.h) to the transfer function
* used in JPEG/R
@@ -117,8 +117,8 @@
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(
- JNIEnv* env, int aDataSpace);
+ static ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(JNIEnv* env,
+ int aDataSpace);
};
#endif // _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index bf9419fe..4be282b 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -29,6 +29,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.IntArray;
import android.util.Log;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
@@ -330,7 +331,7 @@
* @hide
* Array of all usage types exposed in the SDK that applications can use.
*/
- public final static int[] SDK_USAGES = {
+ public static final IntArray SDK_USAGES = IntArray.wrap(new int[] {
USAGE_UNKNOWN,
USAGE_MEDIA,
USAGE_VOICE_COMMUNICATION,
@@ -347,14 +348,14 @@
USAGE_ASSISTANCE_SONIFICATION,
USAGE_GAME,
USAGE_ASSISTANT,
- };
+ });
/**
* @hide
*/
@TestApi
public static int[] getSdkUsages() {
- return SDK_USAGES;
+ return SDK_USAGES.toArray();
}
/**
@@ -567,6 +568,15 @@
private String mFormattedTags;
private Bundle mBundle; // lazy-initialized, may be null
+ /** Array of all content types exposed in the SDK that applications can use */
+ private static final IntArray CONTENT_TYPES = IntArray.wrap(new int[]{
+ CONTENT_TYPE_UNKNOWN,
+ CONTENT_TYPE_SPEECH,
+ CONTENT_TYPE_MUSIC,
+ CONTENT_TYPE_MOVIE,
+ CONTENT_TYPE_SONIFICATION,
+ });
+
private AudioAttributes() {
}
@@ -1669,6 +1679,27 @@
}
/**
+ * Query if the usage is a valid sdk usage
+ *
+ * @param usage one of {@link AttributeSdkUsage}
+ * @return {@code true} if the usage is valid for sdk or {@code false} otherwise
+ * @hide
+ */
+ public static boolean isSdkUsage(@AttributeSdkUsage int usage) {
+ return SDK_USAGES.contains(usage);
+ }
+
+ /**
+ * Query if the content type is a valid sdk content type
+ * @param contentType one of {@link AttributeContentType}
+ * @return {@code true} if the content type is valid for sdk or {@code false} otherwise
+ * @hide
+ */
+ public static boolean isSdkContentType(@AttributeContentType int contentType) {
+ return CONTENT_TYPES.contains(contentType);
+ }
+
+ /**
* Returns the stream type matching this {@code AudioAttributes} instance for volume control.
* Use this method to derive the stream type needed to configure the volume
* control slider in an {@link android.app.Activity} with
diff --git a/media/java/android/media/AudioHalVersionInfo.java b/media/java/android/media/AudioHalVersionInfo.java
index 0f48abeb..c881a03 100644
--- a/media/java/android/media/AudioHalVersionInfo.java
+++ b/media/java/android/media/AudioHalVersionInfo.java
@@ -80,9 +80,8 @@
* List of all valid Audio HAL versions. This list need to be in sync with sAudioHALVersions
* defined in frameworks/av/media/libaudiohal/FactoryHalHidl.cpp.
*/
- // TODO: add AIDL_1_0 with sAudioHALVersions.
public static final @NonNull List<AudioHalVersionInfo> VERSIONS =
- List.of(HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0, HIDL_4_0);
+ List.of(AIDL_1_0, HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0, HIDL_4_0);
private static final String TAG = "AudioHalVersionInfo";
private AudioHalVersion mHalVersion = new AudioHalVersion();
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 367b38a..9ffd644 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -318,11 +318,12 @@
/**
* @hide
- * Convert a Bluetooth codec to an audio format enum
+ * Convert an A2DP Bluetooth codec to an audio format enum
* @param btCodec the codec to convert.
* @return the audio format, or {@link #AUDIO_FORMAT_DEFAULT} if unknown
*/
- public static @AudioFormatNativeEnumForBtCodec int bluetoothCodecToAudioFormat(int btCodec) {
+ public static @AudioFormatNativeEnumForBtCodec int bluetoothA2dpCodecToAudioFormat(
+ int btCodec) {
switch (btCodec) {
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
return AudioSystem.AUDIO_FORMAT_SBC;
@@ -339,7 +340,25 @@
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS:
return AudioSystem.AUDIO_FORMAT_OPUS;
default:
- Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec)
+ Log.e(TAG, "Unknown A2DP BT codec 0x" + Integer.toHexString(btCodec)
+ + " for conversion to audio format");
+ // TODO returning DEFAULT is the current behavior, should this return INVALID?
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ }
+
+ /**
+ * @hide
+ * Convert a LE Audio Bluetooth codec to an audio format enum
+ * @param btCodec the codec to convert.
+ * @return the audio format, or {@link #AUDIO_FORMAT_DEFAULT} if unknown
+ */
+ public static @AudioFormatNativeEnumForBtCodec int bluetoothLeCodecToAudioFormat(int btCodec) {
+ switch (btCodec) {
+ case BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3:
+ return AudioSystem.AUDIO_FORMAT_LC3;
+ default:
+ Log.e(TAG, "Unknown LE Audio BT codec 0x" + Integer.toHexString(btCodec)
+ " for conversion to audio format");
// TODO returning DEFAULT is the current behavior, should this return INVALID?
return AudioSystem.AUDIO_FORMAT_DEFAULT;
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/media/java/android/media/FadeManagerConfiguration.aidl
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to media/java/android/media/FadeManagerConfiguration.aidl
index 4098987..ceb4ded 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/media/java/android/media/FadeManagerConfiguration.aidl
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package android.media;
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
-
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+/**
+ * Class to encapsulate fade configurations.
+ * @hide
+ */
+parcelable FadeManagerConfiguration;
diff --git a/media/java/android/media/FadeManagerConfiguration.java b/media/java/android/media/FadeManagerConfiguration.java
new file mode 100644
index 0000000..337d4b0
--- /dev/null
+++ b/media/java/android/media/FadeManagerConfiguration.java
@@ -0,0 +1,1684 @@
+/*
+ * 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.media;
+
+import static com.android.media.flags.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURATION;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.IntArray;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Class to encapsulate fade configurations.
+ *
+ * <p>Configurations are provided through:
+ * <ul>
+ * <li>Fadeable list: a positive list of fadeable type - usage</li>
+ * <li>Unfadeable lists: negative list of unfadeable types - content type, uid, audio attributes
+ * </li>
+ * <li>Volume shaper configs: fade in and fade out configs per usage or audio attributes
+ * </li>
+ * </ul>
+ *
+ * <p>Fade manager configuration can be created in one of the following ways:
+ * <ul>
+ * <li>Disabled fades:
+ * <pre class="prettyprint">
+ * new FadeManagerConfiguration.Builder()
+ * .setFadeState(FADE_STATE_DISABLED).build()
+ * </pre>
+ * Can be used to disable fading</li>
+ * <li>Default configurations including default fade duration:
+ * <pre class="prettyprint">
+ * new FadeManagerConfiguration.Builder()
+ * .setFadeState(FADE_STATE_ENABLED_DEFAULT).build()
+ * </pre>
+ * Can be used to enable default fading configurations</li>
+ * <li>Default configurations with custom fade duration:
+ * <pre class="prettyprint">
+ * new FadeManagerConfiguration.Builder(fade out duration, fade in duration)
+ * .setFadeState(FADE_STATE_ENABLED_DEFAULT).build()
+ * </pre>
+ * Can be used to enable default fadeability lists with configurable fade in and out duration
+ * </li>
+ * <li>Custom configurations and fade volume shapers:
+ * <pre class="prettyprint">
+ * new FadeManagerConfiguration.Builder(fade out duration, fade in duration)
+ * .setFadeState(FADE_STATE_ENABLED_DEFAULT)
+ * .setFadeableUsages(list of usages)
+ * .setUnfadeableContentTypes(list of content types)
+ * .setUnfadeableUids(list of uids)
+ * .setUnfadeableAudioAttributes(list of audio attributes)
+ * .setFadeOutVolumeShaperConfigForAudioAttributes(attributes, volume shaper config)
+ * .setFadeInDurationForUsaeg(usage, duration)
+ * ....
+ * .build() </pre>
+ * Achieves full customization of fadeability lists and configurations</li>
+ * <li>Also provides a copy constructor from another instance of fade manager configuration
+ * <pre class="prettyprint">
+ * new FadeManagerConfiguration.Builder(fadeManagerConfiguration)
+ * .addFadeableUsage(new usage)
+ * ....
+ * .build()</pre>
+ * Helps with recreating a new instance from another to simply change/add on top of the
+ * existing ones</li>
+ * </ul>
+ * TODO(b/304835727): Convert into system API so that it can be set through AudioPolicy
+ *
+ * @hide
+ */
+
+@FlaggedApi(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION)
+public final class FadeManagerConfiguration implements Parcelable {
+
+ public static final String TAG = "FadeManagerConfiguration";
+
+ /**
+ * Defines the disabled fade state. No player will be faded in this state.
+ */
+ public static final int FADE_STATE_DISABLED = 0;
+
+ /**
+ * Defines the enabled fade state with default configurations
+ */
+ public static final int FADE_STATE_ENABLED_DEFAULT = 1;
+
+ /**
+ * Defines the enabled state with Automotive specific configurations
+ */
+ public static final int FADE_STATE_ENABLED_AUTO = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, prefix = "FADE_STATE", value = {
+ FADE_STATE_DISABLED,
+ FADE_STATE_ENABLED_DEFAULT,
+ FADE_STATE_ENABLED_AUTO,
+ })
+ public @interface FadeStateEnum {}
+
+ /**
+ * Defines ID to be used in volume shaper for fading
+ */
+ public static final int VOLUME_SHAPER_SYSTEM_FADE_ID = 2;
+
+ /**
+ * Used to reset duration or return duration when not set
+ *
+ * @see Builder#setFadeOutDurationForUsage(int, long)
+ * @see Builder#setFadeInDurationForUsage(int, long)
+ * @see Builder#setFadeOutDurationForAudioAttributes(AudioAttributes, long)
+ * @see Builder#setFadeInDurationForAudioAttributes(AudioAttributes, long)
+ * @see #getFadeOutDurationForUsage(int)
+ * @see #getFadeInDurationForUsage(int)
+ * @see #getFadeOutDurationForAudioAttributes(AudioAttributes)
+ * @see #getFadeInDurationForAudioAttributes(AudioAttributes)
+ */
+ public static final long DURATION_NOT_SET = 0;
+ /** Map of Usage to Fade volume shaper configs wrapper */
+ private final SparseArray<FadeVolumeShaperConfigsWrapper> mUsageToFadeWrapperMap;
+ /** Map of AudioAttributes to Fade volume shaper configs wrapper */
+ private final ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper> mAttrToFadeWrapperMap;
+ /** list of fadeable usages */
+ private final @NonNull IntArray mFadeableUsages;
+ /** list of unfadeable content types */
+ private final @NonNull IntArray mUnfadeableContentTypes;
+ /** list of unfadeable player types */
+ private final @NonNull IntArray mUnfadeablePlayerTypes;
+ /** list of unfadeable uid(s) */
+ private final @NonNull IntArray mUnfadeableUids;
+ /** list of unfadeable AudioAttributes */
+ private final @NonNull List<AudioAttributes> mUnfadeableAudioAttributes;
+ /** fade state */
+ private final @FadeStateEnum int mFadeState;
+ /** fade out duration from builder - used for creating default fade out volume shaper */
+ private final long mFadeOutDurationMillis;
+ /** fade in duration from builder - used for creating default fade in volume shaper */
+ private final long mFadeInDurationMillis;
+ /** delay after which the offending players are faded back in */
+ private final long mFadeInDelayForOffendersMillis;
+
+ private FadeManagerConfiguration(int fadeState, long fadeOutDurationMillis,
+ long fadeInDurationMillis, long offendersFadeInDelayMillis,
+ @NonNull SparseArray<FadeVolumeShaperConfigsWrapper> usageToFadeWrapperMap,
+ @NonNull ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper> attrToFadeWrapperMap,
+ @NonNull IntArray fadeableUsages, @NonNull IntArray unfadeableContentTypes,
+ @NonNull IntArray unfadeablePlayerTypes, @NonNull IntArray unfadeableUids,
+ @NonNull List<AudioAttributes> unfadeableAudioAttributes) {
+ mFadeState = fadeState;
+ mFadeOutDurationMillis = fadeOutDurationMillis;
+ mFadeInDurationMillis = fadeInDurationMillis;
+ mFadeInDelayForOffendersMillis = offendersFadeInDelayMillis;
+ mUsageToFadeWrapperMap = Objects.requireNonNull(usageToFadeWrapperMap,
+ "Usage to fade wrapper map cannot be null");
+ mAttrToFadeWrapperMap = Objects.requireNonNull(attrToFadeWrapperMap,
+ "Attribute to fade wrapper map cannot be null");
+ mFadeableUsages = Objects.requireNonNull(fadeableUsages,
+ "List of fadeable usages cannot be null");
+ mUnfadeableContentTypes = Objects.requireNonNull(unfadeableContentTypes,
+ "List of unfadeable content types cannot be null");
+ mUnfadeablePlayerTypes = Objects.requireNonNull(unfadeablePlayerTypes,
+ "List of unfadeable player types cannot be null");
+ mUnfadeableUids = Objects.requireNonNull(unfadeableUids,
+ "List of unfadeable uids cannot be null");
+ mUnfadeableAudioAttributes = Objects.requireNonNull(unfadeableAudioAttributes,
+ "List of unfadeable audio attributes cannot be null");
+ }
+
+ /**
+ * Get the fade state
+ *
+ * @return one of the {@link FadeStateEnum} state
+ */
+ @FadeStateEnum
+ public int getFadeState() {
+ return mFadeState;
+ }
+
+ /**
+ * Get the list of usages that can be faded
+ *
+ * @return list of {@link android.media.AudioAttributes.AttributeUsage} that shall be faded
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @NonNull
+ public List<Integer> getFadeableUsages() {
+ ensureFadingIsEnabled();
+ return convertIntArrayToIntegerList(mFadeableUsages);
+ }
+
+ /**
+ * Get the list of {@link android.media.AudioPlaybackConfiguration.PlayerType player types}
+ * that cannot be faded
+ *
+ * @return list of {@link android.media.AudioPlaybackConfiguration.PlayerType}
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @NonNull
+ public List<Integer> getUnfadeablePlayerTypes() {
+ ensureFadingIsEnabled();
+ return convertIntArrayToIntegerList(mUnfadeablePlayerTypes);
+ }
+
+ /**
+ * Get the list of {@link android.media.AudioAttributes.AttributeContentType content types}
+ * that cannot be faded
+ *
+ * @return list of {@link android.media.AudioAttributes.AttributeContentType}
+ * @throws IllegalStateExceptionif if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @NonNull
+ public List<Integer> getUnfadeableContentTypes() {
+ ensureFadingIsEnabled();
+ return convertIntArrayToIntegerList(mUnfadeableContentTypes);
+ }
+
+ /**
+ * Get the list of uids that cannot be faded
+ *
+ * @return list of uids that shall not be faded
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @NonNull
+ public List<Integer> getUnfadeableUids() {
+ ensureFadingIsEnabled();
+ return convertIntArrayToIntegerList(mUnfadeableUids);
+ }
+
+ /**
+ * Get the list of {@link android.media.AudioAttributes} that cannot be faded
+ *
+ * @return list of {@link android.media.AudioAttributes} that shall not be faded
+ * @throws IllegalStateException if fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @NonNull
+ public List<AudioAttributes> getUnfadeableAudioAttributes() {
+ ensureFadingIsEnabled();
+ return mUnfadeableAudioAttributes;
+ }
+
+ /**
+ * Get the duration used to fade out players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return duration in milliseconds if set for the usage or {@link #DURATION_NOT_SET} otherwise
+ * @throws IllegalArgumentException if the usage is invalid
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ public long getFadeOutDurationForUsage(int usage) {
+ ensureFadingIsEnabled();
+ validateUsage(usage);
+ return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper(
+ mUsageToFadeWrapperMap.get(usage), /* isFadeIn= */ false));
+ }
+
+ /**
+ * Get the duration used to fade in players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return duration in milliseconds if set for the usage or {@link #DURATION_NOT_SET} otherwise
+ * @throws IllegalArgumentException if the usage is invalid
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ public long getFadeInDurationForUsage(int usage) {
+ ensureFadingIsEnabled();
+ validateUsage(usage);
+ return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper(
+ mUsageToFadeWrapperMap.get(usage), /* isFadeIn= */ true));
+ }
+
+ /**
+ * Get the {@link android.media.VolumeShaper.Configuration} used to fade out players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return {@link android.media.VolumeShaper.Configuration} if set for the usage or
+ * {@code null} otherwise
+ * @throws IllegalArgumentException if the usage is invalid
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeOutVolumeShaperConfigForUsage(int usage) {
+ ensureFadingIsEnabled();
+ validateUsage(usage);
+ return getVolumeShaperConfigFromWrapper(mUsageToFadeWrapperMap.get(usage),
+ /* isFadeIn= */ false);
+ }
+
+ /**
+ * Get the {@link android.media.VolumeShaper.Configuration} used to fade in players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage} of player
+ * @return {@link android.media.VolumeShaper.Configuration} if set for the usage or
+ * {@code null} otherwise
+ * @throws IllegalArgumentException if the usage is invalid
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeInVolumeShaperConfigForUsage(int usage) {
+ ensureFadingIsEnabled();
+ validateUsage(usage);
+ return getVolumeShaperConfigFromWrapper(mUsageToFadeWrapperMap.get(usage),
+ /* isFadeIn= */ true);
+ }
+
+ /**
+ * Get the duration used to fade out players with {@link android.media.AudioAttributes}
+ *
+ * @param audioAttributes {@link android.media.AudioAttributes}
+ * @return duration in milliseconds if set for the audio attributes or
+ * {@link #DURATION_NOT_SET} otherwise
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ public long getFadeOutDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes) {
+ ensureFadingIsEnabled();
+ return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper(
+ mAttrToFadeWrapperMap.get(audioAttributes), /* isFadeIn= */ false));
+ }
+
+ /**
+ * Get the duration used to fade-in players with {@link android.media.AudioAttributes}
+ *
+ * @param audioAttributes {@link android.media.AudioAttributes}
+ * @return duration in milliseconds if set for the audio attributes or
+ * {@link #DURATION_NOT_SET} otherwise
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ public long getFadeInDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes) {
+ ensureFadingIsEnabled();
+ return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper(
+ mAttrToFadeWrapperMap.get(audioAttributes), /* isFadeIn= */ true));
+ }
+
+ /**
+ * Get the {@link android.media.VolumeShaper.Configuration} used to fade out players with
+ * {@link android.media.AudioAttributes}
+ *
+ * @param audioAttributes {@link android.media.AudioAttributes}
+ * @return {@link android.media.VolumeShaper.Configuration} if set for the audio attribute or
+ * {@code null} otherwise
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeOutVolumeShaperConfigForAudioAttributes(
+ @NonNull AudioAttributes audioAttributes) {
+ Objects.requireNonNull(audioAttributes, "Audio attributes cannot be null");
+ ensureFadingIsEnabled();
+ return getVolumeShaperConfigFromWrapper(mAttrToFadeWrapperMap.get(audioAttributes),
+ /* isFadeIn= */ false);
+ }
+
+ /**
+ * Get the {@link android.media.VolumeShaper.Configuration} used to fade out players with
+ * {@link android.media.AudioAttributes}
+ *
+ * @param audioAttributes {@link android.media.AudioAttributes}
+ * @return {@link android.media.VolumeShaper.Configuration} used for fading in if set for the
+ * audio attribute or {@code null} otherwise
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED}
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeInVolumeShaperConfigForAudioAttributes(
+ @NonNull AudioAttributes audioAttributes) {
+ Objects.requireNonNull(audioAttributes, "Audio attributes cannot be null");
+ ensureFadingIsEnabled();
+ return getVolumeShaperConfigFromWrapper(mAttrToFadeWrapperMap.get(audioAttributes),
+ /* isFadeIn= */ true);
+ }
+
+ /**
+ * Get the list of {@link android.media.AudioAttributes} for whome the volume shaper
+ * configurations are defined
+ *
+ * @return list of {@link android.media.AudioAttributes} with valid volume shaper configs or
+ * empty list if none set.
+ */
+ @NonNull
+ public List<AudioAttributes> getAudioAttributesWithVolumeShaperConfigs() {
+ return getAudioAttributesInternal();
+ }
+
+ /**
+ * Get the delay after which the offending players are faded back in
+ *
+ * @return delay in milliseconds
+ */
+ public long getFadeInDelayForOffenders() {
+ return mFadeInDelayForOffendersMillis;
+ }
+
+ /**
+ * Query if fade is enabled
+ *
+ * @return {@code true} if fading is enabled, {@code false} otherwise
+ */
+ public boolean isFadeEnabled() {
+ return mFadeState != FADE_STATE_DISABLED;
+ }
+
+ /**
+ * Query if the usage is fadeable
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return {@code true} if usage is fadeable, {@code false} otherwise
+ */
+ public boolean isUsageFadeable(@AudioAttributes.AttributeUsage int usage) {
+ if (!isFadeEnabled()) {
+ return false;
+ }
+ return mFadeableUsages.contains(usage);
+ }
+
+ /**
+ * Query if the content type is unfadeable
+ *
+ * @param contentType the {@link android.media.AudioAttributes.AttributeContentType}
+ * @return {@code true} if content type is unfadeable or if fade state is set to
+ * {@link #FADE_STATE_DISABLED}, {@code false} otherwise
+ */
+ public boolean isContentTypeUnfadeable(@AudioAttributes.AttributeContentType int contentType) {
+ if (!isFadeEnabled()) {
+ return true;
+ }
+ return mUnfadeableContentTypes.contains(contentType);
+ }
+
+ /**
+ * Query if the player type is unfadeable
+ *
+ * @param playerType the {@link android.media.AudioPlaybackConfiguration} player type
+ * @return {@code true} if player type is unfadeable or if fade state is set to
+ * {@link #FADE_STATE_DISABLED}, {@code false} otherwise
+ */
+ public boolean isPlayerTypeUnfadeable(int playerType) {
+ if (!isFadeEnabled()) {
+ return true;
+ }
+ return mUnfadeablePlayerTypes.contains(playerType);
+ }
+
+ /**
+ * Query if the audio attributes is unfadeable
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes}
+ * @return {@code true} if audio attributes is unfadeable or if fade state is set to
+ * {@link #FADE_STATE_DISABLED}, {@code false} otherwise
+ * @throws NullPointerException if the audio attributes is {@code null}
+ */
+ public boolean isAudioAttributesUnfadeable(@NonNull AudioAttributes audioAttributes) {
+ Objects.requireNonNull(audioAttributes, "Audio attributes cannot be null");
+ if (!isFadeEnabled()) {
+ return true;
+ }
+ return mUnfadeableAudioAttributes.contains(audioAttributes);
+ }
+
+ /**
+ * Query if the uid is unfadeable
+ *
+ * @param uid the uid of application
+ * @return {@code true} if uid is unfadeable or if fade state is set to
+ * {@link #FADE_STATE_DISABLED}, {@code false} otherwise
+ */
+ public boolean isUidUnfadeable(int uid) {
+ if (!isFadeEnabled()) {
+ return true;
+ }
+ return mUnfadeableUids.contains(uid);
+ }
+
+ @Override
+ public String toString() {
+ return "FadeManagerConfiguration { fade state = " + fadeStateToString(mFadeState)
+ + ", fade out duration = " + mFadeOutDurationMillis
+ + ", fade in duration = " + mFadeInDurationMillis
+ + ", offenders fade in delay = " + mFadeInDelayForOffendersMillis
+ + ", fade volume shapers for audio attributes = " + mAttrToFadeWrapperMap
+ + ", fadeable usages = " + mFadeableUsages.toString()
+ + ", unfadeable content types = " + mUnfadeableContentTypes.toString()
+ + ", unfadeable player types = " + mUnfadeablePlayerTypes.toString()
+ + ", unfadeable uids = " + mUnfadeableUids.toString()
+ + ", unfadeable audio attributes = " + mUnfadeableAudioAttributes + "}";
+ }
+
+ /**
+ * Convert fade state into a human-readable string
+ *
+ * @param fadeState one of the fade state in {@link FadeStateEnum}
+ * @return human-readable string
+ */
+ @NonNull
+ public static String fadeStateToString(@FadeStateEnum int fadeState) {
+ switch (fadeState) {
+ case FADE_STATE_DISABLED:
+ return "FADE_STATE_DISABLED";
+ case FADE_STATE_ENABLED_DEFAULT:
+ return "FADE_STATE_ENABLED_DEFAULT";
+ case FADE_STATE_ENABLED_AUTO:
+ return "FADE_STATE_ENABLED_AUTO";
+ default:
+ return "unknown fade state: " + fadeState;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof FadeManagerConfiguration)) {
+ return false;
+ }
+
+ FadeManagerConfiguration rhs = (FadeManagerConfiguration) o;
+
+ return mUsageToFadeWrapperMap.contentEquals(rhs.mUsageToFadeWrapperMap)
+ && mAttrToFadeWrapperMap.equals(rhs.mAttrToFadeWrapperMap)
+ && Arrays.equals(mFadeableUsages.toArray(), rhs.mFadeableUsages.toArray())
+ && Arrays.equals(mUnfadeableContentTypes.toArray(),
+ rhs.mUnfadeableContentTypes.toArray())
+ && Arrays.equals(mUnfadeablePlayerTypes.toArray(),
+ rhs.mUnfadeablePlayerTypes.toArray())
+ && Arrays.equals(mUnfadeableUids.toArray(), rhs.mUnfadeableUids.toArray())
+ && mUnfadeableAudioAttributes.equals(rhs.mUnfadeableAudioAttributes)
+ && mFadeState == rhs.mFadeState
+ && mFadeOutDurationMillis == rhs.mFadeOutDurationMillis
+ && mFadeInDurationMillis == rhs.mFadeInDurationMillis
+ && mFadeInDelayForOffendersMillis == rhs.mFadeInDelayForOffendersMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUsageToFadeWrapperMap, mAttrToFadeWrapperMap, mFadeableUsages,
+ mUnfadeableContentTypes, mUnfadeablePlayerTypes, mUnfadeableAudioAttributes,
+ mUnfadeableUids, mFadeState, mFadeOutDurationMillis, mFadeInDurationMillis,
+ mFadeInDelayForOffendersMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mFadeState);
+ dest.writeLong(mFadeOutDurationMillis);
+ dest.writeLong(mFadeInDurationMillis);
+ dest.writeLong(mFadeInDelayForOffendersMillis);
+ dest.writeTypedSparseArray(mUsageToFadeWrapperMap, flags);
+ dest.writeMap(mAttrToFadeWrapperMap);
+ dest.writeIntArray(mFadeableUsages.toArray());
+ dest.writeIntArray(mUnfadeableContentTypes.toArray());
+ dest.writeIntArray(mUnfadeablePlayerTypes.toArray());
+ dest.writeIntArray(mUnfadeableUids.toArray());
+ dest.writeTypedList(mUnfadeableAudioAttributes, flags);
+ }
+
+ /**
+ * Creates fade manage configuration from parcel
+ *
+ * @hide
+ */
+ @VisibleForTesting()
+ FadeManagerConfiguration(Parcel in) {
+ int fadeState = in.readInt();
+ long fadeOutDurationMillis = in.readLong();
+ long fadeInDurationMillis = in.readLong();
+ long fadeInDelayForOffenders = in.readLong();
+ SparseArray<FadeVolumeShaperConfigsWrapper> usageToWrapperMap =
+ in.createTypedSparseArray(FadeVolumeShaperConfigsWrapper.CREATOR);
+ ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper> attrToFadeWrapperMap =
+ new ArrayMap<>();
+ in.readMap(attrToFadeWrapperMap, getClass().getClassLoader(), AudioAttributes.class,
+ FadeVolumeShaperConfigsWrapper.class);
+ int[] fadeableUsages = in.createIntArray();
+ int[] unfadeableContentTypes = in.createIntArray();
+ int[] unfadeablePlayerTypes = in.createIntArray();
+ int[] unfadeableUids = in.createIntArray();
+ List<AudioAttributes> unfadeableAudioAttributes = new ArrayList<>();
+ in.readTypedList(unfadeableAudioAttributes, AudioAttributes.CREATOR);
+
+ this.mFadeState = fadeState;
+ this.mFadeOutDurationMillis = fadeOutDurationMillis;
+ this.mFadeInDurationMillis = fadeInDurationMillis;
+ this.mFadeInDelayForOffendersMillis = fadeInDelayForOffenders;
+ this.mUsageToFadeWrapperMap = usageToWrapperMap;
+ this.mAttrToFadeWrapperMap = attrToFadeWrapperMap;
+ this.mFadeableUsages = IntArray.wrap(fadeableUsages);
+ this.mUnfadeableContentTypes = IntArray.wrap(unfadeableContentTypes);
+ this.mUnfadeablePlayerTypes = IntArray.wrap(unfadeablePlayerTypes);
+ this.mUnfadeableUids = IntArray.wrap(unfadeableUids);
+ this.mUnfadeableAudioAttributes = unfadeableAudioAttributes;
+ }
+
+ @NonNull
+ public static final Creator<FadeManagerConfiguration> CREATOR = new Creator<>() {
+ @Override
+ @NonNull
+ public FadeManagerConfiguration createFromParcel(@NonNull Parcel in) {
+ return new FadeManagerConfiguration(in);
+ }
+
+ @Override
+ @NonNull
+ public FadeManagerConfiguration[] newArray(int size) {
+ return new FadeManagerConfiguration[size];
+ }
+ };
+
+ private long getDurationForVolumeShaperConfig(VolumeShaper.Configuration config) {
+ return config != null ? config.getDuration() : DURATION_NOT_SET;
+ }
+
+ private VolumeShaper.Configuration getVolumeShaperConfigFromWrapper(
+ FadeVolumeShaperConfigsWrapper wrapper, boolean isFadeIn) {
+ // if no volume shaper config is available, return null
+ if (wrapper == null) {
+ return null;
+ }
+ if (isFadeIn) {
+ return wrapper.getFadeInVolShaperConfig();
+ }
+ return wrapper.getFadeOutVolShaperConfig();
+ }
+
+ private List<AudioAttributes> getAudioAttributesInternal() {
+ List<AudioAttributes> attrs = new ArrayList<>(mAttrToFadeWrapperMap.size());
+ for (int index = 0; index < mAttrToFadeWrapperMap.size(); index++) {
+ attrs.add(mAttrToFadeWrapperMap.keyAt(index));
+ }
+ return attrs;
+ }
+
+ private static boolean isUsageValid(int usage) {
+ return AudioAttributes.isSdkUsage(usage) || AudioAttributes.isSystemUsage(usage);
+ }
+
+ private void ensureFadingIsEnabled() {
+ if (!isFadeEnabled()) {
+ throw new IllegalStateException("Method call not allowed when fade is disabled");
+ }
+ }
+
+ private static void validateUsage(int usage) {
+ Preconditions.checkArgument(isUsageValid(usage), "Invalid usage: %s", usage);
+ }
+
+ private static IntArray convertIntegerListToIntArray(List<Integer> integerList) {
+ if (integerList == null) {
+ return new IntArray();
+ }
+
+ IntArray intArray = new IntArray(integerList.size());
+ for (int index = 0; index < integerList.size(); index++) {
+ intArray.add(integerList.get(index));
+ }
+ return intArray;
+ }
+
+ private static List<Integer> convertIntArrayToIntegerList(IntArray intArray) {
+ if (intArray == null) {
+ return new ArrayList<>();
+ }
+
+ ArrayList<Integer> integerArrayList = new ArrayList<>(intArray.size());
+ for (int index = 0; index < intArray.size(); index++) {
+ integerArrayList.add(intArray.get(index));
+ }
+ return integerArrayList;
+ }
+
+ /**
+ * Builder class for {@link FadeManagerConfiguration} objects.
+ *
+ * <p><b>Notes:</b>
+ * <ul>
+ * <li>When fade state is set to enabled, the builder expects at least one valid usage to be
+ * set/added. Failure to do so will result in an exception during {@link #build()}</li>
+ * <li>Every usage added to the fadeable list should have corresponding volume shaper
+ * configs defined. This can be achieved by setting either the duration or volume shaper
+ * config through {@link #setFadeOutDurationForUsage(int, long)} or
+ * {@link #setFadeOutVolumeShaperConfigForUsage(int, VolumeShaper.Configuration)}</li>
+ * <li> It is recommended to set volume shaper configurations individually for fade out and
+ * fade in</li>
+ * <li>For any incomplete volume shaper configs a volume shaper configuration will be
+ * created using either the default fade durations or the ones provided as part of the
+ * {@link #Builder(long, long)}</li>
+ * <li>Additional volume shaper configs can also configured for a given usage
+ * with additional attributes like content-type in order to achieve finer fade controls.
+ * See:
+ * {@link #setFadeOutVolumeShaperConfigForAudioAttributes(AudioAttributes,
+ * VolumeShaper.Configuration)} and
+ * {@link #setFadeInVolumeShaperConfigForAudioAttributes(AudioAttributes,
+ * VolumeShaper.Configuration)} </li>
+ * </ul>
+ *
+ */
+ @SuppressWarnings("WeakerAccess")
+ public static final class Builder {
+ private static final int INVALID_INDEX = -1;
+ private static final long IS_BUILDER_USED_FIELD_SET = 1 << 0;
+ private static final long IS_FADEABLE_USAGES_FIELD_SET = 1 << 1;
+ private static final long IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET = 1 << 2;
+
+ /** duration of the fade out curve */
+ private static final long DEFAULT_FADE_OUT_DURATION_MS = 2_000;
+ /** duration of the fade in curve */
+ private static final long DEFAULT_FADE_IN_DURATION_MS = 1_000;
+
+ /**
+ * delay after which a faded out player will be faded back in. This will be heard by the
+ * user only in the case of unmuting players that didn't respect audio focus and didn't
+ * stop/pause when their app lost focus.
+ * This is the amount of time between the app being notified of the focus loss
+ * (when its muted by the fade out), and the time fade in (to unmute) starts
+ */
+ private static final long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2_000;
+
+
+ private static final IntArray DEFAULT_UNFADEABLE_PLAYER_TYPES = IntArray.wrap(new int[]{
+ AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
+ AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL
+ });
+
+ private static final IntArray DEFAULT_UNFADEABLE_CONTENT_TYPES = IntArray.wrap(new int[]{
+ AudioAttributes.CONTENT_TYPE_SPEECH
+ });
+
+ private static final IntArray DEFAULT_FADEABLE_USAGES = IntArray.wrap(new int[]{
+ AudioAttributes.USAGE_GAME,
+ AudioAttributes.USAGE_MEDIA
+ });
+
+ private int mFadeState = FADE_STATE_ENABLED_DEFAULT;
+ private long mFadeInDelayForOffendersMillis = DEFAULT_DELAY_FADE_IN_OFFENDERS_MS;
+ private long mFadeOutDurationMillis;
+ private long mFadeInDurationMillis;
+ private long mBuilderFieldsSet;
+ private SparseArray<FadeVolumeShaperConfigsWrapper> mUsageToFadeWrapperMap =
+ new SparseArray<>();
+ private ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper> mAttrToFadeWrapperMap =
+ new ArrayMap<>();
+ private IntArray mFadeableUsages = new IntArray();
+ private IntArray mUnfadeableContentTypes = new IntArray();
+ // Player types are not yet configurable
+ private IntArray mUnfadeablePlayerTypes = DEFAULT_UNFADEABLE_PLAYER_TYPES;
+ private IntArray mUnfadeableUids = new IntArray();
+ private List<AudioAttributes> mUnfadeableAudioAttributes = new ArrayList<>();
+
+ /**
+ * Constructs a new Builder with default fade out and fade in durations
+ */
+ public Builder() {
+ mFadeOutDurationMillis = DEFAULT_FADE_OUT_DURATION_MS;
+ mFadeInDurationMillis = DEFAULT_FADE_IN_DURATION_MS;
+ }
+
+ /**
+ * Constructs a new Builder with the provided fade out and fade in durations
+ *
+ * @param fadeOutDurationMillis duration in milliseconds used for fading out
+ * @param fadeInDurationMills duration in milliseconds used for fading in
+ */
+ public Builder(long fadeOutDurationMillis, long fadeInDurationMills) {
+ mFadeOutDurationMillis = fadeOutDurationMillis;
+ mFadeInDurationMillis = fadeInDurationMills;
+ }
+
+ /**
+ * Constructs a new Builder from the given {@link FadeManagerConfiguration}
+ *
+ * @param fmc the {@link FadeManagerConfiguration} object whose data will be reused in the
+ * new builder
+ */
+ public Builder(@NonNull FadeManagerConfiguration fmc) {
+ mFadeState = fmc.mFadeState;
+ mUsageToFadeWrapperMap = fmc.mUsageToFadeWrapperMap.clone();
+ mAttrToFadeWrapperMap = new ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper>(
+ fmc.mAttrToFadeWrapperMap);
+ mFadeableUsages = fmc.mFadeableUsages.clone();
+ setFlag(IS_FADEABLE_USAGES_FIELD_SET);
+ mUnfadeableContentTypes = fmc.mUnfadeableContentTypes.clone();
+ setFlag(IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET);
+ mUnfadeablePlayerTypes = fmc.mUnfadeablePlayerTypes.clone();
+ mUnfadeableUids = fmc.mUnfadeableUids.clone();
+ mUnfadeableAudioAttributes = new ArrayList<>(fmc.mUnfadeableAudioAttributes);
+ mFadeOutDurationMillis = fmc.mFadeOutDurationMillis;
+ mFadeInDurationMillis = fmc.mFadeInDurationMillis;
+ }
+
+ /**
+ * Set the overall fade state
+ *
+ * @param state one of the {@link FadeStateEnum} states
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the fade state is invalid
+ * @see #getFadeState()
+ */
+ @NonNull
+ public Builder setFadeState(@FadeStateEnum int state) {
+ validateFadeState(state);
+ mFadeState = state;
+ return this;
+ }
+
+ /**
+ * Set the {@link android.media.VolumeShaper.Configuration} used to fade out players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ * <p>
+ * This method accepts {@code null} for volume shaper config to clear a previously set
+ * configuration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)})
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage} of target player
+ * @param fadeOutVShaperConfig the {@link android.media.VolumeShaper.Configuration} used
+ * to fade out players with usage
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the usage is invalid
+ * @see #getFadeOutVolumeShaperConfigForUsage(int)
+ */
+ @NonNull
+ public Builder setFadeOutVolumeShaperConfigForUsage(int usage,
+ @Nullable VolumeShaper.Configuration fadeOutVShaperConfig) {
+ validateUsage(usage);
+ getFadeVolShaperConfigWrapperForUsage(usage)
+ .setFadeOutVolShaperConfig(fadeOutVShaperConfig);
+ cleanupInactiveWrapperEntries(usage);
+ return this;
+ }
+
+ /**
+ * Set the {@link android.media.VolumeShaper.Configuration} used to fade in players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ * <p>
+ * This method accepts {@code null} for volume shaper config to clear a previously set
+ * configuration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)})
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @param fadeInVShaperConfig the {@link android.media.VolumeShaper.Configuration} used
+ * to fade in players with usage
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the usage is invalid
+ * @see #getFadeInVolumeShaperConfigForUsage(int)
+ */
+ @NonNull
+ public Builder setFadeInVolumeShaperConfigForUsage(int usage,
+ @Nullable VolumeShaper.Configuration fadeInVShaperConfig) {
+ validateUsage(usage);
+ getFadeVolShaperConfigWrapperForUsage(usage)
+ .setFadeInVolShaperConfig(fadeInVShaperConfig);
+ cleanupInactiveWrapperEntries(usage);
+ return this;
+ }
+
+ /**
+ * Set the duration used for fading out players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ * <p>
+ * A Volume shaper configuration is generated with the provided duration and default
+ * volume curve definitions. This config is then used to fade out players with given usage.
+ * <p>
+ * In order to clear previously set duration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)}), this method accepts
+ * {@link #DURATION_NOT_SET} and sets the corresponding fade out volume shaper config to
+ * {@code null}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage} of target player
+ * @param fadeOutDurationMillis positive duration in milliseconds or
+ * {@link #DURATION_NOT_SET}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the fade out duration is non-positive with the
+ * exception of {@link #DURATION_NOT_SET}
+ * @see #setFadeOutVolumeShaperConfigForUsage(int, VolumeShaper.Configuration)
+ * @see #getFadeOutDurationForUsage(int)
+ */
+ @NonNull
+ public Builder setFadeOutDurationForUsage(int usage, long fadeOutDurationMillis) {
+ validateUsage(usage);
+ VolumeShaper.Configuration fadeOutVShaperConfig =
+ createVolShaperConfigForDuration(fadeOutDurationMillis, /* isFadeIn= */ false);
+ setFadeOutVolumeShaperConfigForUsage(usage, fadeOutVShaperConfig);
+ return this;
+ }
+
+ /**
+ * Set the duration used for fading in players with
+ * {@link android.media.AudioAttributes.AttributeUsage}
+ * <p>
+ * A Volume shaper configuration is generated with the provided duration and default
+ * volume curve definitions. This config is then used to fade in players with given usage.
+ * <p>
+ * <b>Note: </b>In order to clear previously set duration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)}), this method accepts
+ * {@link #DURATION_NOT_SET} and sets the corresponding fade in volume shaper config to
+ * {@code null}
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage} of target player
+ * @param fadeInDurationMillis positive duration in milliseconds or
+ * {@link #DURATION_NOT_SET}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the fade in duration is non-positive with the
+ * exception of {@link #DURATION_NOT_SET}
+ * @see #setFadeInVolumeShaperConfigForUsage(int, VolumeShaper.Configuration)
+ * @see #getFadeInDurationForUsage(int)
+ */
+ @NonNull
+ public Builder setFadeInDurationForUsage(int usage, long fadeInDurationMillis) {
+ validateUsage(usage);
+ VolumeShaper.Configuration fadeInVShaperConfig =
+ createVolShaperConfigForDuration(fadeInDurationMillis, /* isFadeIn= */ true);
+ setFadeInVolumeShaperConfigForUsage(usage, fadeInVShaperConfig);
+ return this;
+ }
+
+ /**
+ * Set the {@link android.media.VolumeShaper.Configuration} used to fade out players with
+ * {@link android.media.AudioAttributes}
+ * <p>
+ * This method accepts {@code null} for volume shaper config to clear a previously set
+ * configuration (example, set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)})
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes}
+ * @param fadeOutVShaperConfig the {@link android.media.VolumeShaper.Configuration} used to
+ * fade out players with audio attribute
+ * @return the same Builder instance
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @see #getFadeOutVolumeShaperConfigForAudioAttributes(AudioAttributes)
+ */
+ @NonNull
+ public Builder setFadeOutVolumeShaperConfigForAudioAttributes(
+ @NonNull AudioAttributes audioAttributes,
+ @Nullable VolumeShaper.Configuration fadeOutVShaperConfig) {
+ Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null");
+ getFadeVolShaperConfigWrapperForAttr(audioAttributes)
+ .setFadeOutVolShaperConfig(fadeOutVShaperConfig);
+ cleanupInactiveWrapperEntries(audioAttributes);
+ return this;
+ }
+
+ /**
+ * Set the {@link android.media.VolumeShaper.Configuration} used to fade in players with
+ * {@link android.media.AudioAttributes}
+ *
+ * <p>This method accepts {@code null} for volume shaper config to clear a previously set
+ * configuration (example, set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)})
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes}
+ * @param fadeInVShaperConfig the {@link android.media.VolumeShaper.Configuration} used to
+ * fade in players with audio attribute
+ * @return the same Builder instance
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @see #getFadeInVolumeShaperConfigForAudioAttributes(AudioAttributes)
+ */
+ @NonNull
+ public Builder setFadeInVolumeShaperConfigForAudioAttributes(
+ @NonNull AudioAttributes audioAttributes,
+ @Nullable VolumeShaper.Configuration fadeInVShaperConfig) {
+ Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null");
+ getFadeVolShaperConfigWrapperForAttr(audioAttributes)
+ .setFadeInVolShaperConfig(fadeInVShaperConfig);
+ cleanupInactiveWrapperEntries(audioAttributes);
+ return this;
+ }
+
+ /**
+ * Set the duration used for fading out players of type
+ * {@link android.media.AudioAttributes}.
+ * <p>
+ * A Volume shaper configuration is generated with the provided duration and default
+ * volume curve definitions. This config is then used to fade out players with given usage.
+ * <p>
+ * <b>Note: </b>In order to clear previously set duration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)}), this method accepts
+ * {@link #DURATION_NOT_SET} and sets the corresponding fade out volume shaper config to
+ * {@code null}
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes} for which the fade out
+ * duration will be set/updated/reset
+ * @param fadeOutDurationMillis positive duration in milliseconds or
+ * {@link #DURATION_NOT_SET}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the fade out duration is non-positive with the
+ * exception of {@link #DURATION_NOT_SET}
+ * @see #getFadeOutDurationForAudioAttributes(AudioAttributes)
+ * @see #setFadeOutVolumeShaperConfigForAudioAttributes(AudioAttributes,
+ * VolumeShaper.Configuration)
+ */
+ @NonNull
+ public Builder setFadeOutDurationForAudioAttributes(
+ @NonNull AudioAttributes audioAttributes,
+ long fadeOutDurationMillis) {
+ Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null");
+ VolumeShaper.Configuration fadeOutVShaperConfig =
+ createVolShaperConfigForDuration(fadeOutDurationMillis, /* isFadeIn= */ false);
+ setFadeOutVolumeShaperConfigForAudioAttributes(audioAttributes, fadeOutVShaperConfig);
+ return this;
+ }
+
+ /**
+ * Set the duration used for fading in players of type
+ * {@link android.media.AudioAttributes}.
+ * <p>
+ * A Volume shaper configuration is generated with the provided duration and default
+ * volume curve definitions. This config is then used to fade in players with given usage.
+ * <p>
+ * <b>Note: </b>In order to clear previously set duration (example, if set through
+ * {@link #Builder(android.media.FadeManagerConfiguration)}), this method accepts
+ * {@link #DURATION_NOT_SET} and sets the corresponding fade in volume shaper config to
+ * {@code null}
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes} for which the fade in
+ * duration will be set/updated/reset
+ * @param fadeInDurationMillis positive duration in milliseconds or
+ * {@link #DURATION_NOT_SET}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the fade in duration is non-positive with the
+ * exception of {@link #DURATION_NOT_SET}
+ * @see #getFadeInDurationForAudioAttributes(AudioAttributes)
+ * @see #setFadeInVolumeShaperConfigForAudioAttributes(AudioAttributes,
+ * VolumeShaper.Configuration)
+ */
+ @NonNull
+ public Builder setFadeInDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes,
+ long fadeInDurationMillis) {
+ Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null");
+ VolumeShaper.Configuration fadeInVShaperConfig =
+ createVolShaperConfigForDuration(fadeInDurationMillis, /* isFadeIn= */ true);
+ setFadeInVolumeShaperConfigForAudioAttributes(audioAttributes, fadeInVShaperConfig);
+ return this;
+ }
+
+ /**
+ * Set the list of {@link android.media.AudioAttributes.AttributeUsage} that can be faded
+ *
+ * <p>This is a positive list. Players with matching usage will be considered for fading.
+ * Usages that are not part of this list will not be faded
+ *
+ * <p>Passing an empty list as input clears the existing list. This can be used to
+ * reset the list when using a copy constructor
+ *
+ * <p><b>Warning:</b> When fade state is set to enabled, the builder expects at least one
+ * usage to be set/added. Failure to do so will result in an exception during
+ * {@link #build()}
+ *
+ * @param usages List of the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the usages are invalid
+ * @throws NullPointerException if the usage list is {@code null}
+ * @see #getFadeableUsages()
+ */
+ @NonNull
+ public Builder setFadeableUsages(@NonNull List<Integer> usages) {
+ Objects.requireNonNull(usages, "List of usages cannot be null");
+ validateUsages(usages);
+ setFlag(IS_FADEABLE_USAGES_FIELD_SET);
+ mFadeableUsages.clear();
+ mFadeableUsages.addAll(convertIntegerListToIntArray(usages));
+ return this;
+ }
+
+ /**
+ * Add the {@link android.media.AudioAttributes.AttributeUsage} to the fadeable list
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the usage is invalid
+ * @see #getFadeableUsages()
+ * @see #setFadeableUsages(List)
+ */
+ @NonNull
+ public Builder addFadeableUsage(@AudioAttributes.AttributeUsage int usage) {
+ validateUsage(usage);
+ setFlag(IS_FADEABLE_USAGES_FIELD_SET);
+ if (!mFadeableUsages.contains(usage)) {
+ mFadeableUsages.add(usage);
+ }
+ return this;
+ }
+
+ /**
+ * Remove the {@link android.media.AudioAttributes.AttributeUsage} from the fadeable list
+ * <p>
+ * Players of this usage type will not be faded.
+ *
+ * @param usage the {@link android.media.AudioAttributes.AttributeUsage}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the usage is invalid
+ * @see #getFadeableUsages()
+ * @see #setFadeableUsages(List)
+ */
+ @NonNull
+ public Builder clearFadeableUsage(@AudioAttributes.AttributeUsage int usage) {
+ validateUsage(usage);
+ setFlag(IS_FADEABLE_USAGES_FIELD_SET);
+ int index = mFadeableUsages.indexOf(usage);
+ if (index != INVALID_INDEX) {
+ mFadeableUsages.remove(index);
+ }
+ return this;
+ }
+
+ /**
+ * Set the list of {@link android.media.AudioAttributes.AttributeContentType} that can not
+ * be faded
+ *
+ * <p>This is a negative list. Players with matching content type of this list will not be
+ * faded. Content types that are not part of this list will be considered for fading.
+ *
+ * <p>Passing an empty list as input clears the existing list. This can be used to
+ * reset the list when using a copy constructor
+ *
+ * @param contentTypes list of {@link android.media.AudioAttributes.AttributeContentType}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the content types are invalid
+ * @throws NullPointerException if the content type list is {@code null}
+ * @see #getUnfadeableContentTypes()
+ */
+ @NonNull
+ public Builder setUnfadeableContentTypes(@NonNull List<Integer> contentTypes) {
+ Objects.requireNonNull(contentTypes, "List of content types cannot be null");
+ validateContentTypes(contentTypes);
+ setFlag(IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET);
+ mUnfadeableContentTypes.clear();
+ mUnfadeableContentTypes.addAll(convertIntegerListToIntArray(contentTypes));
+ return this;
+ }
+
+ /**
+ * Add the {@link android.media.AudioAttributes.AttributeContentType} to unfadeable list
+ *
+ * @param contentType the {@link android.media.AudioAttributes.AttributeContentType}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the content type is invalid
+ * @see #setUnfadeableContentTypes(List)
+ * @see #getUnfadeableContentTypes()
+ */
+ @NonNull
+ public Builder addUnfadeableContentType(
+ @AudioAttributes.AttributeContentType int contentType) {
+ validateContentType(contentType);
+ setFlag(IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET);
+ if (!mUnfadeableContentTypes.contains(contentType)) {
+ mUnfadeableContentTypes.add(contentType);
+ }
+ return this;
+ }
+
+ /**
+ * Remove the {@link android.media.AudioAttributes.AttributeContentType} from the
+ * unfadeable list
+ *
+ * @param contentType the {@link android.media.AudioAttributes.AttributeContentType}
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the content type is invalid
+ * @see #setUnfadeableContentTypes(List)
+ * @see #getUnfadeableContentTypes()
+ */
+ @NonNull
+ public Builder clearUnfadeableContentType(
+ @AudioAttributes.AttributeContentType int contentType) {
+ validateContentType(contentType);
+ setFlag(IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET);
+ int index = mUnfadeableContentTypes.indexOf(contentType);
+ if (index != INVALID_INDEX) {
+ mUnfadeableContentTypes.remove(index);
+ }
+ return this;
+ }
+
+ /**
+ * Set the uids that cannot be faded
+ *
+ * <p>This is a negative list. Players with matching uid of this list will not be faded.
+ * Uids that are not part of this list shall be considered for fading
+ *
+ * <p>Passing an empty list as input clears the existing list. This can be used to
+ * reset the list when using a copy constructor
+ *
+ * @param uids list of uids
+ * @return the same Builder instance
+ * @throws NullPointerException if the uid list is {@code null}
+ * @see #getUnfadeableUids()
+ */
+ @NonNull
+ public Builder setUnfadeableUids(@NonNull List<Integer> uids) {
+ Objects.requireNonNull(uids, "List of uids cannot be null");
+ mUnfadeableUids.clear();
+ mUnfadeableUids.addAll(convertIntegerListToIntArray(uids));
+ return this;
+ }
+
+ /**
+ * Add uid to unfadeable list
+ *
+ * @param uid client uid
+ * @return the same Builder instance
+ * @see #setUnfadeableUids(List)
+ * @see #getUnfadeableUids()
+ */
+ @NonNull
+ public Builder addUnfadeableUid(int uid) {
+ if (!mUnfadeableUids.contains(uid)) {
+ mUnfadeableUids.add(uid);
+ }
+ return this;
+ }
+
+ /**
+ * Remove the uid from unfadeable list
+ *
+ * @param uid client uid
+ * @return the same Builder instance
+ * @see #setUnfadeableUids(List)
+ * @see #getUnfadeableUids()
+ */
+ @NonNull
+ public Builder clearUnfadeableUid(int uid) {
+ int index = mUnfadeableUids.indexOf(uid);
+ if (index != INVALID_INDEX) {
+ mUnfadeableUids.remove(index);
+ }
+ return this;
+ }
+
+ /**
+ * Set the list of {@link android.media.AudioAttributes} that can not be faded
+ *
+ * <p>This is a negative list. Players with matching audio attributes of this list will not
+ * be faded. Audio attributes that are not part of this list shall be considered for fading.
+ *
+ * <p>Passing an empty list as input clears any existing list. This can be used to
+ * reset the list when using a copy constructor
+ *
+ * <p><b>Note:</b> Be cautious when adding generic audio attributes into this list as it can
+ * negatively impact fadeability decision if such an audio attribute and corresponding
+ * usage fall into opposing lists.
+ * For example:
+ * <pre class=prettyprint>
+ * AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build() </pre>
+ * is a generic audio attribute for {@link android.media.AudioAttributes.USAGE_MEDIA}.
+ * It is an undefined behavior to have an
+ * {@link android.media.AudioAttributes.AttributeUsage} in the fadeable usage list and the
+ * corresponding generic {@link android.media.AudioAttributes} in the unfadeable list. Such
+ * cases will result in an exception during {@link #build()}
+ *
+ * @param attrs list of {@link android.media.AudioAttributes}
+ * @return the same Builder instance
+ * @throws NullPointerException if the audio attributes list is {@code null}
+ * @see #getUnfadeableAudioAttributes()
+ */
+ @NonNull
+ public Builder setUnfadeableAudioAttributes(@NonNull List<AudioAttributes> attrs) {
+ Objects.requireNonNull(attrs, "List of audio attributes cannot be null");
+ mUnfadeableAudioAttributes.clear();
+ mUnfadeableAudioAttributes.addAll(attrs);
+ return this;
+ }
+
+ /**
+ * Add the {@link android.media.AudioAttributes} to the unfadeable list
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes}
+ * @return the same Builder instance
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @see #setUnfadeableAudioAttributes(List)
+ * @see #getUnfadeableAudioAttributes()
+ */
+ @NonNull
+ public Builder addUnfadeableAudioAttributes(@NonNull AudioAttributes audioAttributes) {
+ Objects.requireNonNull(audioAttributes, "Audio attributes cannot be null");
+ if (!mUnfadeableAudioAttributes.contains(audioAttributes)) {
+ mUnfadeableAudioAttributes.add(audioAttributes);
+ }
+ return this;
+ }
+
+ /**
+ * Remove the {@link android.media.AudioAttributes} from the unfadeable list.
+ *
+ * @param audioAttributes the {@link android.media.AudioAttributes}
+ * @return the same Builder instance
+ * @throws NullPointerException if the audio attributes is {@code null}
+ * @see #getUnfadeableAudioAttributes()
+ */
+ @NonNull
+ public Builder clearUnfadeableAudioAttributes(@NonNull AudioAttributes audioAttributes) {
+ Objects.requireNonNull(audioAttributes, "Audio attributes cannot be null");
+ if (mUnfadeableAudioAttributes.contains(audioAttributes)) {
+ mUnfadeableAudioAttributes.remove(audioAttributes);
+ }
+ return this;
+ }
+
+ /**
+ * Set the delay after which the offending faded out player will be faded in.
+ *
+ * <p>This is the amount of time between the app being notified of the focus loss (when its
+ * muted by the fade out), and the time fade in (to unmute) starts
+ *
+ * @param delayMillis delay in milliseconds
+ * @return the same Builder instance
+ * @throws IllegalArgumentException if the delay is negative
+ * @see #getFadeInDelayForOffenders()
+ */
+ @NonNull
+ public Builder setFadeInDelayForOffenders(long delayMillis) {
+ Preconditions.checkArgument(delayMillis >= 0, "Delay cannot be negative");
+ mFadeInDelayForOffendersMillis = delayMillis;
+ return this;
+ }
+
+ /**
+ * Builds the {@link FadeManagerConfiguration} with all of the fade configurations that
+ * have been set.
+ *
+ * @return a new {@link FadeManagerConfiguration} object
+ */
+ @NonNull
+ public FadeManagerConfiguration build() {
+ if (!checkNotSet(IS_BUILDER_USED_FIELD_SET)) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+
+ setFlag(IS_BUILDER_USED_FIELD_SET);
+
+ if (checkNotSet(IS_FADEABLE_USAGES_FIELD_SET)) {
+ mFadeableUsages = DEFAULT_FADEABLE_USAGES;
+ setVolShaperConfigsForUsages(mFadeableUsages);
+ }
+
+ if (checkNotSet(IS_UNFADEABLE_CONTENT_TYPE_FIELD_SET)) {
+ mUnfadeableContentTypes = DEFAULT_UNFADEABLE_CONTENT_TYPES;
+ }
+
+ validateFadeConfigurations();
+
+ return new FadeManagerConfiguration(mFadeState, mFadeOutDurationMillis,
+ mFadeInDurationMillis, mFadeInDelayForOffendersMillis, mUsageToFadeWrapperMap,
+ mAttrToFadeWrapperMap, mFadeableUsages, mUnfadeableContentTypes,
+ mUnfadeablePlayerTypes, mUnfadeableUids, mUnfadeableAudioAttributes);
+ }
+
+ private void setFlag(long flag) {
+ mBuilderFieldsSet |= flag;
+ }
+
+ private boolean checkNotSet(long flag) {
+ return (mBuilderFieldsSet & flag) == 0;
+ }
+
+ private FadeVolumeShaperConfigsWrapper getFadeVolShaperConfigWrapperForUsage(int usage) {
+ if (!mUsageToFadeWrapperMap.contains(usage)) {
+ mUsageToFadeWrapperMap.put(usage, new FadeVolumeShaperConfigsWrapper());
+ }
+ return mUsageToFadeWrapperMap.get(usage);
+ }
+
+ private FadeVolumeShaperConfigsWrapper getFadeVolShaperConfigWrapperForAttr(
+ AudioAttributes attr) {
+ // if no entry, create a new one for setting/clearing
+ if (!mAttrToFadeWrapperMap.containsKey(attr)) {
+ mAttrToFadeWrapperMap.put(attr, new FadeVolumeShaperConfigsWrapper());
+ }
+ return mAttrToFadeWrapperMap.get(attr);
+ }
+
+ private VolumeShaper.Configuration createVolShaperConfigForDuration(long duration,
+ boolean isFadeIn) {
+ // used to reset the volume shaper config setting
+ if (duration == DURATION_NOT_SET) {
+ return null;
+ }
+
+ VolumeShaper.Configuration.Builder builder = new VolumeShaper.Configuration.Builder()
+ .setId(VOLUME_SHAPER_SYSTEM_FADE_ID)
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDuration(duration);
+
+ if (isFadeIn) {
+ builder.setCurve(/* times= */ new float[]{0.f, 0.50f, 1.0f},
+ /* volumes= */ new float[]{0.f, 0.30f, 1.0f});
+ } else {
+ builder.setCurve(/* times= */ new float[]{0.f, 0.25f, 1.0f},
+ /* volumes= */ new float[]{1.f, 0.65f, 0.0f});
+ }
+
+ return builder.build();
+ }
+
+ private void cleanupInactiveWrapperEntries(int usage) {
+ FadeVolumeShaperConfigsWrapper fmcw = mUsageToFadeWrapperMap.get(usage);
+ // cleanup map entry if FadeVolumeShaperConfigWrapper is inactive
+ if (fmcw != null && fmcw.isInactive()) {
+ mUsageToFadeWrapperMap.remove(usage);
+ }
+ }
+
+ private void cleanupInactiveWrapperEntries(AudioAttributes attr) {
+ FadeVolumeShaperConfigsWrapper fmcw = mAttrToFadeWrapperMap.get(attr);
+ // cleanup map entry if FadeVolumeShaperConfigWrapper is inactive
+ if (fmcw != null && fmcw.isInactive()) {
+ mAttrToFadeWrapperMap.remove(attr);
+ }
+ }
+
+ private void setVolShaperConfigsForUsages(IntArray usages) {
+ // set default volume shaper configs for fadeable usages
+ for (int index = 0; index < usages.size(); index++) {
+ setMissingVolShaperConfigsForWrapper(
+ getFadeVolShaperConfigWrapperForUsage(usages.get(index)));
+ }
+ }
+
+ private void setMissingVolShaperConfigsForWrapper(FadeVolumeShaperConfigsWrapper wrapper) {
+ if (!wrapper.isFadeOutConfigActive()) {
+ wrapper.setFadeOutVolShaperConfig(createVolShaperConfigForDuration(
+ mFadeOutDurationMillis, /* isFadeIn= */ false));
+ }
+ if (!wrapper.isFadeInConfigActive()) {
+ wrapper.setFadeInVolShaperConfig(createVolShaperConfigForDuration(
+ mFadeInDurationMillis, /* isFadeIn= */ true));
+ }
+ }
+
+ private void validateFadeState(int state) {
+ switch(state) {
+ case FADE_STATE_DISABLED:
+ case FADE_STATE_ENABLED_DEFAULT:
+ case FADE_STATE_ENABLED_AUTO:
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown fade state: " + state);
+ }
+ }
+
+ private void validateUsages(List<Integer> usages) {
+ for (int index = 0; index < usages.size(); index++) {
+ validateUsage(usages.get(index));
+ }
+ }
+
+ private void validateContentTypes(List<Integer> contentTypes) {
+ for (int index = 0; index < contentTypes.size(); index++) {
+ validateContentType(contentTypes.get(index));
+ }
+ }
+
+ private void validateContentType(int contentType) {
+ Preconditions.checkArgument(AudioAttributes.isSdkContentType(contentType),
+ "Invalid content type: ", contentType);
+ }
+
+ private void validateFadeConfigurations() {
+ validateFadeableUsages();
+ validateFadeVolumeShaperConfigsWrappers();
+ validateUnfadeableAudioAttributes();
+ }
+
+ /** Ensure fadeable usage list meets config requirements */
+ private void validateFadeableUsages() {
+ // ensure at least one fadeable usage
+ Preconditions.checkArgumentPositive(mFadeableUsages.size(),
+ "Fadeable usage list cannot be empty when state set to enabled");
+ // ensure all fadeable usages have volume shaper configs - both fade in and out
+ for (int index = 0; index < mFadeableUsages.size(); index++) {
+ setMissingVolShaperConfigsForWrapper(
+ getFadeVolShaperConfigWrapperForUsage(mFadeableUsages.get(index)));
+ }
+ }
+
+ /** Ensure Fade volume shaper config wrappers meet requirements */
+ private void validateFadeVolumeShaperConfigsWrappers() {
+ // ensure both fade in & out volume shaper configs are defined for all wrappers
+ // for usages -
+ for (int index = 0; index < mUsageToFadeWrapperMap.size(); index++) {
+ setMissingVolShaperConfigsForWrapper(
+ getFadeVolShaperConfigWrapperForUsage(mUsageToFadeWrapperMap.keyAt(index)));
+ }
+
+ // for additional audio attributes -
+ for (int index = 0; index < mAttrToFadeWrapperMap.size(); index++) {
+ setMissingVolShaperConfigsForWrapper(
+ getFadeVolShaperConfigWrapperForAttr(mAttrToFadeWrapperMap.keyAt(index)));
+ }
+ }
+
+ /** Ensure Unfadeable attributes meet configuration requirements */
+ private void validateUnfadeableAudioAttributes() {
+ // ensure no generic AudioAttributes in unfadeable list with matching usage in fadeable
+ // list. failure results in an undefined behavior as the audio attributes
+ // shall be both fadeable (because of the usage) and unfadeable at the same time.
+ for (int index = 0; index < mUnfadeableAudioAttributes.size(); index++) {
+ AudioAttributes targetAttr = mUnfadeableAudioAttributes.get(index);
+ int usage = targetAttr.getSystemUsage();
+ boolean isFadeableUsage = mFadeableUsages.contains(usage);
+ // cannot have a generic audio attribute that also is a fadeable usage
+ Preconditions.checkArgument(
+ !isFadeableUsage || (isFadeableUsage && !isGeneric(targetAttr)),
+ "Unfadeable audio attributes cannot be generic of the fadeable usage");
+ }
+ }
+
+ private static boolean isGeneric(AudioAttributes attr) {
+ return (attr.getContentType() == AudioAttributes.CONTENT_TYPE_UNKNOWN
+ && attr.getFlags() == 0x0
+ && attr.getBundle() == null
+ && attr.getTags().isEmpty());
+ }
+ }
+
+ private static final class FadeVolumeShaperConfigsWrapper implements Parcelable {
+ // null volume shaper config refers to either init state or if its cleared/reset
+ private @Nullable VolumeShaper.Configuration mFadeOutVolShaperConfig;
+ private @Nullable VolumeShaper.Configuration mFadeInVolShaperConfig;
+
+ FadeVolumeShaperConfigsWrapper() {}
+
+ public void setFadeOutVolShaperConfig(@Nullable VolumeShaper.Configuration fadeOutConfig) {
+ mFadeOutVolShaperConfig = fadeOutConfig;
+ }
+
+ public void setFadeInVolShaperConfig(@Nullable VolumeShaper.Configuration fadeInConfig) {
+ mFadeInVolShaperConfig = fadeInConfig;
+ }
+
+ /**
+ * Query fade out volume shaper config
+ *
+ * @return configured fade out volume shaper config or {@code null} when initialized/reset
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeOutVolShaperConfig() {
+ return mFadeOutVolShaperConfig;
+ }
+
+ /**
+ * Query fade in volume shaper config
+ *
+ * @return configured fade in volume shaper config or {@code null} when initialized/reset
+ */
+ @Nullable
+ public VolumeShaper.Configuration getFadeInVolShaperConfig() {
+ return mFadeInVolShaperConfig;
+ }
+
+ /**
+ * Wrapper is inactive if both fade out and in configs are cleared.
+ *
+ * @return {@code true} if configs are cleared. {@code false} if either of the configs is
+ * set
+ */
+ public boolean isInactive() {
+ return !isFadeOutConfigActive() && !isFadeInConfigActive();
+ }
+
+ boolean isFadeOutConfigActive() {
+ return mFadeOutVolShaperConfig != null;
+ }
+
+ boolean isFadeInConfigActive() {
+ return mFadeInVolShaperConfig != null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof FadeVolumeShaperConfigsWrapper)) {
+ return false;
+ }
+
+ FadeVolumeShaperConfigsWrapper rhs = (FadeVolumeShaperConfigsWrapper) o;
+
+ if (mFadeInVolShaperConfig == null && rhs.mFadeInVolShaperConfig == null
+ && mFadeOutVolShaperConfig == null && rhs.mFadeOutVolShaperConfig == null) {
+ return true;
+ }
+
+ boolean isEqual;
+ if (mFadeOutVolShaperConfig != null) {
+ isEqual = mFadeOutVolShaperConfig.equals(rhs.mFadeOutVolShaperConfig);
+ } else if (rhs.mFadeOutVolShaperConfig != null) {
+ return false;
+ } else {
+ isEqual = true;
+ }
+
+ if (mFadeInVolShaperConfig != null) {
+ isEqual = isEqual && mFadeInVolShaperConfig.equals(rhs.mFadeInVolShaperConfig);
+ } else if (rhs.mFadeInVolShaperConfig != null) {
+ return false;
+ }
+
+ return isEqual;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mFadeOutVolShaperConfig, mFadeInVolShaperConfig);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mFadeOutVolShaperConfig.writeToParcel(dest, flags);
+ mFadeInVolShaperConfig.writeToParcel(dest, flags);
+ }
+
+ /**
+ * Creates fade volume shaper config wrapper from parcel
+ *
+ * @hide
+ */
+ @VisibleForTesting()
+ FadeVolumeShaperConfigsWrapper(Parcel in) {
+ mFadeOutVolShaperConfig = VolumeShaper.Configuration.CREATOR.createFromParcel(in);
+ mFadeInVolShaperConfig = VolumeShaper.Configuration.CREATOR.createFromParcel(in);
+ }
+
+ @NonNull
+ public static final Creator<FadeVolumeShaperConfigsWrapper> CREATOR = new Creator<>() {
+ @Override
+ @NonNull
+ public FadeVolumeShaperConfigsWrapper createFromParcel(@NonNull Parcel in) {
+ return new FadeVolumeShaperConfigsWrapper(in);
+ }
+
+ @Override
+ @NonNull
+ public FadeVolumeShaperConfigsWrapper[] newArray(int size) {
+ return new FadeVolumeShaperConfigsWrapper[size];
+ }
+ };
+ }
+}
+
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 0a0a626..ab7c27f 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -272,7 +272,7 @@
Log.d(TAG, "Trying to get AIDL service");
IMediaCasService serviceAidl =
IMediaCasService.Stub.asInterface(
- ServiceManager.getService(
+ ServiceManager.waitForDeclaredService(
IMediaCasService.DESCRIPTOR + "/default"));
if (serviceAidl != null) {
return serviceAidl;
diff --git a/media/java/android/media/flags/fade_manager_configuration.aconfig b/media/java/android/media/flags/fade_manager_configuration.aconfig
new file mode 100644
index 0000000..100e2235
--- /dev/null
+++ b/media/java/android/media/flags/fade_manager_configuration.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.media.flags"
+
+flag {
+ namespace: "media_solutions"
+ name: "enable_fade_manager_configuration"
+ description: "Enable Fade Manager Configuration support to determine fade properties"
+ bug: "307354764"
+}
\ No newline at end of file
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index 4624dfe..3dc2a0a 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -17,6 +17,7 @@
"guava-android-testlib",
"hamcrest-library",
"platform-test-annotations",
+ "truth",
],
platform_apis: true,
certificate: "platform",
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
index 94df40d..e9a0d3e 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
@@ -229,7 +229,7 @@
@Test
public void testSetGetVolumePerAttributes() {
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
if (usage == AudioAttributes.USAGE_UNKNOWN) {
continue;
}
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
index 266faae..18e8608 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
@@ -169,7 +169,7 @@
assertNotNull(audioProductStrategies);
assertTrue(audioProductStrategies.size() > 0);
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
AudioAttributes aaForUsage = new AudioAttributes.Builder().setUsage(usage).build();
int streamTypeFromUsage =
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java
new file mode 100644
index 0000000..fb6bd48
--- /dev/null
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java
@@ -0,0 +1,795 @@
+/*
+ * 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.audiopolicytest;
+
+import static com.android.media.flags.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURATION;
+
+import static org.junit.Assert.assertThrows;
+
+import android.media.AudioAttributes;
+import android.media.AudioPlaybackConfiguration;
+import android.media.FadeManagerConfiguration;
+import android.media.VolumeShaper;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+@RequiresFlagsEnabled(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION)
+public final class FadeManagerConfigurationUnitTest {
+ private static final long DEFAULT_FADE_OUT_DURATION_MS = 2_000;
+ private static final long DEFAULT_FADE_IN_DURATION_MS = 1_000;
+ private static final long TEST_FADE_OUT_DURATION_MS = 1_500;
+ private static final long TEST_FADE_IN_DURATION_MS = 750;
+ private static final int TEST_INVALID_USAGE = -10;
+ private static final int TEST_INVALID_CONTENT_TYPE = 100;
+ private static final int TEST_INVALID_FADE_STATE = 100;
+ private static final long TEST_INVALID_DURATION = -10;
+ private static final int TEST_UID_1 = 1010001;
+ private static final int TEST_UID_2 = 1000;
+ private static final int TEST_PARCEL_FLAGS = 0;
+ private static final AudioAttributes TEST_MEDIA_AUDIO_ATTRIBUTE =
+ createAudioAttributesForUsage(AudioAttributes.USAGE_MEDIA);
+ private static final AudioAttributes TEST_GAME_AUDIO_ATTRIBUTE =
+ createAudioAttributesForUsage(AudioAttributes.USAGE_GAME);
+ private static final AudioAttributes TEST_NAVIGATION_AUDIO_ATTRIBUTE =
+ new AudioAttributes.Builder().setUsage(
+ AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build();
+ private static final AudioAttributes TEST_ASSISTANT_AUDIO_ATTRIBUTE =
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANT)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();
+ private static final List<Integer> TEST_FADEABLE_USAGES = Arrays.asList(
+ AudioAttributes.USAGE_MEDIA,
+ AudioAttributes.USAGE_GAME
+ );
+ private static final List<Integer> TEST_UNFADEABLE_CONTENT_TYPES = Arrays.asList(
+ AudioAttributes.CONTENT_TYPE_SPEECH
+ );
+
+ private static final List<Integer> TEST_UNFADEABLE_PLAYER_TYPES = Arrays.asList(
+ AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
+ AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL
+ );
+ private static final VolumeShaper.Configuration TEST_DEFAULT_FADE_OUT_VOLUME_SHAPER_CONFIG =
+ new VolumeShaper.Configuration.Builder()
+ .setId(FadeManagerConfiguration.VOLUME_SHAPER_SYSTEM_FADE_ID)
+ .setCurve(/* times= */new float[]{0.f, 0.25f, 1.0f},
+ /* volumes= */new float[]{1.f, 0.65f, 0.0f})
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDuration(DEFAULT_FADE_OUT_DURATION_MS)
+ .build();
+ private static final VolumeShaper.Configuration TEST_DEFAULT_FADE_IN_VOLUME_SHAPER_CONFIG =
+ new VolumeShaper.Configuration.Builder()
+ .setId(FadeManagerConfiguration.VOLUME_SHAPER_SYSTEM_FADE_ID)
+ .setCurve(/* times= */new float[]{0.f, 0.50f, 1.0f},
+ /* volumes= */new float[]{0.f, 0.30f, 1.0f})
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDuration(DEFAULT_FADE_IN_DURATION_MS)
+ .build();
+ private static final VolumeShaper.Configuration TEST_FADE_OUT_VOLUME_SHAPER_CONFIG =
+ new VolumeShaper.Configuration.Builder()
+ .setId(FadeManagerConfiguration.VOLUME_SHAPER_SYSTEM_FADE_ID)
+ .setCurve(/* times= */new float[]{0.f, 0.25f, 1.0f},
+ /* volumes= */new float[]{1.f, 0.65f, 0.0f})
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDuration(TEST_FADE_OUT_DURATION_MS)
+ .build();
+ private static final VolumeShaper.Configuration TEST_FADE_IN_VOLUME_SHAPER_CONFIG =
+ new VolumeShaper.Configuration.Builder()
+ .setId(FadeManagerConfiguration.VOLUME_SHAPER_SYSTEM_FADE_ID)
+ .setCurve(/* times= */new float[]{0.f, 0.50f, 1.0f},
+ /* volumes= */new float[]{0.f, 0.30f, 1.0f})
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDuration(TEST_FADE_IN_DURATION_MS)
+ .build();
+
+ private FadeManagerConfiguration mFmc;
+
+ @Rule
+ public final Expect expect = Expect.create();
+
+ @Before
+ public void setUp() {
+ mFmc = new FadeManagerConfiguration.Builder().build();
+ }
+
+
+ @Test
+ public void build() {
+ expect.withMessage("Fade state for default builder")
+ .that(mFmc.getFadeState())
+ .isEqualTo(FadeManagerConfiguration.FADE_STATE_ENABLED_DEFAULT);
+ expect.withMessage("Fadeable usages for default builder")
+ .that(mFmc.getFadeableUsages())
+ .containsExactlyElementsIn(TEST_FADEABLE_USAGES);
+ expect.withMessage("Unfadeable content types usages for default builder")
+ .that(mFmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(TEST_UNFADEABLE_CONTENT_TYPES);
+ expect.withMessage("Unfadeable player types for default builder")
+ .that(mFmc.getUnfadeablePlayerTypes())
+ .containsExactlyElementsIn(TEST_UNFADEABLE_PLAYER_TYPES);
+ expect.withMessage("Unfadeable uids for default builder")
+ .that(mFmc.getUnfadeableUids()).isEmpty();
+ expect.withMessage("Unfadeable audio attributes for default builder")
+ .that(mFmc.getUnfadeableAudioAttributes()).isEmpty();
+ expect.withMessage("Fade out volume shaper config for media usage")
+ .that(mFmc.getFadeOutVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(TEST_DEFAULT_FADE_OUT_VOLUME_SHAPER_CONFIG);
+ expect.withMessage("Fade out duration for game usage")
+ .that(mFmc.getFadeOutDurationForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(DEFAULT_FADE_OUT_DURATION_MS);
+ expect.withMessage("Fade in volume shaper config for media uasge")
+ .that(mFmc.getFadeInVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(TEST_DEFAULT_FADE_IN_VOLUME_SHAPER_CONFIG);
+ expect.withMessage("Fade in duration for game audio usage")
+ .that(mFmc.getFadeInDurationForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(DEFAULT_FADE_IN_DURATION_MS);
+ }
+
+ @Test
+ public void build_withFadeDurations_succeeds() {
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration
+ .Builder(TEST_FADE_OUT_DURATION_MS, TEST_FADE_IN_DURATION_MS).build();
+
+ expect.withMessage("Fade state for builder with duration").that(fmc.getFadeState())
+ .isEqualTo(FadeManagerConfiguration.FADE_STATE_ENABLED_DEFAULT);
+ expect.withMessage("Fadeable usages for builder with duration")
+ .that(fmc.getFadeableUsages())
+ .containsExactlyElementsIn(TEST_FADEABLE_USAGES);
+ expect.withMessage("Unfadeable content types usages for builder with duration")
+ .that(fmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(TEST_UNFADEABLE_CONTENT_TYPES);
+ expect.withMessage("Unfadeable player types for builder with duration")
+ .that(fmc.getUnfadeablePlayerTypes())
+ .containsExactlyElementsIn(TEST_UNFADEABLE_PLAYER_TYPES);
+ expect.withMessage("Unfadeable uids for builder with duration")
+ .that(fmc.getUnfadeableUids()).isEmpty();
+ expect.withMessage("Unfadeable audio attributes for builder with duration")
+ .that(fmc.getUnfadeableAudioAttributes()).isEmpty();
+ expect.withMessage("Fade out volume shaper config for media usage")
+ .that(fmc.getFadeOutVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(TEST_FADE_OUT_VOLUME_SHAPER_CONFIG);
+ expect.withMessage("Fade out duration for game usage")
+ .that(fmc.getFadeOutDurationForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(TEST_FADE_OUT_DURATION_MS);
+ expect.withMessage("Fade in volume shaper config for media audio attributes")
+ .that(fmc.getFadeInVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(TEST_FADE_IN_VOLUME_SHAPER_CONFIG);
+ expect.withMessage("Fade in duration for game audio attributes")
+ .that(fmc.getFadeInDurationForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(TEST_FADE_IN_DURATION_MS);
+
+ }
+
+ @Test
+ public void build_withFadeManagerConfiguration_succeeds() {
+ FadeManagerConfiguration fmcObj = new FadeManagerConfiguration
+ .Builder(TEST_FADE_OUT_DURATION_MS, TEST_FADE_IN_DURATION_MS).build();
+
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration
+ .Builder(fmcObj).build();
+
+ expect.withMessage("Fade state for copy builder").that(fmc.getFadeState())
+ .isEqualTo(fmcObj.getFadeState());
+ expect.withMessage("Fadeable usages for copy builder")
+ .that(fmc.getFadeableUsages())
+ .containsExactlyElementsIn(fmcObj.getFadeableUsages());
+ expect.withMessage("Unfadeable content types usages for copy builder")
+ .that(fmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(fmcObj.getUnfadeableContentTypes());
+ expect.withMessage("Unfadeable player types for copy builder")
+ .that(fmc.getUnfadeablePlayerTypes())
+ .containsExactlyElementsIn(fmcObj.getUnfadeablePlayerTypes());
+ expect.withMessage("Unfadeable uids for copy builder")
+ .that(fmc.getUnfadeableUids()).isEqualTo(fmcObj.getUnfadeableUids());
+ expect.withMessage("Unfadeable audio attributes for copy builder")
+ .that(fmc.getUnfadeableAudioAttributes())
+ .isEqualTo(fmcObj.getUnfadeableAudioAttributes());
+ expect.withMessage("Fade out volume shaper config for media usage")
+ .that(fmc.getFadeOutVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(fmcObj.getFadeOutVolumeShaperConfigForUsage(
+ AudioAttributes.USAGE_MEDIA));
+ expect.withMessage("Fade out volume shaper config for game usage")
+ .that(fmc.getFadeOutVolumeShaperConfigForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(fmcObj.getFadeOutVolumeShaperConfigForUsage(
+ AudioAttributes.USAGE_GAME));
+ expect.withMessage("Fade in volume shaper config for media usage")
+ .that(fmc.getFadeInVolumeShaperConfigForUsage(AudioAttributes.USAGE_MEDIA))
+ .isEqualTo(fmcObj.getFadeInVolumeShaperConfigForUsage(
+ AudioAttributes.USAGE_MEDIA));
+ expect.withMessage("Fade in volume shaper config for game usage")
+ .that(fmc.getFadeInVolumeShaperConfigForUsage(AudioAttributes.USAGE_GAME))
+ .isEqualTo(fmcObj.getFadeInVolumeShaperConfigForUsage(
+ AudioAttributes.USAGE_GAME));
+ expect.withMessage("Fade out volume shaper config for media audio attributes")
+ .that(fmc.getFadeOutVolumeShaperConfigForAudioAttributes(
+ TEST_MEDIA_AUDIO_ATTRIBUTE))
+ .isEqualTo(fmcObj.getFadeOutVolumeShaperConfigForAudioAttributes(
+ TEST_MEDIA_AUDIO_ATTRIBUTE));
+ expect.withMessage("Fade out duration for game audio attributes")
+ .that(fmc.getFadeOutDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE))
+ .isEqualTo(fmcObj.getFadeOutDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE));
+ expect.withMessage("Fade in volume shaper config for media audio attributes")
+ .that(fmc.getFadeInVolumeShaperConfigForAudioAttributes(TEST_MEDIA_AUDIO_ATTRIBUTE))
+ .isEqualTo(fmcObj.getFadeInVolumeShaperConfigForAudioAttributes(
+ TEST_MEDIA_AUDIO_ATTRIBUTE));
+ expect.withMessage("Fade in duration for game audio attributes")
+ .that(fmc.getFadeInDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE))
+ .isEqualTo(fmcObj.getFadeInDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE));
+ }
+
+ @Test
+ public void testSetFadeState_toDisable() {
+ final int fadeState = FadeManagerConfiguration.FADE_STATE_DISABLED;
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setFadeState(fadeState).build();
+
+ expect.withMessage("Fade state when disabled").that(fmc.getFadeState())
+ .isEqualTo(fadeState);
+ }
+
+ @Test
+ public void testSetFadeState_toEnableAuto() {
+ final int fadeStateAuto = FadeManagerConfiguration.FADE_STATE_ENABLED_AUTO;
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setFadeState(fadeStateAuto).build();
+
+ expect.withMessage("Fade state when enabled for audio").that(fmc.getFadeState())
+ .isEqualTo(fadeStateAuto);
+ }
+
+ @Test
+ public void testSetFadeState_toInvalid_fails() {
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setFadeState(TEST_INVALID_FADE_STATE).build()
+ );
+
+ expect.withMessage("Invalid fade state exception").that(thrown)
+ .hasMessageThat().contains("Unknown fade state");
+ }
+
+ @Test
+ public void testSetFadeVolShaperConfig() {
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setFadeOutVolumeShaperConfigForAudioAttributes(TEST_ASSISTANT_AUDIO_ATTRIBUTE,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(TEST_ASSISTANT_AUDIO_ATTRIBUTE,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG).build();
+
+ expect.withMessage("Fade out volume shaper config set for assistant audio attributes")
+ .that(fmc.getFadeOutVolumeShaperConfigForAudioAttributes(
+ TEST_ASSISTANT_AUDIO_ATTRIBUTE))
+ .isEqualTo(TEST_FADE_OUT_VOLUME_SHAPER_CONFIG);
+ expect.withMessage("Fade in volume shaper config set for assistant audio attributes")
+ .that(fmc.getFadeInVolumeShaperConfigForAudioAttributes(
+ TEST_ASSISTANT_AUDIO_ATTRIBUTE))
+ .isEqualTo(TEST_FADE_IN_VOLUME_SHAPER_CONFIG);
+ }
+
+ @Test
+ public void testSetFadeOutVolShaperConfig_withNullAudioAttributes_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setFadeOutVolumeShaperConfigForAudioAttributes(/* audioAttributes= */ null,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG).build()
+ );
+
+ expect.withMessage("Null audio attributes for fade out exception")
+ .that(thrown).hasMessageThat().contains("cannot be null");
+ }
+
+ @Test
+ public void testSetFadeVolShaperConfig_withNullVolumeShaper_getsNull() {
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder(mFmc)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(TEST_MEDIA_AUDIO_ATTRIBUTE,
+ /* VolumeShaper.Configuration= */ null)
+ .setFadeInVolumeShaperConfigForAudioAttributes(TEST_MEDIA_AUDIO_ATTRIBUTE,
+ /* VolumeShaper.Configuration= */ null)
+ .clearFadeableUsage(AudioAttributes.USAGE_MEDIA).build();
+
+ expect.withMessage("Fade out volume shaper config set with null value")
+ .that(fmc.getFadeOutVolumeShaperConfigForAudioAttributes(
+ TEST_MEDIA_AUDIO_ATTRIBUTE)).isNull();
+ }
+
+ @Test
+ public void testSetFadeInVolShaperConfig_withNullAudioAttributes_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setFadeInVolumeShaperConfigForAudioAttributes(/* audioAttributes= */ null,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG).build()
+ );
+
+ expect.withMessage("Null audio attributes for fade in exception")
+ .that(thrown).hasMessageThat().contains("cannot be null");
+ }
+
+ @Test
+ public void testSetFadeDuration() {
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setFadeOutDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE,
+ TEST_FADE_OUT_DURATION_MS)
+ .setFadeInDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE,
+ TEST_FADE_IN_DURATION_MS).build();
+
+ expect.withMessage("Fade out duration set for audio attributes")
+ .that(fmc.getFadeOutDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE))
+ .isEqualTo(TEST_FADE_OUT_DURATION_MS);
+ expect.withMessage("Fade in duration set for audio attributes")
+ .that(fmc.getFadeInDurationForAudioAttributes(TEST_GAME_AUDIO_ATTRIBUTE))
+ .isEqualTo(TEST_FADE_IN_DURATION_MS);
+ }
+
+ @Test
+ public void testSetFadeOutDuration_withNullAudioAttributes_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeOutDurationForAudioAttributes(
+ /* audioAttributes= */ null, TEST_FADE_OUT_DURATION_MS).build()
+ );
+
+ expect.withMessage("Null audio attributes for fade out duration exception").that(thrown)
+ .hasMessageThat().contains("cannot be null");
+ }
+
+ @Test
+ public void testSetFadeOutDuration_withInvalidDuration_fails() {
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeOutDurationForAudioAttributes(
+ TEST_NAVIGATION_AUDIO_ATTRIBUTE, TEST_INVALID_DURATION).build()
+ );
+
+ expect.withMessage("Invalid duration for fade out exception").that(thrown)
+ .hasMessageThat().contains("not positive");
+ }
+
+ @Test
+ public void testSetFadeInDuration_withNullAudioAttributes_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeInDurationForAudioAttributes(
+ /* audioAttributes= */ null, TEST_FADE_IN_DURATION_MS).build()
+ );
+
+ expect.withMessage("Null audio attributes for fade in duration exception").that(thrown)
+ .hasMessageThat().contains("cannot be null");
+ }
+
+ @Test
+ public void testSetFadeInDuration_withInvalidDuration_fails() {
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeInDurationForAudioAttributes(
+ TEST_NAVIGATION_AUDIO_ATTRIBUTE, TEST_INVALID_DURATION).build()
+ );
+
+ expect.withMessage("Invalid duration for fade in exception").that(thrown)
+ .hasMessageThat().contains("not positive");
+ }
+
+ @Test
+ public void testSetFadeableUsages() {
+ final List<Integer> fadeableUsages = List.of(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION,
+ AudioAttributes.USAGE_ALARM,
+ AudioAttributes.USAGE_ASSISTANT
+ );
+ AudioAttributes aaForVoiceComm = createAudioAttributesForUsage(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION);
+ AudioAttributes aaForAlarm = createAudioAttributesForUsage(AudioAttributes.USAGE_ALARM);
+ AudioAttributes aaForAssistant = createAudioAttributesForUsage(
+ AudioAttributes.USAGE_ASSISTANT);
+
+
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setFadeableUsages(fadeableUsages)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaForVoiceComm,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaForVoiceComm,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaForAlarm,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaForAlarm,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaForAssistant,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaForAssistant,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG).build();
+
+ expect.withMessage("Fadeable usages")
+ .that(fmc.getFadeableUsages()).isEqualTo(fadeableUsages);
+ }
+
+ @Test
+ public void testSetFadeableUsages_withInvalidUsage_fails() {
+ final List<Integer> fadeableUsages = List.of(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION,
+ TEST_INVALID_USAGE,
+ AudioAttributes.USAGE_ANNOUNCEMENT
+ );
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeableUsages(fadeableUsages).build()
+ );
+
+ expect.withMessage("Fadeable usages set to invalid usage").that(thrown).hasMessageThat()
+ .contains("Invalid usage");
+ }
+
+ @Test
+ public void testSetFadeableUsages_withNullUsages_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder().setFadeableUsages(/* usages= */ null)
+ .build()
+ );
+
+ expect.withMessage("Fadeable usages set to null list").that(thrown).hasMessageThat()
+ .contains("cannot be null");
+ }
+
+ @Test
+ public void testSetFadeableUsages_withEmptyListClears_addsNewUsage() {
+ final List<Integer> fadeableUsages = List.of(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION,
+ AudioAttributes.USAGE_ALARM,
+ AudioAttributes.USAGE_ASSISTANT
+ );
+ FadeManagerConfiguration.Builder fmcBuilder = new FadeManagerConfiguration.Builder()
+ .setFadeableUsages(fadeableUsages);
+
+ fmcBuilder.setFadeableUsages(List.of());
+
+ FadeManagerConfiguration fmc = fmcBuilder
+ .addFadeableUsage(AudioAttributes.USAGE_MEDIA)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(TEST_MEDIA_AUDIO_ATTRIBUTE,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(TEST_MEDIA_AUDIO_ATTRIBUTE,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG).build();
+ expect.withMessage("Fadeable usages set to empty list")
+ .that(fmc.getFadeableUsages()).isEqualTo(List.of(AudioAttributes.USAGE_MEDIA));
+ }
+
+
+ @Test
+ public void testAddFadeableUsage() {
+ final int usageToAdd = AudioAttributes.USAGE_ASSISTANT;
+ AudioAttributes aaToAdd = createAudioAttributesForUsage(usageToAdd);
+ List<Integer> updatedUsages = new ArrayList<>(mFmc.getFadeableUsages());
+ updatedUsages.add(usageToAdd);
+
+ FadeManagerConfiguration updatedFmc = new FadeManagerConfiguration
+ .Builder(mFmc).addFadeableUsage(usageToAdd)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaToAdd,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaToAdd,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG)
+ .build();
+
+ expect.withMessage("Fadeable usages").that(updatedFmc.getFadeableUsages())
+ .containsExactlyElementsIn(updatedUsages);
+ }
+
+ @Test
+ public void testAddFadeableUsage_withoutSetFadeableUsages() {
+ final int newUsage = AudioAttributes.USAGE_ASSISTANT;
+ AudioAttributes aaToAdd = createAudioAttributesForUsage(newUsage);
+
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .addFadeableUsage(newUsage)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaToAdd,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaToAdd,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG)
+ .build();
+
+ expect.withMessage("Fadeable usages").that(fmc.getFadeableUsages())
+ .containsExactlyElementsIn(List.of(newUsage));
+ }
+
+ @Test
+ public void testAddFadeableUsage_withInvalidUsage_fails() {
+ List<Integer> setUsages = Arrays.asList(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION,
+ AudioAttributes.USAGE_ASSISTANT
+ );
+ AudioAttributes aaForVoiceComm = createAudioAttributesForUsage(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION);
+ AudioAttributes aaForAssistant = createAudioAttributesForUsage(
+ AudioAttributes.USAGE_ASSISTANT);
+ FadeManagerConfiguration.Builder fmcBuilder = new FadeManagerConfiguration.Builder()
+ .setFadeableUsages(setUsages)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaForVoiceComm,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaForVoiceComm,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG)
+ .setFadeOutVolumeShaperConfigForAudioAttributes(aaForAssistant,
+ TEST_FADE_OUT_VOLUME_SHAPER_CONFIG)
+ .setFadeInVolumeShaperConfigForAudioAttributes(aaForAssistant,
+ TEST_FADE_IN_VOLUME_SHAPER_CONFIG);
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ fmcBuilder.addFadeableUsage(TEST_INVALID_USAGE)
+ );
+
+ FadeManagerConfiguration fmc = fmcBuilder.build();
+ expect.withMessage("Fadeable usages ").that(thrown).hasMessageThat()
+ .contains("Invalid usage");
+ expect.withMessage("Fadeable usages").that(fmc.getFadeableUsages())
+ .containsExactlyElementsIn(setUsages);
+ }
+
+ @Test
+ public void testClearFadeableUsage() {
+ final int usageToClear = AudioAttributes.USAGE_MEDIA;
+ List<Integer> updatedUsages = new ArrayList<>(mFmc.getFadeableUsages());
+ updatedUsages.remove((Integer) usageToClear);
+
+ FadeManagerConfiguration updatedFmc = new FadeManagerConfiguration
+ .Builder(mFmc).clearFadeableUsage(usageToClear).build();
+
+ expect.withMessage("Clear fadeable usage").that(updatedFmc.getFadeableUsages())
+ .containsExactlyElementsIn(updatedUsages);
+ }
+
+ @Test
+ public void testClearFadeableUsage_withInvalidUsage_fails() {
+ FadeManagerConfiguration.Builder fmcBuilder = new FadeManagerConfiguration.Builder(mFmc);
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ fmcBuilder.clearFadeableUsage(TEST_INVALID_USAGE)
+ );
+
+ FadeManagerConfiguration fmc = fmcBuilder.build();
+ expect.withMessage("Clear invalid usage").that(thrown).hasMessageThat()
+ .contains("Invalid usage");
+ expect.withMessage("Fadeable usages").that(fmc.getFadeableUsages())
+ .containsExactlyElementsIn(mFmc.getFadeableUsages());
+ }
+
+ @Test
+ public void testSetUnfadeableContentTypes() {
+ final List<Integer> unfadeableContentTypes = List.of(
+ AudioAttributes.CONTENT_TYPE_MOVIE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION
+ );
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(unfadeableContentTypes).build();
+
+ expect.withMessage("Unfadeable content types set")
+ .that(fmc.getUnfadeableContentTypes()).isEqualTo(unfadeableContentTypes);
+ }
+
+ @Test
+ public void testSetUnfadeableContentTypes_withInvalidContentType_fails() {
+ final List<Integer> invalidUnfadeableContentTypes = List.of(
+ AudioAttributes.CONTENT_TYPE_MOVIE,
+ TEST_INVALID_CONTENT_TYPE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION
+ );
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(invalidUnfadeableContentTypes).build()
+ );
+
+ expect.withMessage("Invalid content type set exception").that(thrown).hasMessageThat()
+ .contains("Invalid content type");
+ }
+
+ @Test
+ public void testSetUnfadeableContentTypes_withNullContentType_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(/* contentType= */ null).build()
+ );
+
+ expect.withMessage("Null content type set exception").that(thrown).hasMessageThat()
+ .contains("cannot be null");
+ }
+
+ @Test
+ public void testSetUnfadeableContentTypes_withEmptyList_clearsExistingList() {
+ final List<Integer> unfadeableContentTypes = List.of(
+ AudioAttributes.CONTENT_TYPE_MOVIE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION
+ );
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(unfadeableContentTypes).build();
+
+ FadeManagerConfiguration fmcWithEmptyLsit = new FadeManagerConfiguration.Builder(fmc)
+ .setUnfadeableContentTypes(List.of()).build();
+
+ expect.withMessage("Unfadeable content types for empty list")
+ .that(fmcWithEmptyLsit.getUnfadeableContentTypes()).isEmpty();
+ }
+
+ @Test
+ public void testAddUnfadeableContentType() {
+ final int contentTypeToAdd = AudioAttributes.CONTENT_TYPE_MOVIE;
+ List<Integer> upatdedContentTypes = new ArrayList<>(mFmc.getUnfadeableContentTypes());
+ upatdedContentTypes.add(contentTypeToAdd);
+
+ FadeManagerConfiguration updatedFmc = new FadeManagerConfiguration
+ .Builder(mFmc).addUnfadeableContentType(contentTypeToAdd).build();
+
+ expect.withMessage("Unfadeable content types").that(updatedFmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(upatdedContentTypes);
+ }
+
+ @Test
+ public void testAddUnfadeableContentTypes_withoutSetUnfadeableContentTypes() {
+ final int newContentType = AudioAttributes.CONTENT_TYPE_MOVIE;
+
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .addUnfadeableContentType(newContentType).build();
+
+ expect.withMessage("Unfadeable content types").that(fmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(List.of(newContentType));
+ }
+
+ @Test
+ public void testAddunfadeableContentTypes_withInvalidContentType_fails() {
+ final List<Integer> unfadeableContentTypes = List.of(
+ AudioAttributes.CONTENT_TYPE_MOVIE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION
+ );
+ FadeManagerConfiguration.Builder fmcBuilder = new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(unfadeableContentTypes);
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ fmcBuilder.addUnfadeableContentType(TEST_INVALID_CONTENT_TYPE).build()
+ );
+
+ expect.withMessage("Invalid content types exception").that(thrown).hasMessageThat()
+ .contains("Invalid content type");
+ }
+
+ @Test
+ public void testClearUnfadeableContentType() {
+ List<Integer> unfadeableContentTypes = new ArrayList<>(Arrays.asList(
+ AudioAttributes.CONTENT_TYPE_MOVIE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION
+ ));
+ final int contentTypeToClear = AudioAttributes.CONTENT_TYPE_MOVIE;
+
+ FadeManagerConfiguration updatedFmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableContentTypes(unfadeableContentTypes)
+ .clearUnfadeableContentType(contentTypeToClear).build();
+
+ unfadeableContentTypes.remove((Integer) contentTypeToClear);
+ expect.withMessage("Unfadeable content types").that(updatedFmc.getUnfadeableContentTypes())
+ .containsExactlyElementsIn(unfadeableContentTypes);
+ }
+
+ @Test
+ public void testClearUnfadeableContentType_withInvalidContentType_fails() {
+ FadeManagerConfiguration.Builder fmcBuilder = new FadeManagerConfiguration.Builder(mFmc);
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
+ fmcBuilder.clearUnfadeableContentType(TEST_INVALID_CONTENT_TYPE).build()
+ );
+
+ expect.withMessage("Invalid content type exception").that(thrown).hasMessageThat()
+ .contains("Invalid content type");
+ }
+
+ @Test
+ public void testSetUnfadeableUids() {
+ final List<Integer> unfadeableUids = List.of(
+ TEST_UID_1,
+ TEST_UID_2
+ );
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableUids(unfadeableUids).build();
+
+ expect.withMessage("Unfadeable uids set")
+ .that(fmc.getUnfadeableUids()).isEqualTo(unfadeableUids);
+ }
+
+ @Test
+ public void testSetUnfadeableUids_withNullUids_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setUnfadeableUids(/* uids= */ null).build()
+ );
+
+ expect.withMessage("Null unfadeable uids").that(thrown).hasMessageThat()
+ .contains("cannot be null");
+ }
+
+ @Test
+ public void testAddUnfadeableUid() {
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .addUnfadeableUid(TEST_UID_1).build();
+
+ expect.withMessage("Unfadeable uids")
+ .that(fmc.getUnfadeableUids()).isEqualTo(List.of(TEST_UID_1));
+ }
+
+ @Test
+ public void testClearUnfadebaleUid() {
+ final List<Integer> unfadeableUids = List.of(
+ TEST_UID_1,
+ TEST_UID_2
+ );
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableUids(unfadeableUids).build();
+
+ FadeManagerConfiguration updatedFmc = new FadeManagerConfiguration.Builder(fmc)
+ .clearUnfadeableUid(TEST_UID_1).build();
+
+ expect.withMessage("Unfadeable uids").that(updatedFmc.getUnfadeableUids())
+ .isEqualTo(List.of(TEST_UID_2));
+ }
+
+ @Test
+ public void testSetUnfadeableAudioAttributes() {
+ final List<AudioAttributes> unfadeableAttrs = List.of(
+ TEST_ASSISTANT_AUDIO_ATTRIBUTE,
+ TEST_NAVIGATION_AUDIO_ATTRIBUTE
+ );
+
+ FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+ .setUnfadeableAudioAttributes(unfadeableAttrs).build();
+
+ expect.withMessage("Unfadeable audio attributes")
+ .that(fmc.getUnfadeableAudioAttributes()).isEqualTo(unfadeableAttrs);
+ }
+
+ @Test
+ public void testSetUnfadeableAudioAttributes_withNullAttributes_fails() {
+ NullPointerException thrown = assertThrows(NullPointerException.class, () ->
+ new FadeManagerConfiguration.Builder()
+ .setUnfadeableAudioAttributes(/* attrs= */ null).build()
+ );
+
+ expect.withMessage("Null audio attributes exception").that(thrown).hasMessageThat()
+ .contains("cannot be null");
+ }
+
+ @Test
+ public void testWriteToParcel_andCreateFromParcel() {
+ Parcel parcel = Parcel.obtain();
+
+ mFmc.writeToParcel(parcel, TEST_PARCEL_FLAGS);
+ parcel.setDataPosition(/* position= */ 0);
+ expect.withMessage("Fade manager configuration write to and create from parcel")
+ .that(mFmc)
+ .isEqualTo(FadeManagerConfiguration.CREATOR.createFromParcel(parcel));
+ }
+
+ private static AudioAttributes createAudioAttributesForUsage(int usage) {
+ if (AudioAttributes.isSystemUsage(usage)) {
+ return new AudioAttributes.Builder().setSystemUsage(usage).build();
+ }
+ return new AudioAttributes.Builder().setUsage(usage).build();
+ }
+}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index fea6c5f..9f2a9ac 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -336,6 +336,13 @@
APerformanceHint_closeSession; # introduced=Tiramisu
APerformanceHint_setThreads; # introduced=UpsideDownCake
APerformanceHint_setPreferPowerEfficiency; # introduced=VanillaIceCream
+ APerformanceHint_reportActualWorkDuration2; # introduced=VanillaIceCream
+ AWorkDuration_create; # introduced=VanillaIceCream
+ AWorkDuration_release; # introduced=VanillaIceCream
+ AWorkDuration_setWorkPeriodStartTimestampNanos; # introduced=VanillaIceCream
+ AWorkDuration_setActualTotalDurationNanos; # introduced=VanillaIceCream
+ AWorkDuration_setActualCpuDurationNanos; # introduced=VanillaIceCream
+ AWorkDuration_setActualGpuDurationNanos; # introduced=VanillaIceCream
local:
*;
};
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index c25df6e..c4c8128 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -18,12 +18,14 @@
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
+#include <android/WorkDuration.h>
#include <android/os/IHintManager.h>
#include <android/os/IHintSession.h>
#include <android/performance_hint.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
+#include <inttypes.h>
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
@@ -75,10 +77,13 @@
int setThreads(const int32_t* threadIds, size_t size);
int getThreadIds(int32_t* const threadIds, size_t* size);
int setPreferPowerEfficiency(bool enabled);
+ int reportActualWorkDuration(AWorkDuration* workDuration);
private:
friend struct APerformanceHintManager;
+ int reportActualWorkDurationInternal(WorkDuration* workDuration);
+
sp<IHintManager> mHintManager;
sp<IHintSession> mHintSession;
// HAL preferred update rate
@@ -92,8 +97,7 @@
// Last hint reported from sendHint indexed by hint value
std::vector<int64_t> mLastHintSentTimestamp;
// Cached samples
- std::vector<int64_t> mActualDurationsNanos;
- std::vector<int64_t> mTimestampsNanos;
+ std::vector<WorkDuration> mActualWorkDurations;
};
static IHintManager* gIHintManagerForTesting = nullptr;
@@ -195,8 +199,7 @@
* Most of the workload is target_duration dependent, so now clear the cached samples
* as they are most likely obsolete.
*/
- mActualDurationsNanos.clear();
- mTimestampsNanos.clear();
+ mActualWorkDurations.clear();
mFirstTargetMetTimestamp = 0;
mLastTargetMetTimestamp = 0;
return 0;
@@ -207,43 +210,10 @@
ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__);
return EINVAL;
}
- int64_t now = elapsedRealtimeNano();
- mActualDurationsNanos.push_back(actualDurationNanos);
- mTimestampsNanos.push_back(now);
- if (actualDurationNanos >= mTargetDurationNanos) {
- // Reset timestamps if we are equal or over the target.
- mFirstTargetMetTimestamp = 0;
- } else {
- // Set mFirstTargetMetTimestamp for first time meeting target.
- if (!mFirstTargetMetTimestamp || !mLastTargetMetTimestamp ||
- (now - mLastTargetMetTimestamp > 2 * mPreferredRateNanos)) {
- mFirstTargetMetTimestamp = now;
- }
- /**
- * Rate limit the change if the update is over mPreferredRateNanos since first
- * meeting target and less than mPreferredRateNanos since last meeting target.
- */
- if (now - mFirstTargetMetTimestamp > mPreferredRateNanos &&
- now - mLastTargetMetTimestamp <= mPreferredRateNanos) {
- return 0;
- }
- mLastTargetMetTimestamp = now;
- }
+ WorkDuration workDuration(0, actualDurationNanos, actualDurationNanos, 0);
- binder::Status ret =
- mHintSession->reportActualWorkDuration(mActualDurationsNanos, mTimestampsNanos);
- if (!ret.isOk()) {
- ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
- mFirstTargetMetTimestamp = 0;
- mLastTargetMetTimestamp = 0;
- return EPIPE;
- }
- mActualDurationsNanos.clear();
- mTimestampsNanos.clear();
-
- return 0;
+ return reportActualWorkDurationInternal(&workDuration);
}
int APerformanceHintSession::sendHint(SessionHint hint) {
@@ -322,6 +292,67 @@
return OK;
}
+int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* aWorkDuration) {
+ WorkDuration* workDuration = static_cast<WorkDuration*>(aWorkDuration);
+ if (workDuration->workPeriodStartTimestampNanos <= 0) {
+ ALOGE("%s: workPeriodStartTimestampNanos must be positive", __FUNCTION__);
+ return EINVAL;
+ }
+ if (workDuration->actualTotalDurationNanos <= 0) {
+ ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__);
+ return EINVAL;
+ }
+ if (workDuration->actualCpuDurationNanos <= 0) {
+ ALOGE("%s: cpuDurationNanos must be positive", __FUNCTION__);
+ return EINVAL;
+ }
+ if (workDuration->actualGpuDurationNanos < 0) {
+ ALOGE("%s: gpuDurationNanos must be non negative", __FUNCTION__);
+ return EINVAL;
+ }
+
+ return reportActualWorkDurationInternal(workDuration);
+}
+
+int APerformanceHintSession::reportActualWorkDurationInternal(WorkDuration* workDuration) {
+ int64_t actualTotalDurationNanos = workDuration->actualTotalDurationNanos;
+ int64_t now = uptimeNanos();
+ workDuration->timestampNanos = now;
+ mActualWorkDurations.push_back(std::move(*workDuration));
+
+ if (actualTotalDurationNanos >= mTargetDurationNanos) {
+ // Reset timestamps if we are equal or over the target.
+ mFirstTargetMetTimestamp = 0;
+ } else {
+ // Set mFirstTargetMetTimestamp for first time meeting target.
+ if (!mFirstTargetMetTimestamp || !mLastTargetMetTimestamp ||
+ (now - mLastTargetMetTimestamp > 2 * mPreferredRateNanos)) {
+ mFirstTargetMetTimestamp = now;
+ }
+ /**
+ * Rate limit the change if the update is over mPreferredRateNanos since first
+ * meeting target and less than mPreferredRateNanos since last meeting target.
+ */
+ if (now - mFirstTargetMetTimestamp > mPreferredRateNanos &&
+ now - mLastTargetMetTimestamp <= mPreferredRateNanos) {
+ return 0;
+ }
+ mLastTargetMetTimestamp = now;
+ }
+
+ binder::Status ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
+ ret.exceptionMessage().c_str());
+ mFirstTargetMetTimestamp = 0;
+ mLastTargetMetTimestamp = 0;
+ return ret.exceptionCode() == binder::Status::EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+ }
+ mActualWorkDurations.clear();
+
+ return 0;
+}
+
// ===================================== C API
APerformanceHintManager* APerformanceHint_getManager() {
return APerformanceHintManager::getInstance();
@@ -376,6 +407,64 @@
return session->setPreferPowerEfficiency(enabled);
}
+int APerformanceHint_reportActualWorkDuration2(APerformanceHintSession* session,
+ AWorkDuration* workDuration) {
+ if (session == nullptr || workDuration == nullptr) {
+ ALOGE("Invalid value: (session %p, workDuration %p)", session, workDuration);
+ return EINVAL;
+ }
+ return session->reportActualWorkDuration(workDuration);
+}
+
+AWorkDuration* AWorkDuration_create() {
+ WorkDuration* workDuration = new WorkDuration();
+ return static_cast<AWorkDuration*>(workDuration);
+}
+
+void AWorkDuration_release(AWorkDuration* aWorkDuration) {
+ if (aWorkDuration == nullptr) {
+ ALOGE("%s: aWorkDuration is nullptr", __FUNCTION__);
+ }
+ delete aWorkDuration;
+}
+
+void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
+ int64_t workPeriodStartTimestampNanos) {
+ if (aWorkDuration == nullptr || workPeriodStartTimestampNanos <= 0) {
+ ALOGE("%s: Invalid value. (AWorkDuration: %p, workPeriodStartTimestampNanos: %" PRIi64 ")",
+ __FUNCTION__, aWorkDuration, workPeriodStartTimestampNanos);
+ }
+ static_cast<WorkDuration*>(aWorkDuration)->workPeriodStartTimestampNanos =
+ workPeriodStartTimestampNanos;
+}
+
+void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* aWorkDuration,
+ int64_t actualTotalDurationNanos) {
+ if (aWorkDuration == nullptr || actualTotalDurationNanos <= 0) {
+ ALOGE("%s: Invalid value. (AWorkDuration: %p, actualTotalDurationNanos: %" PRIi64 ")",
+ __FUNCTION__, aWorkDuration, actualTotalDurationNanos);
+ }
+ static_cast<WorkDuration*>(aWorkDuration)->actualTotalDurationNanos = actualTotalDurationNanos;
+}
+
+void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* aWorkDuration,
+ int64_t actualCpuDurationNanos) {
+ if (aWorkDuration == nullptr || actualCpuDurationNanos <= 0) {
+ ALOGE("%s: Invalid value. (AWorkDuration: %p, actualCpuDurationNanos: %" PRIi64 ")",
+ __FUNCTION__, aWorkDuration, actualCpuDurationNanos);
+ }
+ static_cast<WorkDuration*>(aWorkDuration)->actualCpuDurationNanos = actualCpuDurationNanos;
+}
+
+void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration,
+ int64_t actualGpuDurationNanos) {
+ if (aWorkDuration == nullptr || actualGpuDurationNanos < 0) {
+ ALOGE("%s: Invalid value. (AWorkDuration: %p, actualGpuDurationNanos: %" PRIi64 ")",
+ __FUNCTION__, aWorkDuration, actualGpuDurationNanos);
+ }
+ static_cast<WorkDuration*>(aWorkDuration)->actualGpuDurationNanos = actualGpuDurationNanos;
+}
+
void APerformanceHint_setIHintManagerForTesting(void* iManager) {
delete gHintManagerForTesting;
gHintManagerForTesting = nullptr;
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 22d33b1..4553b49 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "PerformanceHintNativeTest"
+#include <android/WorkDuration.h>
#include <android/os/IHintManager.h>
#include <android/os/IHintSession.h>
#include <android/performance_hint.h>
@@ -60,6 +61,8 @@
MOCK_METHOD(Status, setMode, (int32_t mode, bool enabled), (override));
MOCK_METHOD(Status, close, (), (override));
MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+ MOCK_METHOD(Status, reportActualWorkDuration2,
+ (const ::std::vector<android::os::WorkDuration>& workDurations), (override));
};
class PerformanceHintTest : public Test {
@@ -120,6 +123,7 @@
std::vector<int64_t> actualDurations;
actualDurations.push_back(20);
EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(_)).Times(Exactly(1));
result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
EXPECT_EQ(0, result);
@@ -238,4 +242,125 @@
APerformanceHintSession* session =
APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
ASSERT_TRUE(session);
-}
\ No newline at end of file
+}
+
+MATCHER_P(WorkDurationEq, expected, "") {
+ if (arg.size() != expected.size()) {
+ *result_listener << "WorkDuration vectors are different sizes. Expected: "
+ << expected.size() << ", Actual: " << arg.size();
+ return false;
+ }
+ for (int i = 0; i < expected.size(); ++i) {
+ android::os::WorkDuration expectedWorkDuration = expected[i];
+ android::os::WorkDuration actualWorkDuration = arg[i];
+ if (!expectedWorkDuration.equalsWithoutTimestamp(actualWorkDuration)) {
+ *result_listener << "WorkDuration at [" << i << "] is different: "
+ << "Expected: " << expectedWorkDuration
+ << ", Actual: " << actualWorkDuration;
+ return false;
+ }
+ }
+ return true;
+}
+
+TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
+ APerformanceHintManager* manager = createManager();
+
+ std::vector<int32_t> tids;
+ tids.push_back(1);
+ tids.push_back(2);
+ int64_t targetDuration = 56789L;
+
+ StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
+ sp<IHintSession> session_sp(iSession);
+
+ EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
+
+ APerformanceHintSession* session =
+ APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ ASSERT_TRUE(session);
+
+ int64_t targetDurationNanos = 10;
+ EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+ EXPECT_EQ(0, result);
+
+ usleep(2); // Sleep for longer than preferredUpdateRateNanos.
+ {
+ std::vector<android::os::WorkDuration> actualWorkDurations;
+ android::os::WorkDuration workDuration(1, 20, 13, 8);
+ actualWorkDurations.push_back(workDuration);
+
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ .Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration2(session,
+ static_cast<AWorkDuration*>(
+ &workDuration));
+ EXPECT_EQ(0, result);
+ }
+
+ {
+ std::vector<android::os::WorkDuration> actualWorkDurations;
+ android::os::WorkDuration workDuration(-1, 20, 13, 8);
+ actualWorkDurations.push_back(workDuration);
+
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ .Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration2(session,
+ static_cast<AWorkDuration*>(
+ &workDuration));
+ EXPECT_EQ(22, result);
+ }
+ {
+ std::vector<android::os::WorkDuration> actualWorkDurations;
+ android::os::WorkDuration workDuration(1, -20, 13, 8);
+ actualWorkDurations.push_back(workDuration);
+
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ .Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration2(session,
+ static_cast<AWorkDuration*>(
+ &workDuration));
+ EXPECT_EQ(22, result);
+ }
+ {
+ std::vector<android::os::WorkDuration> actualWorkDurations;
+ android::os::WorkDuration workDuration(1, 20, -13, 8);
+ actualWorkDurations.push_back(workDuration);
+
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ .Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration2(session,
+ static_cast<AWorkDuration*>(
+ &workDuration));
+ EXPECT_EQ(EINVAL, result);
+ }
+ {
+ std::vector<android::os::WorkDuration> actualWorkDurations;
+ android::os::WorkDuration workDuration(1, 20, 13, -8);
+ actualWorkDurations.push_back(workDuration);
+
+ EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ .Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration2(session,
+ static_cast<AWorkDuration*>(
+ &workDuration));
+ EXPECT_EQ(EINVAL, result);
+ }
+
+ EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ APerformanceHint_closeSession(session);
+}
+
+TEST_F(PerformanceHintTest, TestAWorkDuration) {
+ AWorkDuration* aWorkDuration = AWorkDuration_create();
+ ASSERT_NE(aWorkDuration, nullptr);
+
+ AWorkDuration_setWorkPeriodStartTimestampNanos(aWorkDuration, 1);
+ AWorkDuration_setActualTotalDurationNanos(aWorkDuration, 20);
+ AWorkDuration_setActualCpuDurationNanos(aWorkDuration, 13);
+ AWorkDuration_setActualGpuDurationNanos(aWorkDuration, 8);
+ AWorkDuration_release(aWorkDuration);
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm b/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
index 90041da..24b4d2f 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
@@ -14,8 +14,8 @@
#
# Ukrainian keyboard layout.
-# This is a typical Ukrainian PC keyboard layout.
-# As an added convenience, English characters are accessible using ralt (Alt Gr).
+# Based on PC enhanced Ukrainian layout with added Unicode keys based on
+# the Linux one.
#
type OVERLAY
@@ -25,32 +25,34 @@
### ROW 1
key GRAVE {
- label: '\u0401'
- base: '\u0451'
- shift, capslock: '\u0401'
- shift+capslock: '\u0451'
- ralt: '`'
+ label: '\''
+ base: '\''
+ shift: '\u02bc'
+ ralt: '\u0301'
ralt+shift: '~'
}
key 1 {
label: '1'
base: '1'
- shift, ralt: '!'
+ shift: '!'
+ ralt: '\u00b9'
}
key 2 {
label: '2'
base: '2'
shift: '"'
- ralt: '@'
+ ralt: '\u00b2'
+ ralt+shift: '\u2019'
}
key 3 {
label: '3'
base: '3'
shift: '\u2116'
- ralt: '#'
+ ralt: '\u00a7'
+ ralt+shift: '\u20b4'
}
key 4 {
@@ -58,60 +60,67 @@
base: '4'
shift: ';'
ralt: '$'
+ ralt+shift: '\u20ac'
}
key 5 {
label: '5'
base: '5'
- shift, ralt: '%'
+ shift: '%'
+ ralt: '\u00b0'
}
key 6 {
label: '6'
base: '6'
shift: ':'
- ralt: '^'
+ ralt: '<'
}
key 7 {
label: '7'
base: '7'
shift: '?'
- ralt: '&'
+ ralt: '>'
}
key 8 {
label: '8'
base: '8'
- shift, ralt: '*'
+ shift: '*'
+ ralt: '\u2022'
}
key 9 {
label: '9'
base: '9'
- shift, ralt: '('
+ shift: '('
+ ralt: '['
+ ralt+shift: '{'
}
key 0 {
label: '0'
base: '0'
- shift, ralt: ')'
+ shift: ')'
+ ralt: ']'
+ ralt+shift: '}'
}
key MINUS {
label: '-'
base: '-'
shift: '_'
- ralt: '-'
- shift+ralt: '_'
+ ralt: '\u2014'
+ shift+ralt: '\u2013'
}
key EQUALS {
label: '='
base: '='
shift: '+'
- ralt: '='
- shift+ralt: '+'
+ ralt: '\u2260'
+ shift+ralt: '\u00b1'
}
### ROW 2
@@ -121,6 +130,9 @@
base: '\u0439'
shift, capslock: '\u0419'
shift+capslock: '\u0439'
+ ralt: '\u0458'
+ ralt+shift, ralt+capslock: '\u0408'
+ ralt+shift+capslock: '\u0458'
}
key W {
@@ -128,6 +140,9 @@
base: '\u0446'
shift, capslock: '\u0426'
shift+capslock: '\u0446'
+ ralt: '\u045f'
+ ralt+shift, ralt+capslock: '\u040f'
+ ralt+shift+capslock: '\u045f'
}
key E {
@@ -135,6 +150,9 @@
base: '\u0443'
shift, capslock: '\u0423'
shift+capslock: '\u0443'
+ ralt: '\u045e'
+ ralt+shift, ralt+capslock: '\u040e'
+ ralt+shift+capslock: '\u045e'
}
key R {
@@ -142,6 +160,7 @@
base: '\u043a'
shift, capslock: '\u041a'
shift+capslock: '\u043a'
+ ralt: '\u00ae'
}
key T {
@@ -149,6 +168,9 @@
base: '\u0435'
shift, capslock: '\u0415'
shift+capslock: '\u0435'
+ ralt: '\u0451'
+ ralt+shift, ralt+capslock: '\u0401'
+ ralt+shift+capslock: '\u0451'
}
key Y {
@@ -156,6 +178,9 @@
base: '\u043d'
shift, capslock: '\u041d'
shift+capslock: '\u043d'
+ ralt: '\u045a'
+ ralt+shift, ralt+capslock: '\u040a'
+ ralt+shift+capslock: '\u045a'
}
key U {
@@ -164,8 +189,8 @@
shift, capslock: '\u0413'
shift+capslock: '\u0433'
ralt: '\u0491'
- shift+ralt, capslock+ralt: '\u0490'
- shift+capslock+ralt: '\u0491'
+ ralt+shift, ralt+capslock: '\u0490'
+ ralt+shift+capslock: '\u0491'
}
key I {
@@ -201,6 +226,9 @@
base: '\u0457'
shift, capslock: '\u0407'
shift+capslock: '\u0457'
+ ralt: '\u044a'
+ ralt+shift, ralt+capslock: '\u042a'
+ ralt+shift+capslock: '\u044a'
}
### ROW 3
@@ -217,6 +245,9 @@
base: '\u0456'
shift, capslock: '\u0406'
shift+capslock: '\u0456'
+ ralt: '\u044b'
+ ralt+shift, ralt+capslock: '\u042b'
+ ralt+shift+capslock: '\u044b'
}
key D {
@@ -259,6 +290,9 @@
base: '\u043b'
shift, capslock: '\u041b'
shift+capslock: '\u043b'
+ ralt: '\u0459'
+ ralt+shift, ralt+capslock: '\u0409'
+ ralt+shift+capslock: '\u0459'
}
key L {
@@ -266,6 +300,9 @@
base: '\u0434'
shift, capslock: '\u0414'
shift+capslock: '\u0434'
+ ralt: '\u0452'
+ ralt+shift, ralt+capslock: '\u0402'
+ ralt+shift+capslock: '\u0452'
}
key SEMICOLON {
@@ -282,15 +319,18 @@
base: '\u0454'
shift, capslock: '\u0404'
shift+capslock: '\u0454'
- ralt: '\''
- ralt+shift: '"'
+ ralt: '\u044d'
+ ralt+shift, ralt+capslock: '\u042d'
+ ralt+shift+capslock: '\u044d'
}
key BACKSLASH {
label: '\\'
base: '\\'
shift: '/'
- ralt: '|'
+ ralt: '\u0491'
+ ralt+shift, ralt+capslock: '\u0490'
+ ralt+shift+capslock: '\u0491'
}
### ROW 4
@@ -316,6 +356,9 @@
base: '\u0447'
shift, capslock: '\u0427'
shift+capslock: '\u0447'
+ ralt: '\u045b'
+ ralt+shift, ralt+capslock: '\u040b'
+ ralt+shift+capslock: '\u045b'
}
key C {
@@ -323,6 +366,7 @@
base: '\u0441'
shift, capslock: '\u0421'
shift+capslock: '\u0441'
+ ralt: '\u00a9'
}
key V {
@@ -344,6 +388,7 @@
base: '\u0442'
shift, capslock: '\u0422'
shift+capslock: '\u0442'
+ ralt: '\u2122'
}
key M {
@@ -358,8 +403,8 @@
base: '\u0431'
shift, capslock: '\u0411'
shift+capslock: '\u0431'
- ralt: ','
- ralt+shift: '<'
+ ralt: '\u00ab'
+ ralt+shift: '\u201e'
}
key PERIOD {
@@ -367,8 +412,8 @@
base: '\u044e'
shift, capslock: '\u042e'
shift+capslock: '\u044e'
- ralt: '.'
- ralt+shift: '>'
+ ralt: '\u00bb'
+ ralt+shift: '\u201c'
}
key SLASH {
@@ -376,5 +421,5 @@
base: '.'
shift: ','
ralt: '/'
- ralt+shift: '?'
+ ralt+shift: '\u2026'
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
index 4e28d77..09be768 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
@@ -116,6 +116,7 @@
int flags = allUsers ? PackageManager.DELETE_ALL_USERS : 0;
flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0;
+ flags |= getIntent().getIntExtra(PackageInstaller.EXTRA_DELETE_FLAGS, 0);
createContextAsUser(user, 0).getPackageManager().getPackageInstaller().uninstall(
new VersionedPackage(mAppInfo.packageName,
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
index ba627e9..5c9b728 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -19,6 +19,7 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.content.pm.Flags.usePiaV2;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;
import android.Manifest;
@@ -55,8 +56,8 @@
import com.android.packageinstaller.television.ErrorFragment;
import com.android.packageinstaller.television.UninstallAlertFragment;
import com.android.packageinstaller.television.UninstallAppProgress;
-
import com.android.packageinstaller.v2.ui.UninstallLaunch;
+
import java.util.List;
/*
@@ -76,6 +77,7 @@
public boolean allUsers;
public UserHandle user;
public PackageManager.UninstallCompleteCallback callback;
+ public int deleteFlags;
}
private String mPackageName;
@@ -226,10 +228,26 @@
// Continue as the ActivityInfo isn't critical.
}
}
+ parseDeleteFlags(intent);
showConfirmationDialog();
}
+ /**
+ * Parses specific {@link android.content.pm.PackageManager.DeleteFlags} from {@link Intent}
+ * to archive an app if requested.
+ *
+ * Do not parse any flags because developers might pass here any flags which might cause
+ * unintended behaviour.
+ * For more context {@link com.android.server.pm.PackageArchiver#requestArchive}.
+ */
+ private void parseDeleteFlags(Intent intent) {
+ int deleteFlags = intent.getIntExtra(PackageInstaller.EXTRA_DELETE_FLAGS, 0);
+ int archive = deleteFlags & PackageManager.DELETE_ARCHIVE;
+ int keepData = deleteFlags & PackageManager.DELETE_KEEP_DATA;
+ mDialogInfo.deleteFlags = archive | keepData;
+ }
+
public DialogInfo getDialogInfo() {
return mDialogInfo;
}
@@ -347,7 +365,10 @@
if (returnResult || getCallingActivity() != null) {
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
}
-
+ if (mDialogInfo.deleteFlags != 0) {
+ newIntent.putExtra(PackageInstaller.EXTRA_DELETE_FLAGS,
+ mDialogInfo.deleteFlags);
+ }
startActivity(newIntent);
} else {
int uninstallId;
@@ -393,6 +414,7 @@
int flags = mDialogInfo.allUsers ? PackageManager.DELETE_ALL_USERS : 0;
flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0;
+ flags |= mDialogInfo.deleteFlags;
createContextAsUser(mDialogInfo.user, 0).getPackageManager().getPackageInstaller()
.uninstall(new VersionedPackage(mDialogInfo.appInfo.packageName,
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
index 6979825..e4befc2 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
@@ -70,6 +70,7 @@
<style name="SettingsSwitchPreferenceCompat.SettingsLib" parent="@style/Preference.SwitchPreferenceCompat.Material">
<item name="layout">@layout/settingslib_preference</item>
+ <item name="singleLineTitle">false</item>
<item name="iconSpaceReserved">@bool/settingslib_config_icon_space_reserved</item>
</style>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
similarity index 71%
rename from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt
rename to packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
index de5c558..8f67354 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.settingslib.spaprivileged.database
import android.content.Context
import android.database.ContentObserver
-import android.os.Handler
-import android.provider.Settings
+import android.net.Uri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -27,20 +26,19 @@
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn
-internal fun <T> Context.settingsGlobalFlow(
- name: String,
- sendInitialValue: Boolean = true,
- value: () -> T,
-): Flow<T> = callbackFlow {
- val contentObserver = object : ContentObserver(Handler.getMain()) {
+/** Content change flow for the given [uri]. */
+internal fun Context.contentChangeFlow(
+ uri: Uri,
+ sendInitial: Boolean = true,
+): Flow<Unit> = callbackFlow {
+ val contentObserver = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
- trySend(value())
+ trySend(Unit)
}
}
- val uri = Settings.Global.getUriFor(name)
contentResolver.registerContentObserver(uri, false, contentObserver)
- if (sendInitialValue) {
- trySend(value())
+ if (sendInitial) {
+ trySend(Unit)
}
awaitClose { contentResolver.unregisterContentObserver(contentObserver) }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
similarity index 91%
rename from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
rename to packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
index 8e28bf8..5d67f57 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
@@ -22,13 +22,15 @@
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
fun Context.settingsGlobalBoolean(name: String, defaultValue: Boolean = false):
ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)
fun Context.settingsGlobalBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
val value by settingsGlobalBoolean(name, defaultValue)
- return settingsGlobalFlow(name) { value }
+ return settingsGlobalChangeFlow(name).map { value }.distinctUntilChanged()
}
private class SettingsGlobalBooleanDelegate(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlow.kt
similarity index 82%
rename from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
rename to packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlow.kt
index 4098987..675b2e5 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlow.kt
@@ -17,7 +17,9 @@
package com.android.settingslib.spaprivileged.settingsprovider
import android.content.Context
+import android.provider.Settings
+import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlinx.coroutines.flow.Flow
fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+ contentChangeFlow(Settings.Global.getUriFor(name), sendInitialValue)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
similarity index 67%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
copy to packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
index 8e28bf8..25090a4 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
@@ -19,19 +19,22 @@
import android.content.ContentResolver
import android.content.Context
import android.provider.Settings
+import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
-fun Context.settingsGlobalBoolean(name: String, defaultValue: Boolean = false):
- ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)
+fun Context.settingsSecureBoolean(name: String, defaultValue: Boolean = false):
+ ReadWriteProperty<Any?, Boolean> = SettingsSecureBooleanDelegate(this, name, defaultValue)
-fun Context.settingsGlobalBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
- val value by settingsGlobalBoolean(name, defaultValue)
- return settingsGlobalFlow(name) { value }
+fun Context.settingsSecureBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
+ val value by settingsSecureBoolean(name, defaultValue)
+ return contentChangeFlow(Settings.Secure.getUriFor(name)).map { value }.distinctUntilChanged()
}
-private class SettingsGlobalBooleanDelegate(
+private class SettingsSecureBooleanDelegate(
context: Context,
private val name: String,
private val defaultValue: Boolean = false,
@@ -40,9 +43,9 @@
private val contentResolver: ContentResolver = context.contentResolver
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean =
- Settings.Global.getInt(contentResolver, name, if (defaultValue) 1 else 0) != 0
+ Settings.Secure.getInt(contentResolver, name, if (defaultValue) 1 else 0) != 0
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
- Settings.Global.putInt(contentResolver, name, if (value) 1 else 0)
+ Settings.Secure.putInt(contentResolver, name, if (value) 1 else 0)
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 45295b0..f306918 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -89,7 +89,7 @@
@Composable
fun FooterAppVersion(showPackageName: Boolean = rememberIsDevelopmentSettingsEnabled()) {
val context = LocalContext.current
- val footer = remember(showPackageName) {
+ val footer = remember(packageInfo, showPackageName) {
val list = mutableListOf<String>()
packageInfo.versionNameBidiWrapped?.let {
list += context.getString(R.string.version_text, it)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
index 626c913..7a4f81c 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
@@ -37,7 +37,7 @@
@Composable
fun ApplicationInfo.getStorageSize(): State<String> {
val context = LocalContext.current
- return remember {
+ return remember(this) {
flow {
val sizeBytes = calculateSizeBytes(context)
this.emit(if (sizeBytes != null) Formatter.formatFileSize(context, sizeBytes) else "")
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
index 44973a7..f292231 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
@@ -126,10 +126,7 @@
val flags = argumentCaptor<ApplicationInfoFlags> {
verify(packageManager).getInstalledApplicationsAsUser(capture(), eq(ADMIN_USER_ID))
}.firstValue
- assertThat(flags.value).isEqualTo(
- PackageManager.MATCH_DISABLED_COMPONENTS or
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- )
+ assertThat(flags.value and PackageManager.MATCH_ANY_USER.toLong()).isEqualTo(0L)
}
@Test
@@ -276,21 +273,6 @@
}
@Test
- fun loadApps_archivedAppsDisabled() = runTest {
- mockInstalledApplications(listOf(NORMAL_APP), ADMIN_USER_ID)
- val appList = repository.loadApps(userId = ADMIN_USER_ID)
-
- assertThat(appList).containsExactly(NORMAL_APP)
- val flags = argumentCaptor<ApplicationInfoFlags> {
- verify(packageManager).getInstalledApplicationsAsUser(capture(), eq(ADMIN_USER_ID))
- }.firstValue
- assertThat(flags.value).isEqualTo(
- PackageManager.MATCH_DISABLED_COMPONENTS or
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- )
- }
-
- @Test
fun showSystemPredicate_showSystem() = runTest {
val app = SYSTEM_APP
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
similarity index 98%
rename from packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
rename to packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
index 996c2d5..70b38fe 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
@@ -30,7 +30,7 @@
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
-class SettingsGlobalBooleanRepositoryTest {
+class SettingsGlobalBooleanTest {
private val context: Context = ApplicationProvider.getApplicationContext()
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlowTest.kt
similarity index 95%
rename from packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt
rename to packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlowTest.kt
index 37e00e6..2e6a396 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeFlowTest.kt
@@ -29,7 +29,7 @@
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
-class SettingsGlobalChangeRepositoryTest {
+class SettingsGlobalChangeFlowTest {
private val context: Context = ApplicationProvider.getApplicationContext()
@@ -52,7 +52,7 @@
var value by context.settingsGlobalBoolean(TEST_NAME)
value = false
- val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+ val flow = context.settingsGlobalChangeFlow(TEST_NAME)
value = true
assertThat(flow.toListWithTimeout()).hasSize(1)
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
similarity index 67%
copy from packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
copy to packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
index 996c2d5..29a89be 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
@@ -30,74 +30,74 @@
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
-class SettingsGlobalBooleanRepositoryTest {
+class SettingsSecureBooleanTest {
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun getValue_setTrue_returnTrue() {
- Settings.Global.putInt(context.contentResolver, TEST_NAME, 1)
+ Settings.Secure.putInt(context.contentResolver, TEST_NAME, 1)
- val value by context.settingsGlobalBoolean(TEST_NAME)
+ val value by context.settingsSecureBoolean(TEST_NAME)
assertThat(value).isTrue()
}
@Test
fun getValue_setFalse_returnFalse() {
- Settings.Global.putInt(context.contentResolver, TEST_NAME, 0)
+ Settings.Secure.putInt(context.contentResolver, TEST_NAME, 0)
- val value by context.settingsGlobalBoolean(TEST_NAME)
+ val value by context.settingsSecureBoolean(TEST_NAME)
assertThat(value).isFalse()
}
@Test
fun setValue_setTrue_returnTrue() {
- var value by context.settingsGlobalBoolean(TEST_NAME)
+ var value by context.settingsSecureBoolean(TEST_NAME)
value = true
- assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 0)).isEqualTo(1)
+ assertThat(Settings.Secure.getInt(context.contentResolver, TEST_NAME, 0)).isEqualTo(1)
}
@Test
fun setValue_setFalse_returnFalse() {
- var value by context.settingsGlobalBoolean(TEST_NAME)
+ var value by context.settingsSecureBoolean(TEST_NAME)
value = false
- assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 1)).isEqualTo(0)
+ assertThat(Settings.Secure.getInt(context.contentResolver, TEST_NAME, 1)).isEqualTo(0)
}
@Test
- fun settingsGlobalBooleanFlow_valueNotChanged() = runBlocking {
- var value by context.settingsGlobalBoolean(TEST_NAME)
+ fun settingsSecureBooleanFlow_valueNotChanged() = runBlocking {
+ var value by context.settingsSecureBoolean(TEST_NAME)
value = false
- val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+ val flow = context.settingsSecureBooleanFlow(TEST_NAME)
assertThat(flow.firstWithTimeoutOrNull()).isFalse()
}
@Test
- fun settingsGlobalBooleanFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
- var value by context.settingsGlobalBoolean(TEST_NAME)
+ fun settingsSecureBooleanFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
+ var value by context.settingsSecureBoolean(TEST_NAME)
value = false
- val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+ val flow = context.settingsSecureBooleanFlow(TEST_NAME)
value = true
assertThat(flow.firstWithTimeoutOrNull()).isTrue()
}
@Test
- fun settingsGlobalBooleanFlow_collectBeforeValueChanged_getBoth() = runBlocking {
- var value by context.settingsGlobalBoolean(TEST_NAME)
+ fun settingsSecureBooleanFlow_collectBeforeValueChanged_getBoth() = runBlocking {
+ var value by context.settingsSecureBoolean(TEST_NAME)
value = false
val listDeferred = async {
- context.settingsGlobalBooleanFlow(TEST_NAME).toListWithTimeout()
+ context.settingsSecureBooleanFlow(TEST_NAME).toListWithTimeout()
}
delay(100)
value = true
diff --git a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
index 4936f88..f3e537b 100644
--- a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
@@ -12,4 +12,11 @@
namespace: "tv_system_ui"
description: "Gates all the changes for the tv specific media output dialog"
bug: "303205631"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "enable_output_switcher_for_system_routing"
+ namespace: "media_solutions"
+ description: "Enable Output Switcher when no media is playing."
+ bug: "284227163"
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index ed5654d..ec50323 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2432,9 +2432,7 @@
R.bool.def_auto_time_zone); // Sync timezone to NITZ
loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
- ("1".equals(SystemProperties.get("ro.boot.qemu"))
- || res.getBoolean(R.bool.def_stay_on_while_plugged_in))
- ? 1 : 0);
+ res.getBoolean(R.bool.def_stay_on_while_plugged_in) ? 1 : 0);
loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY,
R.integer.def_wifi_sleep_policy);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 650319f..b6a0c7b 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -442,6 +442,9 @@
<uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS" />
+ <!-- Permission required for CTS test - CtsNfcResolverDerviceTest -->
+ <uses-permission android:name="android.permission.SHOW_CUSTOMIZED_RESOLVER" />
+
<!-- Permission needed for CTS test - MusicRecognitionManagerTest -->
<uses-permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" />
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 77c4aa6..d8d3f87 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -188,3 +188,9 @@
bug: "305049544"
}
+flag {
+ name: "fast_unlock_transition"
+ namespace: "systemui"
+ description: "Faster wallpaper unlock transition"
+ bug: "298186160"
+}
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 ba80a8d..1a653c3 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
@@ -34,9 +34,9 @@
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -66,6 +66,7 @@
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
@@ -97,7 +98,7 @@
fun BouncerContent(
viewModel: BouncerViewModel,
dialogFactory: BouncerDialogFactory,
- modifier: Modifier
+ modifier: Modifier = Modifier,
) {
val isFullScreenUserSwitcherEnabled = viewModel.isUserSwitcherVisible
val isSideBySideSupported by viewModel.isSideBySideSupported.collectAsState()
@@ -142,6 +143,7 @@
viewModel: BouncerViewModel,
dialogFactory: BouncerDialogFactory,
modifier: Modifier = Modifier,
+ layout: BouncerSceneLayout = BouncerSceneLayout.STANDARD,
outputOnly: Boolean = false,
) {
val foldPosture: FoldPosture by foldPosture()
@@ -161,6 +163,7 @@
FoldSplittable(
viewModel = viewModel,
dialogFactory = dialogFactory,
+ layout = layout,
outputOnly = outputOnly,
isSplit = false,
)
@@ -170,6 +173,7 @@
FoldSplittable(
viewModel = viewModel,
dialogFactory = dialogFactory,
+ layout = layout,
outputOnly = outputOnly,
isSplit = true,
)
@@ -193,6 +197,7 @@
private fun SceneScope.FoldSplittable(
viewModel: BouncerViewModel,
dialogFactory: BouncerDialogFactory,
+ layout: BouncerSceneLayout,
outputOnly: Boolean,
isSplit: Boolean,
modifier: Modifier = Modifier,
@@ -210,13 +215,21 @@
// Content above the fold, when split on a foldable device in a "table top" posture:
Box(
modifier =
- Modifier.element(SceneElements.AboveFold).fillMaxWidth().thenIf(isSplit) {
- Modifier.weight(splitRatio)
- },
+ Modifier.element(SceneElements.AboveFold)
+ .fillMaxWidth()
+ .then(
+ if (isSplit) {
+ Modifier.weight(splitRatio)
+ } else if (outputOnly) {
+ Modifier.fillMaxHeight()
+ } else {
+ Modifier
+ }
+ ),
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier.fillMaxWidth().padding(top = 92.dp),
+ modifier = Modifier.fillMaxWidth().padding(top = layout.topPadding),
) {
Crossfade(
targetState = message,
@@ -230,11 +243,23 @@
)
}
- Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
+ if (!outputOnly) {
+ Spacer(Modifier.height(layout.spacingBetweenMessageAndEnteredInput))
+ UserInputArea(
+ viewModel = viewModel,
+ visibility = UserInputAreaVisibility.OUTPUT_ONLY,
+ layout = layout,
+ )
+ }
+ }
+
+ if (outputOnly) {
UserInputArea(
viewModel = viewModel,
visibility = UserInputAreaVisibility.OUTPUT_ONLY,
+ layout = layout,
+ modifier = Modifier.align(Alignment.Center),
)
}
}
@@ -242,25 +267,32 @@
// Content below the fold, when split on a foldable device in a "table top" posture:
Box(
modifier =
- Modifier.element(SceneElements.BelowFold).fillMaxWidth().thenIf(isSplit) {
- Modifier.weight(1 - splitRatio)
- },
+ Modifier.element(SceneElements.BelowFold)
+ .fillMaxWidth()
+ .weight(
+ if (isSplit) {
+ 1 - splitRatio
+ } else {
+ 1f
+ }
+ ),
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier.fillMaxWidth(),
+ modifier = Modifier.fillMaxSize()
) {
if (!outputOnly) {
Box(Modifier.weight(1f)) {
UserInputArea(
viewModel = viewModel,
visibility = UserInputAreaVisibility.INPUT_ONLY,
- modifier = Modifier.align(Alignment.Center),
+ layout = layout,
+ modifier = Modifier.align(Alignment.BottomCenter),
)
}
}
- Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
+ Spacer(Modifier.height(48.dp))
val actionButtonModifier = Modifier.height(56.dp)
@@ -275,7 +307,7 @@
}
}
- Spacer(Modifier.height(48.dp))
+ Spacer(Modifier.height(layout.bottomPadding))
}
}
@@ -311,6 +343,7 @@
private fun UserInputArea(
viewModel: BouncerViewModel,
visibility: UserInputAreaVisibility,
+ layout: BouncerSceneLayout,
modifier: Modifier = Modifier,
) {
val authMethodViewModel: AuthMethodBouncerViewModel? by
@@ -327,6 +360,7 @@
UserInputAreaVisibility.INPUT_ONLY ->
PinPad(
viewModel = nonNullViewModel,
+ layout = layout,
modifier = modifier,
)
}
@@ -341,7 +375,8 @@
if (visibility == UserInputAreaVisibility.INPUT_ONLY) {
PatternBouncer(
viewModel = nonNullViewModel,
- modifier = modifier.aspectRatio(1f, matchHeightConstraintsFirst = false)
+ layout = layout,
+ modifier = modifier.aspectRatio(1f, matchHeightConstraintsFirst = false),
)
}
else -> Unit
@@ -449,7 +484,7 @@
}
/**
- * Renders the dropdown menu that displays the actual users and/or user actions that can be
+ * Renders the dropdowm menu that displays the actual users and/or user actions that can be
* selected.
*/
@Composable
@@ -519,6 +554,7 @@
StandardLayout(
viewModel = viewModel,
dialogFactory = dialogFactory,
+ layout = BouncerSceneLayout.SPLIT,
outputOnly = true,
modifier = startContentModifier,
)
@@ -527,10 +563,12 @@
UserInputArea(
viewModel = viewModel,
visibility = UserInputAreaVisibility.INPUT_ONLY,
+ layout = BouncerSceneLayout.SPLIT,
modifier = endContentModifier,
)
},
- modifier = modifier
+ layout = BouncerSceneLayout.SPLIT,
+ modifier = modifier,
)
}
@@ -542,6 +580,7 @@
private fun SwappableLayout(
startContent: @Composable (Modifier) -> Unit,
endContent: @Composable (Modifier) -> Unit,
+ layout: BouncerSceneLayout,
modifier: Modifier = Modifier,
) {
val layoutDirection = LocalLayoutDirection.current
@@ -597,7 +636,7 @@
alpha = animatedAlpha(animatedOffset)
}
) {
- endContent(Modifier.widthIn(max = 400.dp).align(Alignment.BottomCenter))
+ endContent(Modifier.align(layout.swappableEndContentAlignment).widthIn(max = 400.dp))
}
}
}
@@ -635,9 +674,11 @@
StandardLayout(
viewModel = viewModel,
dialogFactory = dialogFactory,
+ layout = BouncerSceneLayout.SIDE_BY_SIDE,
modifier = endContentModifier,
)
},
+ layout = BouncerSceneLayout.SIDE_BY_SIDE,
modifier = modifier,
)
}
@@ -663,6 +704,7 @@
StandardLayout(
viewModel = viewModel,
dialogFactory = dialogFactory,
+ layout = BouncerSceneLayout.STACKED,
modifier = Modifier.fillMaxWidth().weight(1f),
)
}
@@ -732,3 +774,48 @@
private val SceneTransitions = transitions {
from(SceneKeys.ContiguousSceneKey, to = SceneKeys.SplitSceneKey) { spec = tween() }
}
+
+/** Whether a more compact size should be used for various spacing dimensions. */
+internal val BouncerSceneLayout.isUseCompactSize: Boolean
+ get() =
+ when (this) {
+ BouncerSceneLayout.SIDE_BY_SIDE -> true
+ BouncerSceneLayout.SPLIT -> true
+ else -> false
+ }
+
+/** Amount of space to place between the message and the entered input UI elements, in dips. */
+private val BouncerSceneLayout.spacingBetweenMessageAndEnteredInput: Dp
+ get() =
+ when {
+ this == BouncerSceneLayout.STACKED -> 24.dp
+ isUseCompactSize -> 96.dp
+ else -> 128.dp
+ }
+
+/** Amount of space to place above the topmost UI element, in dips. */
+private val BouncerSceneLayout.topPadding: Dp
+ get() =
+ if (this == BouncerSceneLayout.SPLIT) {
+ 40.dp
+ } else {
+ 92.dp
+ }
+
+/** Amount of space to place below the bottommost UI element, in dips. */
+private val BouncerSceneLayout.bottomPadding: Dp
+ get() =
+ if (this == BouncerSceneLayout.SPLIT) {
+ 40.dp
+ } else {
+ 48.dp
+ }
+
+/** The in-a-box alignment for the content on the "end" side of a swappable layout. */
+private val BouncerSceneLayout.swappableEndContentAlignment: Alignment
+ get() =
+ if (this == BouncerSceneLayout.SPLIT) {
+ Alignment.Center
+ } else {
+ Alignment.BottomCenter
+ }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
index eb06889..2799959 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
@@ -18,8 +18,6 @@
import android.view.ViewTreeObserver
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.LocalTextStyle
@@ -31,7 +29,6 @@
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@@ -64,10 +61,6 @@
focusRequester.requestFocus()
}
}
- val (isTextFieldFocused, onTextFieldFocusChanged) = remember { mutableStateOf(false) }
- LaunchedEffect(isTextFieldFocused) {
- viewModel.onTextFieldFocusChanged(isFocused = isTextFieldFocused)
- }
val password: String by viewModel.password.collectAsState()
val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsState()
@@ -113,7 +106,7 @@
),
modifier =
Modifier.focusRequester(focusRequester)
- .onFocusChanged { onTextFieldFocusChanged(it.isFocused) }
+ .onFocusChanged { viewModel.onTextFieldFocusChanged(it.isFocused) }
.drawBehind {
drawLine(
color = color,
@@ -123,8 +116,6 @@
)
},
)
-
- Spacer(Modifier.height(100.dp))
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index ff1cbd6..a4b1955 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -48,6 +48,7 @@
import com.android.compose.animation.Easings
import com.android.compose.modifiers.thenIf
import com.android.internal.R
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout
import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
import kotlin.math.min
@@ -64,6 +65,7 @@
@Composable
internal fun PatternBouncer(
viewModel: PatternBouncerViewModel,
+ layout: BouncerSceneLayout,
modifier: Modifier = Modifier,
) {
DisposableEffect(Unit) {
@@ -190,6 +192,8 @@
// This is the position of the input pointer.
var inputPosition: Offset? by remember { mutableStateOf(null) }
var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
+ var offset: Offset by remember { mutableStateOf(Offset.Zero) }
+ var scale: Float by remember { mutableStateOf(1f) }
Canvas(
modifier
@@ -224,21 +228,42 @@
},
) { change, _ ->
inputPosition = change.position
- viewModel.onDrag(
- xPx = change.position.x,
- yPx = change.position.y,
- containerSizePx = size.width,
- )
+ change.position.minus(offset).div(scale).let {
+ viewModel.onDrag(
+ xPx = it.x,
+ yPx = it.y,
+ containerSizePx = size.width,
+ )
+ }
}
}
}
) {
gridCoordinates?.let { nonNullCoordinates ->
val containerSize = nonNullCoordinates.size
+ if (containerSize.width <= 0 || containerSize.height <= 0) {
+ return@let
+ }
+
val horizontalSpacing = containerSize.width.toFloat() / colCount
val verticalSpacing = containerSize.height.toFloat() / rowCount
val spacing = min(horizontalSpacing, verticalSpacing)
- val verticalOffset = containerSize.height - spacing * rowCount
+ val horizontalOffset =
+ offset(
+ availableSize = containerSize.width,
+ spacingPerDot = spacing,
+ dotCount = colCount,
+ isCentered = true,
+ )
+ val verticalOffset =
+ offset(
+ availableSize = containerSize.height,
+ spacingPerDot = spacing,
+ dotCount = rowCount,
+ isCentered = layout.isCenteredVertically,
+ )
+ offset = Offset(horizontalOffset, verticalOffset)
+ scale = (colCount * spacing) / containerSize.width
if (isAnimationEnabled) {
// Draw lines between dots.
@@ -248,8 +273,9 @@
val lineFadeOutAnimationProgress =
lineFadeOutAnimatables[previousDot]!!.value
val startLerp = 1 - lineFadeOutAnimationProgress
- val from = pixelOffset(previousDot, spacing, verticalOffset)
- val to = pixelOffset(dot, spacing, verticalOffset)
+ val from =
+ pixelOffset(previousDot, spacing, horizontalOffset, verticalOffset)
+ val to = pixelOffset(dot, spacing, horizontalOffset, verticalOffset)
val lerpedFrom =
Offset(
x = from.x + (to.x - from.x) * startLerp,
@@ -270,7 +296,7 @@
// position.
inputPosition?.let { lineEnd ->
currentDot?.let { dot ->
- val from = pixelOffset(dot, spacing, verticalOffset)
+ val from = pixelOffset(dot, spacing, horizontalOffset, verticalOffset)
val lineLength =
sqrt((from.y - lineEnd.y).pow(2) + (from.x - lineEnd.x).pow(2))
drawLine(
@@ -288,7 +314,7 @@
// Draw each dot on the grid.
dots.forEach { dot ->
drawCircle(
- center = pixelOffset(dot, spacing, verticalOffset),
+ center = pixelOffset(dot, spacing, horizontalOffset, verticalOffset),
color = dotColor,
radius = dotRadius * (dotScalingAnimatables[dot]?.value ?: 1f),
)
@@ -301,10 +327,11 @@
private fun pixelOffset(
dot: PatternDotViewModel,
spacing: Float,
+ horizontalOffset: Float,
verticalOffset: Float,
): Offset {
return Offset(
- x = dot.x * spacing + spacing / 2,
+ x = dot.x * spacing + spacing / 2 + horizontalOffset,
y = dot.y * spacing + spacing / 2 + verticalOffset,
)
}
@@ -371,6 +398,35 @@
}
}
+/**
+ * Returns the amount of offset along the axis, in pixels, that should be applied to all dots.
+ *
+ * @param availableSize The size of the container, along the axis of interest.
+ * @param spacingPerDot The amount of pixels that each dot should take (including the area around
+ * that dot).
+ * @param dotCount The number of dots along the axis (e.g. if the axis of interest is the
+ * horizontal/x axis, this is the number of columns in the dot grid).
+ * @param isCentered Whether the dots should be centered along the axis of interest; if `false`, the
+ * dots will be pushed towards to end/bottom of the axis.
+ */
+private fun offset(
+ availableSize: Int,
+ spacingPerDot: Float,
+ dotCount: Int,
+ isCentered: Boolean = false,
+): Float {
+ val default = availableSize - spacingPerDot * dotCount
+ return if (isCentered) {
+ default / 2
+ } else {
+ default
+ }
+}
+
+/** Whether the UI should be centered vertically. */
+private val BouncerSceneLayout.isCenteredVertically: Boolean
+ get() = this == BouncerSceneLayout.SPLIT
+
private const val DOT_DIAMETER_DP = 16
private const val SELECTED_DOT_DIAMETER_DP = 24
private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83
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 59617c9..8f5d9f4 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
@@ -52,6 +52,7 @@
import com.android.compose.animation.Easings
import com.android.compose.grid.VerticalGrid
import com.android.compose.modifiers.thenIf
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout
import com.android.systemui.bouncer.ui.viewmodel.ActionButtonAppearance
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.common.shared.model.ContentDescription
@@ -65,9 +66,11 @@
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+/** Renders the PIN button pad. */
@Composable
fun PinPad(
viewModel: PinBouncerViewModel,
+ layout: BouncerSceneLayout,
modifier: Modifier = Modifier,
) {
DisposableEffect(Unit) {
@@ -92,9 +95,9 @@
}
VerticalGrid(
- columns = 3,
- verticalSpacing = 12.dp,
- horizontalSpacing = 20.dp,
+ columns = columns,
+ verticalSpacing = layout.verticalSpacing,
+ horizontalSpacing = calculateHorizontalSpacingBetweenColumns(layout.gridWidth),
modifier = modifier,
) {
repeat(9) { index ->
@@ -254,7 +257,7 @@
val cornerRadius: Dp by
animateDpAsState(
- if (isAnimationEnabled && isPressed) 24.dp else pinButtonSize / 2,
+ if (isAnimationEnabled && isPressed) 24.dp else pinButtonMaxSize / 2,
label = "PinButton round corners",
animationSpec = tween(animDurationMillis, easing = animEasing)
)
@@ -284,7 +287,7 @@
contentAlignment = Alignment.Center,
modifier =
modifier
- .sizeIn(maxWidth = pinButtonSize, maxHeight = pinButtonSize)
+ .sizeIn(maxWidth = pinButtonMaxSize, maxHeight = pinButtonMaxSize)
.aspectRatio(1f)
.drawBehind {
drawRoundRect(
@@ -345,10 +348,32 @@
}
}
-private val pinButtonSize = 84.dp
-private val pinButtonErrorShrinkFactor = 67.dp / pinButtonSize
+/** Returns the amount of horizontal spacing between columns, in dips. */
+private fun calculateHorizontalSpacingBetweenColumns(
+ gridWidth: Dp,
+): Dp {
+ return (gridWidth - (pinButtonMaxSize * columns)) / (columns - 1)
+}
+
+/** The width of the grid of PIN pad buttons, in dips. */
+private val BouncerSceneLayout.gridWidth: Dp
+ get() = if (isUseCompactSize) 292.dp else 300.dp
+
+/** The spacing between rows of PIN pad buttons, in dips. */
+private val BouncerSceneLayout.verticalSpacing: Dp
+ get() = if (isUseCompactSize) 8.dp else 12.dp
+
+/** Number of columns in the PIN pad grid. */
+private const val columns = 3
+/** Maximum size (width and height) of each PIN pad button. */
+private val pinButtonMaxSize = 84.dp
+/** Scale factor to apply to buttons when animating the "error" animation on them. */
+private val pinButtonErrorShrinkFactor = 67.dp / pinButtonMaxSize
+/** Animation duration of the "shrink" phase of the error animation, on each PIN pad button. */
private const val pinButtonErrorShrinkMs = 50
+/** Amount of time to wait between application of the "error" animation to each row of buttons. */
private const val pinButtonErrorStaggerDelayMs = 33
+/** Animation duration of the "revert" phase of the error animation, on each PIN pad button. */
private const val pinButtonErrorRevertMs = 617
// Pin button motion spec: http://shortn/_9TTIG6SoEa
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 2c4dc80..185a06c 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
@@ -7,6 +7,7 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
@@ -19,8 +20,10 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
@@ -28,6 +31,7 @@
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.SceneTransitionLayout
+import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.transitions
@@ -56,6 +60,7 @@
* This is a temporary container to allow the communal UI to use [SceneTransitionLayout] for gesture
* handling and transitions before the full Flexiglass layout is ready.
*/
+@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun CommunalContainer(
modifier: Modifier = Modifier,
@@ -65,6 +70,7 @@
viewModel.currentScene
.transform<CommunalSceneKey, SceneKey> { value -> value.toTransitionSceneKey() }
.collectAsState(TransitionSceneKey.Blank)
+ val sceneTransitionLayoutState = remember { SceneTransitionLayoutState(currentScene) }
// Don't show hub mode UI if keyguard is present. This is important since we're in the shade,
// which can be opened from many locations.
val isKeyguardShowing by viewModel.isKeyguardVisible.collectAsState(initial = false)
@@ -75,32 +81,59 @@
return
}
- SceneTransitionLayout(
- modifier = modifier.fillMaxSize(),
- currentScene = currentScene,
- onChangeScene = { sceneKey -> viewModel.onSceneChanged(sceneKey.toCommunalSceneKey()) },
- transitions = sceneTransitions,
- edgeDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize)
- ) {
- scene(
- TransitionSceneKey.Blank,
- userActions =
- mapOf(
- Swipe(SwipeDirection.Left, fromEdge = Edge.Right) to TransitionSceneKey.Communal
- )
+ Box(modifier = modifier.fillMaxSize()) {
+ SceneTransitionLayout(
+ modifier = Modifier.fillMaxSize(),
+ currentScene = currentScene,
+ onChangeScene = { sceneKey -> viewModel.onSceneChanged(sceneKey.toCommunalSceneKey()) },
+ transitions = sceneTransitions,
+ state = sceneTransitionLayoutState,
+ edgeDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize)
) {
- BlankScene { showSceneTransitionLayout = false }
+ scene(
+ TransitionSceneKey.Blank,
+ userActions =
+ mapOf(
+ Swipe(SwipeDirection.Left, fromEdge = Edge.Right) to
+ TransitionSceneKey.Communal
+ )
+ ) {
+ BlankScene { showSceneTransitionLayout = false }
+ }
+
+ scene(
+ TransitionSceneKey.Communal,
+ userActions =
+ mapOf(
+ Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to
+ TransitionSceneKey.Blank
+ ),
+ ) {
+ CommunalScene(viewModel, modifier = modifier)
+ }
}
- scene(
- TransitionSceneKey.Communal,
- userActions =
- mapOf(
- Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to TransitionSceneKey.Blank
- ),
- ) {
- CommunalScene(viewModel, modifier = modifier)
- }
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't
+ // block touches anymore.
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ // Offsetting to the left so that edge swipe to open the hub still works. This
+ // does mean that the very right edge of the hub won't refresh the screen
+ // timeout, but should be good enough for a temporary solution.
+ .offset(x = -ContainerDimensions.EdgeSwipeSize)
+ .pointerInteropFilter {
+ viewModel.onUserActivity()
+ if (
+ sceneTransitionLayoutState.transitionState.currentScene ==
+ TransitionSceneKey.Blank
+ ) {
+ viewModel.onOuterTouch(it)
+ return@pointerInteropFilter true
+ }
+ false
+ }
+ )
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 651594c..ca24d94 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -30,15 +30,15 @@
import com.android.systemui.log.core.MessageBuffer
import com.android.systemui.log.core.MessageInitializer
import com.android.systemui.log.core.MessagePrinter
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockId
-import com.android.systemui.plugins.ClockMetadata
-import com.android.systemui.plugins.ClockProvider
-import com.android.systemui.plugins.ClockProviderPlugin
-import com.android.systemui.plugins.ClockSettings
import com.android.systemui.plugins.PluginLifecycleManager
import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMetadata
+import com.android.systemui.plugins.clocks.ClockProvider
+import com.android.systemui.plugins.clocks.ClockProviderPlugin
+import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.util.Assert
import java.io.PrintWriter
import java.util.concurrent.ConcurrentHashMap
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 42ba643..141e1c1 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -25,16 +25,18 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.customization.R
import com.android.systemui.log.core.MessageBuffer
-import com.android.systemui.plugins.ClockAnimations
-import com.android.systemui.plugins.ClockConfig
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockEvents
-import com.android.systemui.plugins.ClockFaceConfig
-import com.android.systemui.plugins.ClockFaceController
-import com.android.systemui.plugins.ClockFaceEvents
-import com.android.systemui.plugins.ClockSettings
-import com.android.systemui.plugins.DefaultClockFaceLayout
-import com.android.systemui.plugins.WeatherData
+import com.android.systemui.plugins.clocks.AlarmData
+import com.android.systemui.plugins.clocks.ClockAnimations
+import com.android.systemui.plugins.clocks.ClockConfig
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockEvents
+import com.android.systemui.plugins.clocks.ClockFaceConfig
+import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockFaceEvents
+import com.android.systemui.plugins.clocks.ClockSettings
+import com.android.systemui.plugins.clocks.DefaultClockFaceLayout
+import com.android.systemui.plugins.clocks.WeatherData
+import com.android.systemui.plugins.clocks.ZenData
import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
@@ -53,6 +55,7 @@
private val resources: Resources,
private val settings: ClockSettings?,
private val hasStepClockAnimation: Boolean = false,
+ private val migratedClocks: Boolean = false,
) : ClockController {
override val smallClock: DefaultClockFaceController
override val largeClock: LargeClockFaceController
@@ -195,6 +198,10 @@
}
override fun recomputePadding(targetRegion: Rect?) {
+ // TODO(b/310989341): remove after changing migrate_clocks_to_blueprint to aconfig
+ if (migratedClocks) {
+ return
+ }
// We center the view within the targetRegion instead of within the parent
// view by computing the difference and adding that to the padding.
val lp = view.getLayoutParams() as FrameLayout.LayoutParams
@@ -251,6 +258,8 @@
}
override fun onWeatherDataChanged(data: WeatherData) {}
+ override fun onAlarmDataChanged(data: AlarmData) {}
+ override fun onZenDataChanged(data: ZenData) {}
}
open inner class DefaultClockAnimations(
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index dd52e39..a219be5 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -18,11 +18,11 @@
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import com.android.systemui.customization.R
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockId
-import com.android.systemui.plugins.ClockMetadata
-import com.android.systemui.plugins.ClockProvider
-import com.android.systemui.plugins.ClockSettings
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMetadata
+import com.android.systemui.plugins.clocks.ClockProvider
+import com.android.systemui.plugins.clocks.ClockSettings
private val TAG = DefaultClockProvider::class.simpleName
const val DEFAULT_CLOCK_ID = "DEFAULT"
@@ -32,7 +32,8 @@
val ctx: Context,
val layoutInflater: LayoutInflater,
val resources: Resources,
- val hasStepClockAnimation: Boolean = false
+ val hasStepClockAnimation: Boolean = false,
+ val migratedClocks: Boolean = false
) : ClockProvider {
override fun getClocks(): List<ClockMetadata> = listOf(ClockMetadata(DEFAULT_CLOCK_ID))
@@ -47,6 +48,7 @@
resources,
settings,
hasStepClockAnimation,
+ migratedClocks,
)
}
diff --git a/packages/SystemUI/docs/clock-plugins.md b/packages/SystemUI/docs/clock-plugins.md
index 9cb115a..fee82df 100644
--- a/packages/SystemUI/docs/clock-plugins.md
+++ b/packages/SystemUI/docs/clock-plugins.md
@@ -12,7 +12,7 @@
clock controller.
### Clock Library Code
-[ClockProvider and ClockController](../plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt)
+[ClockProvider and ClockController](../plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt)
serve as the interface between the lockscreen (or other host application) and the clock that is
being rendered. Implementing these interfaces is the primary integration point for rendering clocks
in SystemUI. Many of the methods have an empty default implementation and are optional for
@@ -29,12 +29,12 @@
The [ClockRegistry](../customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt)
determines which clock should be shown, and handles creating them. It does this by maintaining a
-list of [ClockProviders](../plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt) and
+list of [ClockProviders](../plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt) and
delegating work to them as appropriate. The DefaultClockProvider is compiled in so that it is
guaranteed to be available, and additional ClockProviders are loaded at runtime via
[PluginManager](../plugin_core/src/com/android/systemui/plugins/PluginManager.java).
-[ClockPlugin](../plugin/src/com/android/systemui/plugins/ClockPlugin.java) is deprecated and no
+[ClockPlugin](../plugin/src/com/android/systemui/plugins/clocks/ClockPlugin.java) is deprecated and no
longer used by keyguard to render clocks. The host code has been disabled but most of it is still
present in the source tree, although it will likely be removed in a later patch.
diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md
index 6ce7ee0..bfccbac 100644
--- a/packages/SystemUI/docs/plugin_hooks.md
+++ b/packages/SystemUI/docs/plugin_hooks.md
@@ -52,7 +52,7 @@
Use: Control over swipes/input for notification views, can be used to control what happens when you swipe/long-press
### Action: com.android.systemui.action.PLUGIN_CLOCK_PROVIDER
-Expected interface: [ClockProviderPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt)
+Expected interface: [ClockProviderPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt)
Use: Allows replacement of the keyguard main clock. See [additional Documentation](./clock-plugins.md).
diff --git a/packages/SystemUI/docs/qs-tiles.md b/packages/SystemUI/docs/qs-tiles.md
index bd0b4ab..ee388ec 100644
--- a/packages/SystemUI/docs/qs-tiles.md
+++ b/packages/SystemUI/docs/qs-tiles.md
@@ -4,25 +4,37 @@
## About this document
-This document is a more or less comprehensive summary of the state and infrastructure used by Quick Settings tiles. It provides descriptions about the lifecycle of a tile, how to create new tiles and how SystemUI manages and displays tiles, among other topics.
+This document is a more or less comprehensive summary of the state and infrastructure used by Quick
+Settings tiles. It provides descriptions about the lifecycle of a tile, how to create new tiles and
+how SystemUI manages and displays tiles, among other topics.
## What are Quick Settings Tiles?
-Quick Settings (from now on, QS) is the expanded panel that contains shortcuts for the user to toggle many settings. This is opened by expanding the notification drawer twice (or once when phone is locked). Quick Quick Settings (QQS) is the smaller panel that appears on top of the notifications before expanding twice and contains some of the toggles with no secondary line.
+Quick Settings (from now on, QS) is the expanded panel that contains shortcuts for the user to
+toggle many settings. This is opened by expanding the notification drawer twice (or once when phone
+is locked). Quick Quick Settings (QQS) is the smaller panel that appears on top of the notifications
+before expanding twice and contains some of the toggles with no secondary line.
-Each of these toggles that appear either in QS or QQS are called Quick Settings Tiles (or tiles for short). They allow the user to enable or disable settings quickly and sometimes provides access to more comprehensive settings pages.
+Each of these toggles that appear either in QS or QQS are called Quick Settings Tiles (or tiles for
+short). They allow the user to enable or disable settings quickly and sometimes provides access to
+more comprehensive settings pages.
The following image shows QQS on the left and QS on the right, with the tiles highlighted.

-QS Tiles usually depend on one or more Controllers that bind the tile with the necessary service. Controllers are obtained by the backend and used for communication between the user and the device.
+QS Tiles usually depend on one or more Controllers that bind the tile with the necessary service.
+Controllers are obtained by the backend and used for communication between the user and the device.
### A note on multi-user support
-All the classes described in this document that live inside SystemUI are only instantiated in the process of user 0. The different controllers that back the QS Tiles (also instantiated just in user 0) are user aware and provide an illusion of different instances for different users.
+All the classes described in this document that live inside SystemUI are only instantiated in the
+process of user 0. The different controllers that back the QS Tiles (also instantiated just in user
+0) are user aware and provide an illusion of different instances for different users.
-For an example on this, see [`RotationLockController`](/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java). This controller for the `RotationLockTile` listens to changes in all users.
+For an example on this,
+see [`RotationLockController`](/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java).
+This controller for the `RotationLockTile` listens to changes in all users.
## What are tiles made of?
@@ -30,104 +42,161 @@
QS Tiles are composed of the following backend classes.
-* [`QSTile`](/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java): Interface providing common behavior for all Tiles. This class also contains some useful utility classes needed for the tiles.
- * `Icon`: Defines the basic interface for an icon as used by the tiles.
- * `State`: Encapsulates the state of the Tile in order to communicate between the backend and the UI.
-* [`QSTileImpl`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java): Abstract implementation of `QSTile`, providing basic common behavior for all tiles. Also implements extensions for different types of `Icon`. All tiles currently defined in SystemUI subclass from this implementation.
-* [`SystemUI/src/com/android/systemui/qs/tiles`](/packages/SystemUI/src/com/android/systemui/qs/tiles): Each tile from SystemUI is defined here by a class that extends `QSTileImpl`. These implementations connect to corresponding controllers. The controllers serve two purposes:
- * track the state of the device and notify the tile when a change has occurred (for example, bluetooth connected to a device)
- * accept actions from the tiles to modify the state of the phone (for example, enablind and disabling wifi).
-* [`CustomTile`](/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java): Equivalent to the tiles in the previous item, but used for 3rd party tiles. In depth information to be found in [`CustomTile`](#customtile)
+* [`QSTile`](/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java): Interface
+ providing common behavior for all Tiles. This class also contains some useful utility classes
+ needed for the tiles.
+ * `Icon`: Defines the basic interface for an icon as used by the tiles.
+ * `State`: Encapsulates the state of the Tile in order to communicate between the backend and
+ the UI.
+* [`QSTileImpl`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java): Abstract
+ implementation of `QSTile`, providing basic common behavior for all tiles. Also implements
+ extensions for different types of `Icon`. All tiles currently defined in SystemUI subclass from
+ this implementation.
+* [`SystemUI/src/com/android/systemui/qs/tiles`](/packages/SystemUI/src/com/android/systemui/qs/tiles):
+ Each tile from SystemUI is defined here by a class that extends `QSTileImpl`. These
+ implementations connect to corresponding controllers. The controllers serve two purposes:
+ * track the state of the device and notify the tile when a change has occurred (for example,
+ bluetooth connected to a device)
+ * accept actions from the tiles to modify the state of the phone (for example, enablind and
+ disabling wifi).
+* [`CustomTile`](/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java):
+ Equivalent to the tiles in the previous item, but used for 3rd party tiles. In depth information
+ to be found in [`CustomTile`](#customtile)
-All the elements in SystemUI that work with tiles operate on `QSTile` or the interfaces defined in it. However, all the current implementations of tiles in SystemUI subclass from `QSTileImpl`, as it takes care of many common situations. Throughout this document, we will focus on `QSTileImpl` as examples of tiles.
+All the elements in SystemUI that work with tiles operate on `QSTile` or the interfaces defined in
+it. However, all the current implementations of tiles in SystemUI subclass from `QSTileImpl`, as it
+takes care of many common situations. Throughout this document, we will focus on `QSTileImpl` as
+examples of tiles.
-The interfaces in `QSTile` as well as other interfaces described in this document can be used to implement plugins to add additional tiles or different behavior. For more information, see [plugins.md](plugins.md)
+The interfaces in `QSTile` as well as other interfaces described in this document can be used to
+implement plugins to add additional tiles or different behavior. For more information,
+see [plugins.md](plugins.md)
#### Tile State
-Each tile has an associated `State` object that is used to communicate information to the corresponding view. The base class `State` has (among others) the following fields:
+Each tile has an associated `State` object that is used to communicate information to the
+corresponding view. The base class `State` has (among others) the following fields:
* **`state`**: one of `Tile#STATE_UNAVAILABLE`, `Tile#STATE_ACTIVE`, `Tile#STATE_INACTIVE`.
* **`icon`**; icon to display. It may depend on the current state.
* **`label`**: usually the name of the tile.
* **`secondaryLabel`**: text to display in a second line. Usually extra state information.
* **`contentDescription`**
-* **`expandedAccessibilityClassName`**: usually `Switch.class.getName()` for boolean Tiles. This will make screen readers read the current state of the tile as well as the new state when it's toggled. For this, the Tile has to use `BooleanState`.
-* **`handlesLongClick`**: whether the Tile will handle long click. If it won't, it should be set to `false` so it will not be announced for accessibility.
+* **`expandedAccessibilityClassName`**: usually `Switch.class.getName()` for boolean Tiles. This
+ will make screen readers read the current state of the tile as well as the new state when it's
+ toggled. For this, the Tile has to use `BooleanState`.
+* **`handlesLongClick`**: whether the Tile will handle long click. If it won't, it should be set
+ to `false` so it will not be announced for accessibility.
Setting any of these fields during `QSTileImpl#handleUpdateState` will update the UI after it.
-Additionally. `BooleanState` has a `value` boolean field that usually would be set to `state == Tile#STATE_ACTIVE`. This is used by accessibility services along with `expandedAccessibilityClassName`.
+Additionally. `BooleanState` has a `value` boolean field that usually would be set
+to `state == Tile#STATE_ACTIVE`. This is used by accessibility services along
+with `expandedAccessibilityClassName`.
#### SystemUI tiles
-Each tile defined in SystemUI extends `QSTileImpl`. This abstract class implements some common functions and leaves others to be implemented by each tile, in particular those that determine how to handle different events (refresh, click, etc.).
+Each tile defined in SystemUI extends `QSTileImpl`. This abstract class implements some common
+functions and leaves others to be implemented by each tile, in particular those that determine how
+to handle different events (refresh, click, etc.).
-For more information on how to implement a tile in SystemUI, see [Implementing a SystemUI tile](#implementing-a-systemui-tile).
+For more information on how to implement a tile in SystemUI,
+see [Implementing a SystemUI tile](#implementing-a-systemui-tile).
### Tile views
-Each Tile has a couple of associated views for displaying it in QS and QQS. These views are updated after the backend updates the `State` using `QSTileImpl#handleUpdateState`.
+Each Tile has a couple of associated views for displaying it in QS and QQS. These views are updated
+after the backend updates the `State` using `QSTileImpl#handleUpdateState`.
-* **[`QSTileView`](/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java)**: Abstract class that provides basic Tile functionality. These allows external [Factories](#qsfactory) to create Tiles.
-* **[`QSTileViewImpl`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.java)**: Implementation of `QSTileView`. It takes care of the following:
- * Holding the icon
- * Background color and shape
- * Ripple
- * Click listening
- * Labels
+* **[`QSTileView`](/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java)**:
+ Abstract class that provides basic Tile functionality. These allows
+ external [Factories](#qsfactory) to create Tiles.
+* **[`QSTileViewImpl`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.java)**:
+ Implementation of `QSTileView`. It takes care of the following:
+ * Holding the icon
+ * Background color and shape
+ * Ripple
+ * Click listening
+ * Labels
* **[`QSIconView`](/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java)**
* **[`QSIconViewImpl`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java)**
#### QSIconView and QSIconViewImpl
-`QSIconView` is an interface that define the basic actions that icons have to respond to. Its base implementation in SystemUI is `QSIconViewImpl` and it and its subclasses are used by all QS tiles.
+`QSIconView` is an interface that define the basic actions that icons have to respond to. Its base
+implementation in SystemUI is `QSIconViewImpl` and it and its subclasses are used by all QS tiles.
-This `ViewGroup` is a container for the icon used in each tile. It has methods to apply the current `State` of the tile, modifying the icon (color and animations). Classes that inherit from this can add other details that are modified when the `State` changes.
+This `ViewGroup` is a container for the icon used in each tile. It has methods to apply the
+current `State` of the tile, modifying the icon (color and animations). Classes that inherit from
+this can add other details that are modified when the `State` changes.
-Each `QSTileImpl` can specify that they use a particular implementation of this class when creating an icon.
+Each `QSTileImpl` can specify that they use a particular implementation of this class when creating
+an icon.
### How are the backend and the views related?
-The backend of the tiles (all the implementations of `QSTileImpl`) communicate with the views by using a `State`. The backend populates the state, and then the view maps the state to a visual representation.
+The backend of the tiles (all the implementations of `QSTileImpl`) communicate with the views by
+using a `State`. The backend populates the state, and then the view maps the state to a visual
+representation.
-It's important to notice that the state of the tile (internal or visual) is not directly modified by a user action like clicking on the tile. Instead, acting on a tile produces internal state changes on the device, and those trigger the changes on the tile state and UI.
+It's important to notice that the state of the tile (internal or visual) is not directly modified by
+a user action like clicking on the tile. Instead, acting on a tile produces internal state changes
+on the device, and those trigger the changes on the tile state and UI.
-When a container for tiles (`QuickQSPanel` or `QSPanel`) has to display tiles, they create a [`TileRecord`](/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java). This associates the corresponding `QSTile` with its `QSTileView`, doing the following:
+When a container for tiles (`QuickQSPanel` or `QSPanel`) has to display tiles, they create
+a [`TileRecord`](/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java). This associates the
+corresponding `QSTile` with its `QSTileView`, doing the following:
* Create the corresponding `QSTileView` to display in that container.
-* Create a callback for `QSTile` to call when its state changes. Note that a single tile will normally have up to two callbacks: one for QS and one for QQS.
+* Create a callback for `QSTile` to call when its state changes. Note that a single tile will
+ normally have up to two callbacks: one for QS and one for QQS.
#### Life of a tile click
-This is a brief run-down of what happens when a user clicks on a tile. Internal changes on the device (for example, changes from Settings) will trigger this process starting in step 3. Throughout this section, we assume that we are dealing with a `QSTileImpl`.
+This is a brief run-down of what happens when a user clicks on a tile. Internal changes on the
+device (for example, changes from Settings) will trigger this process starting in step 3. Throughout
+this section, we assume that we are dealing with a `QSTileImpl`.
1. User clicks on tile. The following calls happen in sequence:
- 1. `QSTileViewImpl#onClickListener`.
- 2. `QSTile#click`.
- 3. `QSTileImpl#handleClick`. This last call sets the new state for the device by using the associated controller.
+ 1. `QSTileViewImpl#onClickListener`.
+ 2. `QSTile#click`.
+ 3. `QSTileImpl#handleClick`. This last call sets the new state for the device by using the
+ associated controller.
2. State in the device changes. This is normally outside of SystemUI's control.
-3. Controller receives a callback (or `Intent`) indicating the change in the device. The following calls happen:
- 1. `QSTileImpl#refreshState`, maybe passing an object with necessary information regarding the new state.
- 2. `QSTileImpl#handleRefreshState`
-4. `QSTileImpl#handleUpdateState` is called to update the state with the new information. This information can be obtained both from the `Object` passed to `refreshState` as well as from the controller.
-5. If the state has changed (in at least one element), `QSTileImpl#handleStateChanged` is called. This will trigger a call to all the associated `QSTile.Callback#onStateChanged`, passing the new `State`.
-6. `QSTileView#onStateChanged` is called and this calls `QSTileView#handleStateChanged`. This method maps the state into the view:
- * The tile colors change to match the new state.
- * `QSIconView.setIcon` is called to apply the correct state to the icon and the correct icon to the view.
- * The tile labels change to match the new state.
+3. Controller receives a callback (or `Intent`) indicating the change in the device. The following
+ calls happen:
+ 1. `QSTileImpl#refreshState`, maybe passing an object with necessary information regarding the
+ new state.
+ 2. `QSTileImpl#handleRefreshState`
+4. `QSTileImpl#handleUpdateState` is called to update the state with the new information. This
+ information can be obtained both from the `Object` passed to `refreshState` as well as from the
+ controller.
+5. If the state has changed (in at least one element), `QSTileImpl#handleStateChanged` is called.
+ This will trigger a call to all the associated `QSTile.Callback#onStateChanged`, passing the
+ new `State`.
+6. `QSTileView#onStateChanged` is called and this calls `QSTileView#handleStateChanged`. This method
+ maps the state into the view:
+ * The tile colors change to match the new state.
+ * `QSIconView.setIcon` is called to apply the correct state to the icon and the correct icon to
+ the view.
+ * The tile labels change to match the new state.
## Third party tiles (TileService)
-A third party tile is any Quick Settings tile that is provided by an app (that's not SystemUI). This is implemented by developers subclassing [`TileService`](/core/java/android/service/quicksettings/TileService.java) and interacting with its API.
+A third party tile is any Quick Settings tile that is provided by an app (that's not SystemUI). This
+is implemented by developers
+subclassing [`TileService`](/core/java/android/service/quicksettings/TileService.java) and
+interacting with its API.
### API classes
-The classes that define the public API are in [core/java/android/service/quicksettings](/core/java/android/service/quicksettings).
+The classes that define the public API are
+in [core/java/android/service/quicksettings](/core/java/android/service/quicksettings).
#### Tile
-Parcelable class used to communicate information about the state between the external app and SystemUI. The class supports the following fields:
+Parcelable class used to communicate information about the state between the external app and
+SystemUI. The class supports the following fields:
* Label
* Subtitle
@@ -135,18 +204,25 @@
* State (`Tile#STATE_ACTIVE`, `Tile#STATE_INACTIVE`, `Tile#STATE_UNAVAILABLE`)
* Content description
-Additionally, it provides a method to notify SystemUI that the information may have changed and the tile should be refreshed.
+Additionally, it provides a method to notify SystemUI that the information may have changed and the
+tile should be refreshed.
#### TileService
-This is an abstract Service that needs to be implemented by the developer. The Service manifest must have the permission `android.permission.BIND_QUICK_SETTINGS_TILE` and must respond to the action `android.service.quicksettings.action.QS_TILE`. This will allow SystemUI to find the available tiles and display them to the user.
+This is an abstract Service that needs to be implemented by the developer. The Service manifest must
+have the permission `android.permission.BIND_QUICK_SETTINGS_TILE` and must respond to the
+action `android.service.quicksettings.action.QS_TILE`. This will allow SystemUI to find the
+available tiles and display them to the user.
-The implementer is responsible for creating the methods that will respond to the following calls from SystemUI:
+The implementer is responsible for creating the methods that will respond to the following calls
+from SystemUI:
* **`onTileAdded`**: called when the tile is added to QS.
* **`onTileRemoved`**: called when the tile is removed from QS.
-* **`onStartListening`**: called when QS is opened and the tile is showing. This marks the start of the window when calling `getQSTile` is safe and will provide the correct object.
-* **`onStopListening`**: called when QS is closed or the tile is no longer visible by the user. This marks the end of the window described in `onStartListening`.
+* **`onStartListening`**: called when QS is opened and the tile is showing. This marks the start of
+ the window when calling `getQSTile` is safe and will provide the correct object.
+* **`onStopListening`**: called when QS is closed or the tile is no longer visible by the user. This
+ marks the end of the window described in `onStartListening`.
* **`onClick`**: called when the user clicks on the tile.
Additionally, the following final methods are provided:
@@ -155,7 +231,8 @@
public final Tile getQsTile()
```
- Provides the tile object that can be modified. This should only be called in the window between `onStartListening` and `onStopListening`.
+ Provides the tile object that can be modified. This should only be called in the window
+ between `onStartListening` and `onStopListening`.
* ```java
public final boolean isLocked()
@@ -163,13 +240,15 @@
public final boolean isSecure()
```
- Provide information about the secure state of the device. This can be used by the tile to accept or reject actions on the tile.
+ Provide information about the secure state of the device. This can be used by the tile to accept
+ or reject actions on the tile.
* ```java
public final void unlockAndRun(Runnable)
```
- May prompt the user to unlock the device if locked. Once the device is unlocked, it runs the given `Runnable`.
+ May prompt the user to unlock the device if locked. Once the device is unlocked, it runs the
+ given `Runnable`.
* ```java
public final void showDialog(Dialog)
@@ -179,162 +258,272 @@
##### Binding
-When the Service is bound, a callback Binder is provided by SystemUI for all the callbacks, as well as an identifier token (`Binder`). This token is used in the callbacks to identify this `TileService` and match it to the corresponding tile.
+When the Service is bound, a callback Binder is provided by SystemUI for all the callbacks, as well
+as an identifier token (`Binder`). This token is used in the callbacks to identify
+this `TileService` and match it to the corresponding tile.
-The tiles are bound once immediately on creation. After that, the tile is bound whenever it should start listening. When the panels are closed, and the tile is set to stop listening, it will be unbound after a delay of `TileServiceManager#UNBIND_DELAY` (30s), if it's not set to listening again.
+The tiles are bound once immediately on creation. After that, the tile is bound whenever it should
+start listening. When the panels are closed, and the tile is set to stop listening, it will be
+unbound after a delay of `TileServiceManager#UNBIND_DELAY` (30s), if it's not set to listening
+again.
##### Active tile
-A `TileService` can be declared as an active tile by adding specific meta-data to its manifest (see [TileService#META_DATA_ACTIVE_TILE](https://developer.android.com/reference/android/service/quicksettings/TileService#META_DATA_ACTIVE_TILE)). In this case, it won't receive a call of `onStartListening` when QS is opened. Instead, the tile must request listening status by making a call to `TileService#requestListeningState` with its component name. This will initiate a window that will last until the tile is updated.
+A `TileService` can be declared as an active tile by adding specific meta-data to its manifest (
+see [TileService#META_DATA_ACTIVE_TILE](https://developer.android.com/reference/android/service/quicksettings/TileService#META_DATA_ACTIVE_TILE)).
+In this case, it won't receive a call of `onStartListening` when QS is opened. Instead, the tile
+must request listening status by making a call to `TileService#requestListeningState` with its
+component name. This will initiate a window that will last until the tile is updated.
The tile will also be granted listening status if it's clicked by the user.
### SystemUI classes
-The following sections describe the classes that live in SystemUI to support third party tiles. These classes live in [SystemUI/src/com/android/systemui/qs/external](/packages/SystemUI/src/com/android/systemui/qs/external/)
+The following sections describe the classes that live in SystemUI to support third party tiles.
+These classes live
+in [SystemUI/src/com/android/systemui/qs/external](/packages/SystemUI/src/com/android/systemui/qs/external/)
#### CustomTile
-This class is an subclass of `QSTileImpl` to be used with third party tiles. It provides similar behavior to SystemUI tiles as well as handling exclusive behavior like lifting default icons and labels from the application manifest.
+This class is an subclass of `QSTileImpl` to be used with third party tiles. It provides similar
+behavior to SystemUI tiles as well as handling exclusive behavior like lifting default icons and
+labels from the application manifest.
#### TileServices
-This class is the central controller for all tile services that are currently in Quick Settings as well as provides the support for starting new ones. It is also an implementation of the `Binder` that receives all calls from current `TileService` components and dispatches them to SystemUI or the corresponding `CustomTile`.
+This class is the central controller for all tile services that are currently in Quick Settings as
+well as provides the support for starting new ones. It is also an implementation of the `Binder`
+that receives all calls from current `TileService` components and dispatches them to SystemUI or the
+corresponding `CustomTile`.
-Whenever a binder call is made to this class, it matches the corresponding token assigned to the `TileService` with the `ComponentName` and verifies that the call comes from the right UID to prevent spoofing.
+Whenever a binder call is made to this class, it matches the corresponding token assigned to
+the `TileService` with the `ComponentName` and verifies that the call comes from the right UID to
+prevent spoofing.
-As this class is the only one that's aware of every `TileService` that's currently bound, it is also in charge of requesting some to be unbound whenever there is a low memory situation.
+As this class is the only one that's aware of every `TileService` that's currently bound, it is also
+in charge of requesting some to be unbound whenever there is a low memory situation.
#### TileLifecycleManager
-This class is in charge of binding and unbinding to a particular `TileService` when necessary, as well as sending the corresponding binder calls. It does not decide whether the tile should be bound or unbound, unless it's requested to process a message. It additionally handles errors in the `Binder` as well as changes in the corresponding component (like updates and enable/disable).
+This class is in charge of binding and unbinding to a particular `TileService` when necessary, as
+well as sending the corresponding binder calls. It does not decide whether the tile should be bound
+or unbound, unless it's requested to process a message. It additionally handles errors in
+the `Binder` as well as changes in the corresponding component (like updates and enable/disable).
-The class has a queue that stores requests while the service is not bound, to be processed as soon as the service is bound.
+The class has a queue that stores requests while the service is not bound, to be processed as soon
+as the service is bound.
-Each `TileService` gets assigned an exclusive `TileLifecycleManager` when its corresponding tile is added to the set of current ones and kept as long as the tile is available to the user.
+Each `TileService` gets assigned an exclusive `TileLifecycleManager` when its corresponding tile is
+added to the set of current ones and kept as long as the tile is available to the user.
#### TileServiceManager
-Each instance of this class is an intermediary between the `TileServices` controller and a `TileLifecycleManager` corresponding to a particular `TileService`.
+Each instance of this class is an intermediary between the `TileServices` controller and
+a `TileLifecycleManager` corresponding to a particular `TileService`.
This class handles management of the service, including:
* Deciding when to bind and unbind, requesting it to the `TileLifecycleManager`.
* Relaying messages to the `TileService` through the `TileLifecycleManager`.
* Determining the service's bind priority (to deal with OOM situations).
-* Detecting when the package/component has been removed in order to remove the tile and references to it.
+* Detecting when the package/component has been removed in order to remove the tile and references
+ to it.
## How are tiles created/instantiated?
-This section describes the classes that aid in the creation of each tile as well as the complete lifecycle of a tile. First we describe two important interfaces/classes.
+This section describes the classes that aid in the creation of each tile as well as the complete
+lifecycle of a tile. The current system makes use of flows to propagate information downstream.
-### QSTileHost
+First we describe three important interfaces/classes.
-This class keeps track of the tiles selected by the current user (backed in the Secure Setting `sysui_qs_tiles`) to be displayed in Quick Settings. Whenever the value of this setting changes (or on device start), the whole list of tiles is read. This is compared with the current tiles, destroying unnecessary ones and creating needed ones.
+### TileSpecRepository (and UserTileSpecRepository)
-It additionally provides a point of communication between the tiles and the StatusBar, for example to open it and collapse it. And a way for the StatusBar service to add tiles (only works for `CustomTile`).
+These classes keep track of the current tiles for each user, as a list of Tile specs. While the
+device is running, this is the source of truth of tiles for that user.
+
+The list is persisted to `Settings.Secure` every time it changes so it will be available upon
+restart or backup. In particular, any changes in the secure setting while this repository is
+tracking the list of tiles will be reverted.
+
+The class provides a `Flow<List<TileSpec>>` for each user that can be collected to keep track of the
+current list of tiles.
#### Tile specs
-Each single tile is identified by a spec, which is a unique String for that type of tile. The current tiles are stored as a Setting string of comma separated values of these specs. Additionally, the default tiles (that appear on a fresh system) configuration value is stored likewise.
+Each single tile is identified by a spec, which is a unique String for that type of tile. The
+current tiles are stored as a Setting string of comma separated values of these specs. Additionally,
+the default tiles (that appear on a fresh system) configuration value is stored likewise.
-SystemUI tile specs are usually a single simple word identifying the tile (like `wifi` or `battery`). Custom tile specs are always a string of the form `custom(...)` where the ellipsis is a flattened String representing the `ComponentName` for the corresponding `TileService`.
+SystemUI tile specs are usually a single simple word identifying the tile (like `wifi`
+or `battery`). Custom tile specs are always a string of the form `custom(...)` where the ellipsis is
+a flattened String representing the `ComponentName` for the corresponding `TileService`.
+
+We represent these internally using a `TileSpec` class that can distinguish between platform tiles
+and custom tiles.
+
+### CurrentTilesInteractor
+
+This class consumes the lists of specs provided by `TileSpecRepository` and produces a
+`Flow<List<Pair<TileSpec, QSTile>>>` with the current tiles for the current user.
+
+Internally, whenever the list of tiles changes, the following operation is performed:
+* Properly dispose of tiles that are no longer in the current list.
+* Properly dispose of tiles that are no longer available.
+* If the user has changed, relay the new user to the platform tiles and destroy any custom tiles.
+* Create new tiles as needed, disposing those that are not available or when the corresponding
+ service does not exist.
+* Reorder the tiles.
+
+Also, when this is completed, we pass the final list back to the repository so it matches the
+correct list of tiles.
### QSFactory
-This interface provides a way of creating tiles and views from a spec. It can be used in plugins to provide different definitions for tiles.
+This interface provides a way of creating tiles and views from a spec. It can be used in plugins to
+provide different definitions for tiles.
-In SystemUI there is only one implementation of this factory and that is the default factory (`QSFactoryImpl`) in `QSTileHost`.
+In SystemUI there is only one implementation of this factory and that is the default
+factory (`QSFactoryImpl`) in `CurrentTilesInteractorImpl`.
#### QSFactoryImpl
-This class implements two methods as specified in the `QSFactory` interface:
+This class implements the following method as specified in the `QSFactory` interface:
* ```java
public QSTile createTile(String)
```
- Creates a tile (backend) from a given spec. The factory has providers for all of the SystemUI tiles, returning one when the correct spec is used.
+ Creates a tile (backend) from a given spec. The factory has a map with providers for all of the
+ SystemUI tiles, returning one when the correct spec is used.
- If the spec is not recognized but it has the `custom(` prefix, the factory tries to create a `CustomTile` for the component in the spec. This could fail (the component is not a valid `TileService` or is not enabled) and will be detected later when the tile is polled to determine if it's available.
+ If the spec is not recognized but it has the `custom(` prefix, the factory tries to create
+ a `CustomTile` for the component in the spec.
-* ```java
- public QSTileView createTileView(QSTile, boolean)
- ```
-
- Creates a view for the corresponding `QSTile`. The second parameter determines if the view that is created should be a collapsed one (for using in QQS) or not (for using in QS).
+ As part of filtering not valid tiles, custom tiles that don't have a corresponding valid service
+ component are never instantiated.
### Lifecycle of a Tile
-We describe first the parts of the lifecycle that are common to SystemUI tiles and third party tiles. Following that, there will be a section with the steps that are exclusive to third party tiles.
+We describe first the parts of the lifecycle that are common to SystemUI tiles and third party
+tiles. Following that, there will be a section with the steps that are exclusive to third party
+tiles.
-1. The tile is added through the QS customizer by the user. This will immediately save the new list of tile specs to the Secure Setting `sysui_qs_tiles`. This step could also happend if `StatusBar` adds tiles (either through adb, or through its service interface as with the `DevelopmentTiles`).
-2. This triggers a "setting changed" that is caught by `QSTileHost`. This class processes the new value of the setting and finds out that there is a new spec in the list. Alternatively, when the device is booted, all tiles in the setting are considered as "new".
-3. `QSTileHost` calls all the available `QSFactory` classes that it has registered in order to find the first one that will be able to create a tile with that spec. Assume that `QSFactoryImpl` managed to create the tile, which is some implementation of `QSTile` (either a SystemUI subclass of `QSTileImpl` or a `CustomTile`). If the tile is available, it's stored in a map and things proceed forward.
-4. `QSTileHost` calls its callbacks indicating that the tiles have changed. In particular, `QSPanel` and `QuickQSPanel` receive this call with the full list of tiles. We will focus on these two classes.
-5. For each tile in this list, a `QSTileView` is created (collapsed or expanded) and attached to a `TileRecord` containing the tile backend and the view. Additionally:
- * a callback is attached to the tile to communicate between the backend and the view or the panel.
+1. The tile is added through the QS customizer by the user. This will send the new list of tiles to
+ `TileSpecRepository` which will update its internal state and also store the new value in the
+ secure setting `sysui_qs_tiles`. This step could also happen if `StatusBar` adds tiles (either
+ through adb, or through its service interface as with the `DevelopmentTiles`).
+2. This updates the flow that `CurrentTilesInteractor` is collecting from, triggering the process
+ described above.
+3. `CurrentTilesInteractor` calls the available `QSFactory` classes in order to find one that will
+ be able to create a tile with that spec. Assuming that `QSFactoryImpl` managed to create the
+ tile, which is some implementation of `QSTile` (either a SystemUI subclass
+ of `QSTileImpl` or a `CustomTile`) it will be added to the current list.
+ If the tile is available, it's stored in a map and things proceed forward.
+4. `CurrentTilesInteractor` updates its flow and classes collecting from it will be notified of the
+ change. In particular, `QSPanel` and `QuickQSPanel` receive this call with the full list of
+ tiles. We will focus on these two classes.
+5. For each tile in this list, a `QSTileView` is created (collapsed or expanded) and attached to
+ a `TileRecord` containing the tile backend and the view. Additionally:
+ * a callback is attached to the tile to communicate between the backend and the view or the
+ panel.
* the click listeners in the tile are attached to those of the view.
6. The tile view is added to the corresponding layout.
-When the tile is removed from the list of current tiles, all these classes are properly disposed including removing the callbacks and making sure that the backends remove themselves from the controllers they were listening to.
+When the tile is removed from the list of current tiles, all these classes are properly disposed
+including removing the callbacks and making sure that the backends remove themselves from the
+controllers they were listening to.
#### Lifecycle of a CustomTile
-In step 3 of the previous process, when a `CustomTile` is created, additional steps are taken to ensure the proper binding to the service as described in [Third party tiles (TileService)](#third-party-tiles-tileservice).
+In step 3 of the previous process, when a `CustomTile` is created, additional steps are taken to
+ensure the proper binding to the service as described
+in [Third party tiles (TileService)](#third-party-tiles-tileservice).
-1. The `CustomTile` obtains the `TileServices` class from the `QSTileHost` and request the creation of a `TileServiceManager` with its token. As the spec for the `CustomTile` contains the `ComponentName` of the associated service, this can be used to bind to it.
-2. The `TileServiceManager` creates its own `TileLifecycleManager` to take care of binding to the service.
-3. `TileServices` creates maps between the token, the `CustomTile`, the `TileServiceManager`, the token and the `ComponentName`.
+1. The `CustomTile` obtains the `TileServices` class from the `QSTileHost` and request the creation
+ of a `TileServiceManager` with its token. As the spec for the `CustomTile` contains
+ the `ComponentName` of the associated service, this can be used to bind to it.
+2. The `TileServiceManager` creates its own `TileLifecycleManager` to take care of binding to the
+ service.
+3. `TileServices` creates maps between the token, the `CustomTile`, the `TileServiceManager`, the
+ token and the `ComponentName`.
## Implementing a tile
-This section describes necessary and recommended steps when implementing a Quick Settings tile. Some of them are optional and depend on the requirements of the tile.
+This section describes necessary and recommended steps when implementing a Quick Settings tile. Some
+of them are optional and depend on the requirements of the tile.
### Implementing a SystemUI tile
-1. Create a class (preferably in [`SystemUI/src/com/android/systemui/qs/tiles`](/packages/SystemUI/src/com/android/systemui/qs/tiles)) implementing `QSTileImpl` with a particular type of `State` as a parameter.
-2. Create an injectable constructor taking a `QSHost` and whichever classes are needed for the tile's operation. Normally this would be other SystemUI controllers.
-3. Implement the methods described in [Abstract methods in QSTileImpl](#abstract-methods-in-qstileimpl). Look at other tiles for help. Some considerations to have in mind:
- * If the tile will not support long click (like the `FlashlightTile`), set `state.handlesLongClick` to `false` (maybe in `newTileState`).
+1. Create a class (preferably
+ in [`SystemUI/src/com/android/systemui/qs/tiles`](/packages/SystemUI/src/com/android/systemui/qs/tiles))
+ implementing `QSTileImpl` with a particular type of `State` as a parameter.
+2. Create an injectable constructor taking a `QSHost` and whichever classes are needed for the
+ tile's operation. Normally this would be other SystemUI controllers.
+3. Implement the methods described
+ in [Abstract methods in QSTileImpl](#abstract-methods-in-qstileimpl). Look at other tiles for
+ help. Some considerations to have in mind:
+ * If the tile will not support long click (like the `FlashlightTile`),
+ set `state.handlesLongClick` to `false` (maybe in `newTileState`).
* Changes to the tile state (either from controllers or from clicks) should call `refreshState`.
- * Use only `handleUpdateState` to modify the values of the state to the new ones. This can be done by polling controllers or through the `arg` parameter.
- * If the controller is not a `CallbackController`, respond to `handleSetListening` by attaching/dettaching from controllers.
+ * Use only `handleUpdateState` to modify the values of the state to the new ones. This can be
+ done by polling controllers or through the `arg` parameter.
+ * If the controller is not a `CallbackController`, respond to `handleSetListening` by
+ attaching/dettaching from controllers.
* Implement `isAvailable` so the tile will not be created when it's not necessary.
-4. Either create a new feature module or find an existing related feature module and add the following binding method:
+4. Either create a new feature module or find an existing related feature module and add the
+ following binding method:
* ```kotlin
@Binds
@IntoMap
@StringKey(YourNewTile.TILE_SPEC) // A unique word that will map to YourNewTile
fun bindYourNewTile(yourNewTile: YourNewTile): QSTileImpl<*>
```
-5. In [SystemUI/res/values/config.xml](/packages/SystemUI/res/values/config.xml), modify `quick_settings_tiles_stock` and add the spec defined in the previous step. If necessary, add it also to `quick_settings_tiles_default`. The first one contains a list of all the tiles that SystemUI knows how to create (to show to the user in the customization screen). The second one contains only the default tiles that the user will experience on a fresh boot or after they reset their tiles.
-6. In [SystemUI/res/values/tiles_states_strings.xml](/packages/SystemUI/res/values/tiles_states_strings.xml), add a new array for your tile. The name has to be `tile_states_<spec>`. Use a good description to help the translators.
-7. In [`SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt), add a new element to the map in `SubtitleArrayMapping` corresponding to the resource created in the previous step.
+5. In [SystemUI/res/values/config.xml](/packages/SystemUI/res/values/config.xml),
+ modify `quick_settings_tiles_stock` and add the spec defined in the previous step. If necessary,
+ add it also to `quick_settings_tiles_default`. The first one contains a list of all the tiles
+ that SystemUI knows how to create (to show to the user in the customization screen). The second
+ one contains only the default tiles that the user will experience on a fresh boot or after they
+ reset their tiles.
+6. In [SystemUI/res/values/tiles_states_strings.xml](/packages/SystemUI/res/values/tiles_states_strings.xml),
+add a new array for your tile. The name has to be `tile_states_<spec>`. Use a good description to
+help the translators.
+7. In [`SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt),
+add a new element to the map in `SubtitleArrayMapping` corresponding to the resource created in the
+previous step.
#### Abstract methods in QSTileImpl
-Following are methods that need to be implemented when creating a new SystemUI tile. `TState` is a type variable of type `State`.
+Following are methods that need to be implemented when creating a new SystemUI tile. `TState` is a
+type variable of type `State`.
* ```java
public TState newTileState()
```
- Creates a new `State` for this tile to use. Each time the state changes, it is copied into a new one and the corresponding fields are modified. The framework provides `State`, `BooleanState` (has an on and off state and provides this as a content description), `SignalState` (`BooleanState` with `activityIn` and `activityOut`), and `SlashState` (can be rotated or slashed through).
+ Creates a new `State` for this tile to use. Each time the state changes, it is copied into a new
+ one and the corresponding fields are modified. The framework provides `State`, `BooleanState` (has
+ an on and off state and provides this as a content description), `SignalState` (`BooleanState`
+ with `activityIn` and `activityOut`), and `SlashState` (can be rotated or slashed through).
- If a tile has special behavior (no long click, no ripple), it can be set in its state here.
+ If a tile has special behavior (no long click, no ripple), it can be set in its state here.
* ```java
public void handleSetListening(boolean)
```
- Initiates or terminates listening behavior, like listening to Callbacks from controllers. This gets triggered when QS is expanded or collapsed (i.e., when the tile is visible and actionable). Most tiles (like `WifiTile`) do not implement this. Instead, Tiles are LifecycleOwner and are marked as `RESUMED` or `DESTROYED` in `QSTileImpl#handleListening` and handled as part of the lifecycle of [CallbackController](/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java)
+ Initiates or terminates listening behavior, like listening to Callbacks from controllers. This
+ gets triggered when QS is expanded or collapsed (i.e., when the tile is visible and actionable).
+ Most tiles (like `WifiTile`) do not implement this. Instead, Tiles are LifecycleOwner and are
+ marked as `RESUMED` or `DESTROYED` in `QSTileImpl#handleListening` and handled as part of the
+ lifecycle
+ of [CallbackController](/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java)
* ```java
public QSIconView createTileView(Context)
```
- Allows a Tile to use a `QSIconView` different from `QSIconViewImpl` (see [Tile views](#tile-views)), which is the default defined in `QSTileImpl`
+ Allows a Tile to use a `QSIconView` different from `QSIconViewImpl` (
+ see [Tile views](#tile-views)), which is the default defined in `QSTileImpl`
* ```java
public Intent getLongClickIntent()
@@ -350,36 +539,137 @@
protected void handleLongClick()
```
- Handles what to do when the Tile is clicked. In general, a Tile will make calls to its controller here and maybe update its state immediately (by calling `QSTileImpl#refreshState`). A Tile can also decide to ignore the click here, if it's `Tile#STATE_UNAVAILABLE`.
+ Handles what to do when the Tile is clicked. In general, a Tile will make calls to its controller
+ here and maybe update its state immediately (by calling `QSTileImpl#refreshState`). A Tile can
+ also decide to ignore the click here, if it's `Tile#STATE_UNAVAILABLE`.
- By default long click redirects to click and long click launches the intent defined in `getLongClickIntent`.
+ By default long click redirects to click and long click launches the intent defined
+ in `getLongClickIntent`.
* ```java
protected void handleUpdateState(TState, Object)
```
- Updates the `State` of the Tile based on the state of the device as provided by the respective controller. It will be called every time the Tile becomes visible, is interacted with or `QSTileImpl#refreshState` is called. After this is done, the updated state will be reflected in the UI.
+ Updates the `State` of the Tile based on the state of the device as provided by the respective
+ controller. It will be called every time the Tile becomes visible, is interacted with
+ or `QSTileImpl#refreshState` is called. After this is done, the updated state will be reflected in
+ the UI.
* ```java
@Deprecated
public int getMetricsCategory()
```
- ~~Identifier for this Tile, as defined in [proto/src/metrics_constants/metrics_constants.proto](/proto/src/metrics_constants/metrics_constants.proto). This is used to log events related to this Tile.~~
+ ~~Identifier for this Tile, as defined
+ in [proto/src/metrics_constants/metrics_constants.proto](/proto/src/metrics_constants/metrics_constants.proto).
+ This is used to log events related to this Tile.~~
This is now deprecated in favor of `UiEvent` that use the tile spec.
* ```java
public boolean isAvailable()
```
- Determines if a Tile is available to be used (for example, disable `WifiTile` in devices with no Wifi support). If this is false, the Tile will be destroyed upon creation.
+ Determines if a Tile is available to be used (for example, disable `WifiTile` in devices with no
+ Wifi support). If this is false, the Tile will be destroyed upon creation.
* ```java
public CharSequence getTileLabel()
```
- Provides a default label for this Tile. Used by the QS Panel customizer to show a name next to each available tile.
+ Provides a default label for this Tile. Used by the QS Panel customizer to show a name next to
+ each available tile.
### Implementing a third party tile
-For information about this, use the Android Developer documentation for [TileService](https://developer.android.com/reference/android/service/quicksettings/TileService).
\ No newline at end of file
+For information about this, use the Android Developer documentation
+for [TileService](https://developer.android.com/reference/android/service/quicksettings/TileService).
+
+## AutoAddable tiles
+
+AutoAddable tiles are tiles that are not part of the default set, but will be automatically added
+for the user, when the user enabled a feature for the first time. For example:
+* When the user creates a work profile, the work profile tile is automatically added.
+* When the user sets up a hotspot for the first time, the hotspot tile is automatically added.
+
+In order to declare a tile as auto-addable, there are two ways:
+
+* If the tile can be tied to a secure setting such that the tile should be auto added after that
+ setting has changed to a non-zero value for the first time, a new line can be added to the
+ string-array `config_quickSettingsAutoAdd` in [config.xml](/packages/SystemUI/res/values/config.xml).
+* If more specific behavior is needed, a new
+ [AutoAddable](/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/model/AutoAddable.kt)
+ can be added in the `autoaddables` package. This can have custom logic that produces a flow of
+ signals on when the tile should be auto-added (or auto-removed in special cases).
+
+ *Special case: If the data comes from a `CallbackController`, a special
+ `CallbackControllerAutoAddable` can be created instead that handles a lot of the common code.*
+
+### AutoAddRepository (and UserAutoAddRepository)
+
+These classes keep track of tiles that have been auto-added for each user, as a list of Tile specs.
+While the device is running, this is the source of truth of already auto-added tiles for that user.
+
+The list is persisted to `Settings.Secure` every time it changes so it will be available upon
+restart or backup. In particular, any changes in the secure setting while this repository is
+tracking the list of tiles will be reverted.
+
+The class provides a `Flow<Set<TileSpec>>` for each user that can be collected to keep track of the
+set of already auto added tiles.
+
+### AutoAddInteractor
+
+This class collects all registered (through Dagger) `AutoAddables` and merges all the signals for
+the current user. It will add/remove tiles as necessary and mark them as such in the
+`AutoAddRepository`.
+
+## Backup and restore
+
+It's important to point out that B&R of Quick Settings tiles only concerns itself with restoring,
+for each user, the list of current tiles and their order. The state of the tiles (or other things
+that can be accessed from them like list of WiFi networks) is the concern of each feature team and
+out of the scope of Quick Settings.
+
+In order to provide better support to restoring Quick Settings tiles and prevent overwritten or
+inconsistent data, the system has the following steps:
+
+1. When `Settings.Secure.SYSUI_QS_TILES` and `Settings.Secure.QS_AUTO_TILES` are restored, a
+ broadcast is sent to SystemUI. This is handled by
+ [SettingsHelper](/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java).
+ The broadcasts are received by [QSSettingsRestoredRepository](/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt)
+ and grouped by user into a data object. As described above, the change performed by the restore in
+ settings is overriden by the corresponding repositories.
+2. Once both settings have been restored, the data is reconciled with the current data, to account
+ for tiles that may have been auto-added between the start of SystemUI and the time the restore
+ happened. The guiding principles for the reconciliation are as follows:
+ * We assume that the user expects the restored tiles to be the ones to be present after restore,
+ so those are taken as the basis for the reconciliation.
+ * Any tile that was auto-added before the restore, but had not been auto-added in the source
+ device, is auto-added again (preferably in a similar position).
+ * Any tile that was auto-added before the restore, and it was also auto-added in the source
+ device, but not present in the restored tiles, is considered removed by the user and therefore
+ not restored.
+ * Every tile that was marked as auto-added (all tiles in source + tiles added before restore)
+ are set as auto-added.
+
+## Logs for debugging
+
+The following log buffers are used for Quick Settings debugging purposes:
+
+### QSLog
+
+Logs events in the individual tiles, like listening state, clicks, and status updates.
+
+### QSTileListLog
+
+Logs changes in the current set of tiles for each user, including when tiles are created or
+destroyed, and the reason for that. It also logs what operation caused the tiles to change
+(add, remove, change, restore).
+
+### QSAutoAddLog
+
+Logs operations of auto-add (or auto-remove) of tiles.
+
+### QSRestoreLog
+
+Logs the data obtained after a successful restore of the settings. This is the data that will be
+used for reconciliation.
\ No newline at end of file
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 80d45bc..78b854e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -22,8 +22,11 @@
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
+import com.android.internal.widget.LockscreenCredential
+import com.android.keyguard.KeyguardPinViewController.PinBouncerUiEvent
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
@@ -91,6 +94,7 @@
@Mock lateinit var passwordTextView: PasswordTextView
@Mock lateinit var deleteButton: NumPadButton
@Mock lateinit var enterButton: View
+ @Mock lateinit var uiEventLogger: UiEventLogger
@Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
@@ -137,6 +141,7 @@
postureController,
featureFlags,
mSelectedUserInteractor,
+ uiEventLogger
)
}
@@ -251,4 +256,21 @@
verify(lockPatternUtils).getCurrentFailedPasswordAttempts(anyInt())
}
+
+ @Test
+ fun onUserInput_autoConfirmation_attemptsUnlock() {
+ val pinViewController = constructPinViewController(mockKeyguardPinView)
+ whenever(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
+ whenever(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
+ whenever(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
+ whenever(passwordTextView.text).thenReturn("000000")
+ whenever(enterButton.visibility).thenReturn(View.INVISIBLE)
+ whenever(mockKeyguardPinView.enteredCredential)
+ .thenReturn(LockscreenCredential.createPin("000000"))
+
+ pinViewController.onUserInput()
+
+ verify(uiEventLogger).log(PinBouncerUiEvent.ATTEMPT_UNLOCK_WITH_AUTO_CONFIRM_FEATURE)
+ verify(keyguardUpdateMonitor).setCredentialAttempted()
+ }
}
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 602f3dc..da97a12 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -1041,8 +1041,9 @@
mExecution, mCommandQueue, mActivityTaskManager, mWindowManager,
mFingerprintManager, mFaceManager, () -> mUdfpsController,
() -> mSideFpsController, mDisplayManager, mWakefulnessLifecycle,
- mPanelInteractionDetector, mUserManager, mLockPatternUtils, mUdfpsLogger,
- mLogContextInteractor, () -> mBiometricPromptCredentialInteractor,
+ mPanelInteractionDetector, mUserManager, mLockPatternUtils, () -> mUdfpsLogger,
+ () -> mLogContextInteractor,
+ () -> mBiometricPromptCredentialInteractor,
() -> mPromptSelectionInteractor, () -> mCredentialViewModel,
() -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor,
mUdfpsUtils, mVibratorHelper);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
index 79f0625..cbb772f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
@@ -396,7 +396,7 @@
.onDozeAmountChanged(
eq(.3f),
eq(.3f),
- eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF)
+ eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF)
)
transitionRepository.sendTransitionStep(
@@ -413,9 +413,130 @@
.onDozeAmountChanged(
eq(1f),
eq(1f),
- eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF)
+ eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF)
)
job.cancel()
}
+
+ @Test
+ fun aodToOccluded_dozeAmountChanged() =
+ testScope.runTest {
+ // GIVEN view is attached
+ mController.onViewAttached()
+ Mockito.reset(mView)
+
+ val job = mController.listenForAodToOccludedTransitions(this)
+
+ // WHEN transitioning from aod to occluded
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.OCCLUDED,
+ value = .3f,
+ transitionState = TransitionState.RUNNING
+ )
+ )
+ runCurrent()
+ // THEN doze amount is updated
+ verify(mView)
+ .onDozeAmountChanged(eq(.7f), eq(.7f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE))
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.OCCLUDED,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ )
+ )
+ runCurrent()
+ // THEN doze amount is updated
+ verify(mView)
+ .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE))
+
+ job.cancel()
+ }
+
+ @Test
+ fun occludedToAod_dozeAmountChanged() =
+ testScope.runTest {
+ // GIVEN view is attached
+ mController.onViewAttached()
+ Mockito.reset(mView)
+
+ val job = mController.listenForOccludedToAodTransition(this)
+
+ // WHEN transitioning from occluded to aod
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.AOD,
+ value = .3f,
+ transitionState = TransitionState.RUNNING
+ )
+ )
+ runCurrent()
+ // THEN doze amount is updated
+ verify(mView)
+ .onDozeAmountChanged(
+ eq(.3f),
+ eq(.3f),
+ eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF)
+ )
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.AOD,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ )
+ )
+ runCurrent()
+ // THEN doze amount is updated
+ verify(mView)
+ .onDozeAmountChanged(
+ eq(1f),
+ eq(1f),
+ eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF)
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun cancelledAodToLockscreen_dozeAmountChangedToZero() =
+ testScope.runTest {
+ // GIVEN view is attached
+ mController.onViewAttached()
+ Mockito.reset(mView)
+
+ val job = mController.listenForLockscreenAodTransitions(this)
+ // WHEN aod to lockscreen transition is cancelled
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ value = 1f,
+ transitionState = TransitionState.CANCELED
+ )
+ )
+ runCurrent()
+ // ... and WHEN the next transition is from lockscreen => occluded
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ value = .4f,
+ transitionState = TransitionState.STARTED
+ )
+ )
+ runCurrent()
+
+ // THEN doze amount is updated to zero
+ verify(mView)
+ .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE))
+ job.cancel()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
index ce7db80..ea3006f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.view.viewmodel
import android.app.smartspace.SmartspaceTarget
+import android.os.PowerManager
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,6 +34,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -50,6 +52,8 @@
@RunWith(AndroidJUnit4::class)
class CommunalEditModeViewModelTest : SysuiTestCase() {
@Mock private lateinit var mediaHost: MediaHost
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var powerManager: PowerManager
private lateinit var testScope: TestScope
@@ -79,6 +83,8 @@
underTest =
CommunalEditModeViewModel(
withDeps.communalInteractor,
+ shadeViewController,
+ powerManager,
mediaHost,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 32f4d07..9bd0835 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.view.viewmodel
import android.app.smartspace.SmartspaceTarget
+import android.os.PowerManager
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,6 +34,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -50,6 +52,8 @@
@RunWith(AndroidJUnit4::class)
class CommunalViewModelTest : SysuiTestCase() {
@Mock private lateinit var mediaHost: MediaHost
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var powerManager: PowerManager
private lateinit var testScope: TestScope
@@ -80,6 +84,8 @@
CommunalViewModel(
withDeps.communalInteractor,
withDeps.tutorialInteractor,
+ shadeViewController,
+ powerManager,
mediaHost,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 706f94e..11939c1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -53,7 +54,6 @@
private val sceneInteractor = testUtils.sceneInteractor()
private val commandQueue = FakeCommandQueue()
private val bouncerRepository = FakeKeyguardBouncerRepository()
- private val configurationRepository = FakeConfigurationRepository()
private val shadeRepository = FakeShadeRepository()
private val transitionState: MutableStateFlow<ObservableTransitionState> =
MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Gone))
@@ -65,7 +65,7 @@
powerInteractor = PowerInteractorFactory.create().powerInteractor,
sceneContainerFlags = testUtils.sceneContainerFlags,
bouncerRepository = bouncerRepository,
- configurationRepository = configurationRepository,
+ configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
shadeRepository = shadeRepository,
sceneInteractorProvider = { sceneInteractor },
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index fd125e0..53bca48 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -19,14 +19,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+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.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
@@ -38,16 +35,12 @@
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
import com.google.common.collect.Range
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.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,223 +48,201 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: DreamingToLockscreenTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest =
- DreamingToLockscreenTransitionViewModel(
- interactor,
- mock(),
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = FakeBiometricSettingsRepository(),
- ),
- )
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ private val underTest = kosmos.dreamingToLockscreenTransitionViewModel
@Test
fun dreamOverlayTranslationY() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
-
+ testScope.runTest {
val pixels = 100
- val job =
- underTest.dreamOverlayTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
+ val values by collectValues(underTest.dreamOverlayTranslationY(pixels))
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ step(0.6f),
+ step(0.8f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(7)
values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
-
- job.cancel()
}
@Test
fun dreamOverlayFadeOut() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ val values by collectValues(underTest.dreamOverlayAlpha)
- val job = underTest.dreamOverlayAlpha.onEach { values.add(it) }.launchIn(this)
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ // Should start running here...
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.5f),
+ // ...up to here
+ step(1f),
+ ),
+ testScope,
+ )
- // Should start running here...
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.5f))
- // ...up to here
- repository.sendTransitionStep(step(1f))
-
- // Only two values should be present, since the dream overlay runs for a small fraction
- // of the overall animation time
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun lockscreenFadeIn() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ val values by collectValues(underTest.lockscreenAlpha)
- val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.2f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun deviceEntryParentViewFadeIn() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ val values by collectValues(underTest.deviceEntryParentViewAlpha)
- val job = underTest.deviceEntryParentViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.2f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun deviceEntryBackgroundViewAppear() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
fingerprintPropertyRepository.setProperties(
sensorId = 0,
strength = SensorStrength.STRONG,
sensorType = FingerprintSensorType.UDFPS_OPTICAL,
sensorLocations = emptyMap(),
)
- val values = mutableListOf<Float>()
+ val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
- val job =
- underTest.deviceEntryBackgroundViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.2f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(1f))
+ 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(1f) }
-
- job.cancel()
}
@Test
fun deviceEntryBackground_noUdfps_noUpdates() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
fingerprintPropertyRepository.setProperties(
sensorId = 0,
strength = SensorStrength.STRONG,
sensorType = FingerprintSensorType.REAR,
sensorLocations = emptyMap(),
)
- val values = mutableListOf<Float>()
+ val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
- val job =
- underTest.deviceEntryBackgroundViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.2f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(0) // no updates
-
- job.cancel()
}
@Test
fun lockscreenTranslationY() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
-
+ testScope.runTest {
val pixels = 100
- val job =
- underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
+ val values by collectValues(underTest.lockscreenTranslationY(pixels))
- repository.sendTransitionStep(step(0f, STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
-
- job.cancel()
}
@Test
fun transitionEnded() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<TransitionStep>()
+ testScope.runTest {
+ val values by collectValues(underTest.transitionEnded)
- val job = underTest.transitionEnded.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(TransitionStep(DOZING, DREAMING, 0.0f, STARTED))
- repository.sendTransitionStep(TransitionStep(DOZING, DREAMING, 1.0f, FINISHED))
-
- repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 0.0f, STARTED))
- repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 0.1f, RUNNING))
- repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 1.0f, FINISHED))
-
- repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 0.0f, STARTED))
- repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 0.5f, RUNNING))
- repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 1.0f, FINISHED))
-
- repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 0.0f, STARTED))
- repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 0.5f, RUNNING))
- repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 1.0f, CANCELED))
-
- repository.sendTransitionStep(TransitionStep(DREAMING, AOD, 0.0f, STARTED))
- repository.sendTransitionStep(TransitionStep(DREAMING, AOD, 1.0f, FINISHED))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(DOZING, DREAMING, 0.0f, STARTED),
+ TransitionStep(DOZING, DREAMING, 1.0f, FINISHED),
+ TransitionStep(DREAMING, LOCKSCREEN, 0.0f, STARTED),
+ TransitionStep(DREAMING, LOCKSCREEN, 0.1f, RUNNING),
+ TransitionStep(DREAMING, LOCKSCREEN, 1.0f, FINISHED),
+ TransitionStep(LOCKSCREEN, DREAMING, 0.0f, STARTED),
+ TransitionStep(LOCKSCREEN, DREAMING, 0.5f, RUNNING),
+ TransitionStep(LOCKSCREEN, DREAMING, 1.0f, FINISHED),
+ TransitionStep(DREAMING, GONE, 0.0f, STARTED),
+ TransitionStep(DREAMING, GONE, 0.5f, RUNNING),
+ TransitionStep(DREAMING, GONE, 1.0f, CANCELED),
+ TransitionStep(DREAMING, AOD, 0.0f, STARTED),
+ TransitionStep(DREAMING, AOD, 1.0f, FINISHED),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(3)
values.forEach {
assertThat(it.transitionState == FINISHED || it.transitionState == CANCELED)
.isTrue()
}
-
- job.cancel()
}
private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
index cf20129..3c07034 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -19,85 +19,73 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.coroutines.collectValues
+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.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
class GoneToDreamingTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: GoneToDreamingTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest = GoneToDreamingTransitionViewModel(interactor)
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest = kosmos.goneToDreamingTransitionViewModel
@Test
- fun lockscreenFadeOut() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ fun runTest() =
+ testScope.runTest {
+ val values by collectValues(underTest.lockscreenAlpha)
- val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
-
- // Should start running here...
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.2f))
- repository.sendTransitionStep(step(0.3f))
- // ...up to here
- repository.sendTransitionStep(step(1f))
+ repository.sendTransitionSteps(
+ listOf(
+ // Should start running here...
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ // ...up to here
+ step(1f),
+ ),
+ testScope,
+ )
// Only three values should be present, since the dream overlay runs for a small
// fraction of the overall animation time
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun lockscreenTranslationY() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
-
+ testScope.runTest {
val pixels = 100
- val job =
- underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
+ val values by collectValues(underTest.lockscreenTranslationY(pixels))
- // Should start running here...
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- // And a final reset event on CANCEL
- repository.sendTransitionStep(step(0.8f, TransitionState.CANCELED))
+ repository.sendTransitionSteps(
+ listOf(
+ // Should start running here...
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ // And a final reset event on CANCEL
+ step(0.8f, TransitionState.CANCELED)
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
-
- job.cancel()
}
private fun step(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index ba72b4c..9226c0d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -27,7 +27,6 @@
import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
@@ -55,11 +54,7 @@
private val repository = kosmos.fakeKeyguardTransitionRepository
private val shadeRepository = kosmos.shadeRepository
private val keyguardRepository = kosmos.fakeKeyguardRepository
- private val underTest =
- LockscreenToDreamingTransitionViewModel(
- interactor = kosmos.keyguardTransitionInteractor,
- shadeDependentFlows = kosmos.shadeDependentFlows,
- )
+ private val underTest = kosmos.lockscreenToDreamingTransitionViewModel
@Test
fun lockscreenFadeOut() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 3536d5c..bcad72b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -21,18 +21,19 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
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.coroutines.collectValues
import com.android.systemui.flags.Flags
import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
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.res.R
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.testKosmos
import com.google.common.collect.Range
@@ -46,7 +47,6 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() {
-
private val kosmos =
testKosmos().apply {
featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
@@ -55,11 +55,8 @@
private val repository = kosmos.fakeKeyguardTransitionRepository
private val shadeRepository = kosmos.shadeRepository
private val keyguardRepository = kosmos.fakeKeyguardRepository
- private val underTest =
- LockscreenToOccludedTransitionViewModel(
- interactor = kosmos.keyguardTransitionInteractor,
- shadeDependentFlows = kosmos.shadeDependentFlows,
- )
+ private val configurationRepository = kosmos.fakeConfigurationRepository
+ private val underTest = kosmos.lockscreenToOccludedTransitionViewModel
@Test
fun lockscreenFadeOut() =
@@ -86,8 +83,11 @@
@Test
fun lockscreenTranslationY() =
testScope.runTest {
- val pixels = 100
- val values by collectValues(underTest.lockscreenTranslationY(pixels))
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y,
+ 100
+ )
+ val values by collectValues(underTest.lockscreenTranslationY)
repository.sendTransitionSteps(
steps =
listOf(
@@ -106,8 +106,11 @@
@Test
fun lockscreenTranslationYIsCanceled() =
testScope.runTest {
- val pixels = 100
- val values by collectValues(underTest.lockscreenTranslationY(pixels))
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y,
+ 100
+ )
+ val values by collectValues(underTest.lockscreenTranslationY)
repository.sendTransitionSteps(
steps =
listOf(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index d077227..d419d4a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -19,24 +19,21 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+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.res.R
+import com.android.systemui.testKosmos
import com.google.common.collect.Range
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.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,163 +41,139 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: OccludedToLockscreenTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- biometricSettingsRepository = FakeBiometricSettingsRepository()
- underTest =
- OccludedToLockscreenTransitionViewModel(
- interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor,
- deviceEntryUdfpsInteractor =
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = biometricSettingsRepository,
- ),
- )
- }
+ val biometricSettingsRepository = kosmos.biometricSettingsRepository
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val underTest = kosmos.occludedToLockscreenTransitionViewModel
@Test
fun lockscreenFadeIn() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ val values by collectValues(underTest.lockscreenAlpha)
- val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- // Should start running here...
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- // ...up to here
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.1f),
+ // Should start running here...
+ step(0.3f),
+ step(0.4f),
+ step(0.5f),
+ step(0.6f),
+ // ...up to here
+ step(0.8f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun lockscreenTranslationY() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y,
+ 100
+ )
+ val values by collectValues(underTest.lockscreenTranslationY)
- val pixels = 100
- val job =
- underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
-
- job.cancel()
}
@Test
fun lockscreenTranslationYResettedAfterJobCancelled() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y,
+ 100
+ )
+ val values by collectValues(underTest.lockscreenTranslationY)
- val pixels = 100
- val job =
- underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
- repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
assertThat(values.last()).isEqualTo(0f)
-
- job.cancel()
}
@Test
fun deviceEntryParentViewFadeIn() =
- runTest(UnconfinedTestDispatcher()) {
- val values = mutableListOf<Float>()
+ testScope.runTest {
+ val values by collectValues(underTest.deviceEntryParentViewAlpha)
- val job = underTest.deviceEntryParentViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- // Should start running here...
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- // ...up to here
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.1f),
+ // Should start running here...
+ step(0.3f),
+ step(0.4f),
+ step(0.5f),
+ step(0.6f),
+ // ...up to here
+ step(0.8f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(5)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
-
- job.cancel()
}
@Test
fun deviceEntryBackgroundViewShows() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
fingerprintPropertyRepository.supportsUdfps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val values = mutableListOf<Float>()
+ val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
- val job =
- underTest.deviceEntryBackgroundViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(0.1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.3f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.4f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.6f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.8f))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
values.forEach { assertThat(it).isEqualTo(1f) }
-
- job.cancel()
}
@Test
fun deviceEntryBackgroundView_noUdfpsEnrolled_noUpdates() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
fingerprintPropertyRepository.supportsRearFps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val values = mutableListOf<Float>()
+ val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
- val job =
- underTest.deviceEntryBackgroundViewAlpha.onEach { values.add(it) }.launchIn(this)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(0.1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.3f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.4f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.6f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.8f))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
assertThat(values).isEmpty() // no updates
-
- job.cancel()
}
private fun step(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index 6cab023..78d87a6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -19,80 +19,61 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.flags.featureFlagsClassic
+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.statusbar.SysuiStatusBarStateController
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.sysuiStatusBarStateController
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: PrimaryBouncerToGoneTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var featureFlags: FakeFeatureFlags
- @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
- @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
- @Mock private lateinit var bouncerToGoneFlows: BouncerToGoneFlows
- @Mock
- private lateinit var keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>
+ val kosmos =
+ testKosmos().apply {
+ featureFlagsClassic.apply {
+ set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ }
+ }
+ val testScope = kosmos.testScope
- private val shadeExpansionStateFlow = MutableStateFlow(0.1f)
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val primaryBouncerInteractor = kosmos.primaryBouncerInteractor
+ val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController
+ val underTest = kosmos.primaryBouncerToGoneTransitionViewModel
@Before
fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- repository = FakeKeyguardTransitionRepository()
- val featureFlags =
- FakeFeatureFlags().apply { set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) }
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest =
- PrimaryBouncerToGoneTransitionViewModel(
- interactor,
- statusBarStateController,
- primaryBouncerInteractor,
- keyguardDismissActionInteractor,
- featureFlags,
- bouncerToGoneFlows,
- )
-
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
- whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
}
@Test
fun bouncerAlpha() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.bouncerAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(3)
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
@@ -100,14 +81,19 @@
@Test
fun bouncerAlpha_runDimissFromKeyguard() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.bouncerAlpha)
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(3)
values.forEach { assertThat(it).isEqualTo(0f) }
@@ -115,11 +101,11 @@
@Test
fun lockscreenAlpha() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.lockscreenAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
assertThat(values.size).isEqualTo(2)
values.forEach { assertThat(it).isEqualTo(0f) }
@@ -127,13 +113,13 @@
@Test
fun lockscreenAlpha_runDimissFromKeyguard() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.lockscreenAlpha)
- whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
assertThat(values.size).isEqualTo(2)
values.forEach { assertThat(it).isEqualTo(1f) }
@@ -141,13 +127,13 @@
@Test
fun lockscreenAlpha_leaveShadeOpen() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.lockscreenAlpha)
- whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(true)
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
assertThat(values.size).isEqualTo(2)
values.forEach { assertThat(it).isEqualTo(1f) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt
new file mode 100644
index 0000000..2b744ac
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain
+
+import android.app.AlarmManager
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
+import com.android.systemui.qs.tiles.impl.alarm.qsAlarmTileConfig
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import java.time.Instant
+import java.time.LocalDateTime
+import java.util.TimeZone
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlarmTileMapperTest : SysuiTestCase() {
+ private val kosmos = Kosmos()
+ private val alarmTileConfig = kosmos.qsAlarmTileConfig
+ // Using lazy (versus =) to make sure we override the right context -- see b/311612168
+ private val mapper by lazy { AlarmTileMapper(context.orCreateTestableResources.resources) }
+
+ @Test
+ fun notAlarmSet() {
+ val inputModel = AlarmTileModel.NoAlarmSet
+
+ val outputState = mapper.map(alarmTileConfig, inputModel)
+
+ val expectedState =
+ createAlarmTileState(
+ QSTileState.ActivationState.INACTIVE,
+ context.getString(R.string.qs_alarm_tile_no_alarm)
+ )
+ QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+ }
+
+ @Test
+ fun nextAlarmSet24HourFormat() {
+ val triggerTime = 1L
+ val inputModel =
+ AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null))
+
+ val outputState = mapper.map(alarmTileConfig, inputModel)
+
+ val localDateTime =
+ LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(triggerTime),
+ TimeZone.getDefault().toZoneId()
+ )
+ val expectedSecondaryLabel = AlarmTileMapper.formatter24Hour.format(localDateTime)
+ val expectedState =
+ createAlarmTileState(QSTileState.ActivationState.ACTIVE, expectedSecondaryLabel)
+ QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+ }
+
+ @Test
+ fun nextAlarmSet12HourFormat() {
+ val triggerTime = 1L
+ val inputModel =
+ AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null))
+
+ val outputState = mapper.map(alarmTileConfig, inputModel)
+
+ val localDateTime =
+ LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(triggerTime),
+ TimeZone.getDefault().toZoneId()
+ )
+ val expectedSecondaryLabel = AlarmTileMapper.formatter12Hour.format(localDateTime)
+ val expectedState =
+ createAlarmTileState(QSTileState.ActivationState.ACTIVE, expectedSecondaryLabel)
+ QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+ }
+
+ private fun createAlarmTileState(
+ activationState: QSTileState.ActivationState,
+ secondaryLabel: String
+ ): QSTileState {
+ val label = context.getString(R.string.status_bar_alarm)
+ return QSTileState(
+ { Icon.Resource(R.drawable.ic_alarm, null) },
+ label,
+ activationState,
+ secondaryLabel,
+ setOf(QSTileState.UserAction.CLICK),
+ label,
+ null,
+ QSTileState.SideViewIcon.None,
+ QSTileState.EnabledState.ENABLED,
+ Switch::class.qualifiedName
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractorTest.kt
new file mode 100644
index 0000000..990d747
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractorTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain.interactor
+
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.os.UserHandle
+import android.testing.LeakCheck
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.DateFormatUtil
+import com.android.systemui.utils.leaks.FakeNextAlarmController
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.toCollection
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlarmTileDataInteractorTest : SysuiTestCase() {
+ private lateinit var dateFormatUtil: DateFormatUtil
+
+ private val nextAlarmController = FakeNextAlarmController(LeakCheck())
+ private lateinit var underTest: AlarmTileDataInteractor
+
+ @Before
+ fun setup() {
+ dateFormatUtil = mock<DateFormatUtil>()
+ underTest = AlarmTileDataInteractor(nextAlarmController, dateFormatUtil)
+ }
+
+ @Test
+ fun alarmTriggerTimeDataMatchesTheController() = runTest {
+ val expectedTriggerTime = 1L
+ val alarmInfo = AlarmManager.AlarmClockInfo(expectedTriggerTime, mock<PendingIntent>())
+ val dataList: List<AlarmTileModel> by
+ collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)))
+
+ runCurrent()
+ nextAlarmController.setNextAlarm(alarmInfo)
+ runCurrent()
+ nextAlarmController.setNextAlarm(null)
+ runCurrent()
+
+ assertThat(dataList).hasSize(3)
+ assertThat(dataList[0]).isInstanceOf(AlarmTileModel.NoAlarmSet::class.java)
+ assertThat(dataList[1]).isInstanceOf(AlarmTileModel.NextAlarmSet::class.java)
+ val actualAlarmClockInfo = (dataList[1] as AlarmTileModel.NextAlarmSet).alarmClockInfo
+ assertThat(actualAlarmClockInfo).isNotNull()
+ val actualTriggerTime = actualAlarmClockInfo.triggerTime
+ assertThat(actualTriggerTime).isEqualTo(expectedTriggerTime)
+ assertThat(dataList[2]).isInstanceOf(AlarmTileModel.NoAlarmSet::class.java)
+ }
+
+ @Test
+ fun dateFormatUtil24HourDataMatchesController() = runTest {
+ val expectedValue = true
+ whenever(dateFormatUtil.is24HourFormat).thenReturn(expectedValue)
+ val alarmInfo = AlarmManager.AlarmClockInfo(1L, mock<PendingIntent>())
+ nextAlarmController.setNextAlarm(alarmInfo)
+
+ val model by
+ collectLastValue(
+ underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+ )
+ runCurrent()
+
+ assertThat(model).isNotNull()
+ assertThat(model).isInstanceOf(AlarmTileModel.NextAlarmSet::class.java)
+ val actualValue = (model as AlarmTileModel.NextAlarmSet).is24HourFormat
+ assertThat(actualValue).isEqualTo(expectedValue)
+ }
+
+ @Test
+ fun dateFormatUtil12HourDataMatchesController() = runTest {
+ val expectedValue = false
+ whenever(dateFormatUtil.is24HourFormat).thenReturn(expectedValue)
+ val alarmInfo = AlarmManager.AlarmClockInfo(1L, mock<PendingIntent>())
+ nextAlarmController.setNextAlarm(alarmInfo)
+
+ val model by
+ collectLastValue(
+ underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+ )
+ runCurrent()
+
+ assertThat(model).isNotNull()
+ assertThat(model).isInstanceOf(AlarmTileModel.NextAlarmSet::class.java)
+ val actualValue = (model as AlarmTileModel.NextAlarmSet).is24HourFormat
+ assertThat(actualValue).isEqualTo(expectedValue)
+ }
+
+ @Test
+ fun alwaysAvailable() = runTest {
+ val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())
+
+ assertThat(availability).hasSize(1)
+ assertThat(availability.last()).isTrue()
+ }
+
+ private companion object {
+ val TEST_USER = UserHandle.of(1)!!
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..e44c849
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractorTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain.interactor
+
+import android.app.AlarmManager.AlarmClockInfo
+import android.app.PendingIntent
+import android.content.Intent
+import android.provider.AlarmClock
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx.click
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlarmTileUserActionInteractorTest : SysuiTestCase() {
+ private lateinit var activityStarter: ActivityStarter
+ private lateinit var intentCaptor: ArgumentCaptor<Intent>
+ private lateinit var pendingIntentCaptor: ArgumentCaptor<PendingIntent>
+
+ lateinit var underTest: AlarmTileUserActionInteractor
+
+ @Before
+ fun setup() {
+ activityStarter = mock<ActivityStarter>()
+ intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
+ pendingIntentCaptor = ArgumentCaptor.forClass(PendingIntent::class.java)
+ underTest = AlarmTileUserActionInteractor(activityStarter)
+ }
+
+ @Test
+ fun handleClickWithDefaultIntent() = runTest {
+ val alarmInfo = AlarmClockInfo(1L, null)
+ val inputModel = AlarmTileModel.NextAlarmSet(true, alarmInfo)
+
+ underTest.handleInput(click(inputModel))
+
+ verify(activityStarter)
+ .postStartActivityDismissingKeyguard(capture(intentCaptor), eq(0), nullable())
+ assertThat(intentCaptor.value.action).isEqualTo(AlarmClock.ACTION_SHOW_ALARMS)
+ }
+
+ @Test
+ fun handleClickWithPendingIntent() = runTest {
+ val expectedIntent: PendingIntent = mock<PendingIntent>()
+ val alarmInfo = AlarmClockInfo(1L, expectedIntent)
+ val inputModel = AlarmTileModel.NextAlarmSet(true, alarmInfo)
+
+ underTest.handleInput(click(inputModel))
+
+ verify(activityStarter)
+ .postStartActivityDismissingKeyguard(capture(pendingIntentCaptor), nullable())
+ assertThat(pendingIntentCaptor.value).isEqualTo(expectedIntent)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
index 0b922a8..de767e3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
@@ -65,7 +65,7 @@
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
- private DialogDelegate<SystemUIDialog> mDelegate;
+ private SystemUIDialog.Delegate mDelegate;
@Before
public void setup() {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/AlarmData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/AlarmData.kt
new file mode 100644
index 0000000..837857b
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/AlarmData.kt
@@ -0,0 +1,6 @@
+package com.android.systemui.plugins.clocks
+
+data class AlarmData(
+ val nextAlarmMillis: Long?,
+ val descriptionId: String?,
+)
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
similarity index 97%
rename from packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
rename to packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
index 63ded2e..1c5f221 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
@@ -11,7 +11,7 @@
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-package com.android.systemui.plugins
+package com.android.systemui.plugins.clocks
import android.content.res.Resources
import android.graphics.Rect
@@ -20,6 +20,7 @@
import androidx.constraintlayout.widget.ConstraintSet
import com.android.internal.annotations.Keep
import com.android.systemui.log.core.MessageBuffer
+import com.android.systemui.plugins.Plugin
import com.android.systemui.plugins.annotations.ProvidesInterface
import java.io.PrintWriter
import java.util.Locale
@@ -145,6 +146,12 @@
/** Call whenever the weather data should update */
fun onWeatherDataChanged(data: WeatherData)
+
+ /** Call with alarm information */
+ fun onAlarmDataChanged(data: AlarmData)
+
+ /** Call with zen/dnd information */
+ fun onZenDataChanged(data: ZenData)
}
/** Methods which trigger various clock animations */
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
similarity index 98%
rename from packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
rename to packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
index affb76b..789a473 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
@@ -1,4 +1,4 @@
-package com.android.systemui.plugins
+package com.android.systemui.plugins.clocks
import android.os.Bundle
import android.util.Log
@@ -7,8 +7,7 @@
typealias WeatherTouchAction = (View) -> Unit
-class WeatherData
-constructor(
+data class WeatherData(
val description: String,
val state: WeatherStateIcon,
val useCelsius: Boolean,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ZenData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ZenData.kt
new file mode 100644
index 0000000..e927ec3
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ZenData.kt
@@ -0,0 +1,22 @@
+package com.android.systemui.plugins.clocks
+
+import android.provider.Settings.Global.ZEN_MODE_ALARMS
+import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+import android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+import android.provider.Settings.Global.ZEN_MODE_OFF
+
+data class ZenData(
+ val zenMode: ZenMode,
+ val descriptionId: String?,
+) {
+ enum class ZenMode(val zenMode: Int) {
+ OFF(ZEN_MODE_OFF),
+ IMPORTANT_INTERRUPTIONS(ZEN_MODE_IMPORTANT_INTERRUPTIONS),
+ NO_INTERRUPTIONS(ZEN_MODE_NO_INTERRUPTIONS),
+ ALARMS(ZEN_MODE_ALARMS);
+
+ companion object {
+ fun fromInt(zenMode: Int) = values().firstOrNull { it.zenMode == zenMode }
+ }
+ }
+}
diff --git a/packages/SystemUI/res/color/notification_overlay_color.xml b/packages/SystemUI/res/color/notification_overlay_color.xml
index c24bff9..a14a7ad 100644
--- a/packages/SystemUI/res/color/notification_overlay_color.xml
+++ b/packages/SystemUI/res/color/notification_overlay_color.xml
@@ -17,7 +17,9 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:state_pressed="true" android:color="?androidprv:attr/materialColorOnSurface" android:alpha="0.15" />
+ <!-- Pressed state's alpha is set to 0.00 temporarily until this bug is resolved permanently
+ b/313920497 Design intended alpha is 0.15-->
+ <item android:state_pressed="true" android:color="?androidprv:attr/materialColorOnSurface" android:alpha="0.00" />
<item android:state_hovered="true" android:color="?androidprv:attr/materialColorOnSurface" android:alpha="0.11" />
<item android:color="@color/transparent" />
</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 03960d5..7db21b2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -37,6 +37,7 @@
<!-- Used while animating the navbar during a long press. -->
<dimen name="navigation_home_handle_additional_width_for_animation">20dp</dimen>
<dimen name="navigation_home_handle_additional_height_for_animation">4dp</dimen>
+ <dimen name="navigation_home_handle_shrink_width_for_animation">16dp</dimen>
<!-- Size of the nav bar edge panels, should be greater to the
edge sensitivity + the drag threshold -->
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 0903463..763930d 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -38,6 +38,4 @@
protected. -->
<bool name="flag_battery_shield_icon">false</bool>
- <!-- Whether we want to stop pulsing while running the face scanning animation -->
- <bool name="flag_stop_pulsing_face_scanning_animation">true</bool>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 26e785d..4632914 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -149,10 +149,11 @@
*
* @param isTouchDown {@code true} if the button is starting to be pressed ({@code false} if
* released or canceled)
+ * @param shrink {@code true} if the handle should shrink, {@code false} if it should grow
* @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
* should be the same as the amount of time to trigger a long-press)
*/
- oneway void animateNavBarLongPress(boolean isTouchDown, long durationMs) = 54;
+ oneway void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) = 54;
// Next id = 55
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index c02ffa7..76abad8 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -33,8 +33,8 @@
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.customization.R
import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.customization.R
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.DisplaySpecific
import com.android.systemui.dagger.qualifiers.Main
@@ -49,14 +49,19 @@
import com.android.systemui.log.core.LogLevel.DEBUG
import com.android.systemui.log.dagger.KeyguardLargeClockLog
import com.android.systemui.log.dagger.KeyguardSmallClockLog
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockFaceController
-import com.android.systemui.plugins.ClockTickRate
-import com.android.systemui.plugins.WeatherData
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockTickRate
+import com.android.systemui.plugins.clocks.AlarmData
+import com.android.systemui.plugins.clocks.WeatherData
+import com.android.systemui.plugins.clocks.ZenData
+import com.android.systemui.plugins.clocks.ZenData.ZenMode
+import com.android.systemui.res.R as SysuiR
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.concurrency.DelayableExecutor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
@@ -88,7 +93,8 @@
@Background private val bgExecutor: Executor,
@KeyguardSmallClockLog private val smallLogBuffer: LogBuffer?,
@KeyguardLargeClockLog private val largeLogBuffer: LogBuffer?,
- private val featureFlags: FeatureFlags
+ private val featureFlags: FeatureFlags,
+ private val zenModeController: ZenModeController,
) {
var clock: ClockController? = null
set(value) {
@@ -137,12 +143,18 @@
}
updateFontSizes()
updateTimeListeners()
- cachedWeatherData?.let {
+ weatherData?.let {
if (WeatherData.DEBUG) {
Log.i(TAG, "Pushing cached weather data to new clock: $it")
}
value.events.onWeatherDataChanged(it)
}
+ zenData?.let {
+ value.events.onZenDataChanged(it)
+ }
+ alarmData?.let {
+ value.events.onAlarmDataChanged(it)
+ }
smallClockOnAttachStateChangeListener =
object : OnAttachStateChangeListener {
@@ -260,7 +272,10 @@
var largeTimeListener: TimeListener? = null
val shouldTimeListenerRun: Boolean
get() = isKeyguardVisible && dozeAmount < DOZE_TICKRATE_THRESHOLD
- private var cachedWeatherData: WeatherData? = null
+
+ private var weatherData: WeatherData? = null
+ private var zenData: ZenData? = null
+ private var alarmData: AlarmData? = null
private val configListener =
object : ConfigurationController.ConfigurationListener {
@@ -321,14 +336,43 @@
override fun onUserSwitchComplete(userId: Int) {
clock?.run { events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) }
+ zenModeCallback.onNextAlarmChanged()
}
override fun onWeatherDataChanged(data: WeatherData) {
- cachedWeatherData = data
+ weatherData = data
clock?.run { events.onWeatherDataChanged(data) }
}
}
+ private val zenModeCallback = object : ZenModeController.Callback {
+ override fun onZenChanged(zen: Int) {
+ var mode = ZenMode.fromInt(zen)
+ if (mode == null) {
+ Log.e(TAG, "Failed to get zen mode from int: $zen")
+ return
+ }
+
+ zenData = ZenData(
+ mode,
+ if (mode == ZenMode.OFF) SysuiR.string::dnd_is_off.name
+ else SysuiR.string::dnd_is_on.name
+ ).also { data ->
+ clock?.run { events.onZenDataChanged(data) }
+ }
+ }
+
+ override fun onNextAlarmChanged() {
+ val nextAlarmMillis = zenModeController.getNextAlarm()
+ alarmData = AlarmData(
+ if (nextAlarmMillis > 0) nextAlarmMillis else null,
+ SysuiR.string::status_bar_alarm.name
+ ).also { data ->
+ clock?.run { events.onAlarmDataChanged(data) }
+ }
+ }
+ }
+
fun registerListeners(parent: View) {
if (isRegistered) {
return
@@ -341,6 +385,7 @@
configurationController.addCallback(configListener)
batteryController.addCallback(batteryCallback)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+ zenModeController.addCallback(zenModeCallback)
disposableHandle =
parent.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -355,6 +400,10 @@
}
smallTimeListener?.update(shouldTimeListenerRun)
largeTimeListener?.update(shouldTimeListenerRun)
+
+ // Query ZenMode data
+ zenModeCallback.onZenChanged(zenModeController.zen)
+ zenModeCallback.onNextAlarmChanged()
}
fun unregisterListeners() {
@@ -368,6 +417,7 @@
configurationController.removeCallback(configListener)
batteryController.removeCallback(batteryCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
+ zenModeController.removeCallback(zenModeCallback)
smallRegionSampler?.stopRegionSampler()
largeRegionSampler?.stopRegionSampler()
smallTimeListener?.stop()
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 39a59c4..a5a545a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -24,7 +24,7 @@
import com.android.keyguard.dagger.KeyguardStatusViewScope;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.LogLevel;
-import com.android.systemui.plugins.ClockController;
+import com.android.systemui.plugins.clocks.ClockController;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.DefaultClockController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 54cb501..85c9fff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -54,7 +54,7 @@
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.log.dagger.KeyguardClockLog;
-import com.android.systemui.plugins.ClockController;
+import com.android.systemui.plugins.clocks.ClockController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.ClockRegistry;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index b309483..714fe64 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -26,6 +26,7 @@
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -210,6 +211,7 @@
private final KeyguardViewController mKeyguardViewController;
private final FeatureFlags mFeatureFlags;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final UiEventLogger mUiEventLogger;
@Inject
public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -222,7 +224,8 @@
EmergencyButtonController.Factory emergencyButtonControllerFactory,
DevicePostureController devicePostureController,
KeyguardViewController keyguardViewController,
- FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor) {
+ FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor,
+ UiEventLogger uiEventLogger) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
@@ -238,6 +241,7 @@
mKeyguardViewController = keyguardViewController;
mFeatureFlags = featureFlags;
mSelectedUserInteractor = selectedUserInteractor;
+ mUiEventLogger = uiEventLogger;
}
/** Create a new {@link KeyguardInputViewController}. */
@@ -265,7 +269,8 @@
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
- mDevicePostureController, mFeatureFlags, mSelectedUserInteractor);
+ mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
+ mUiEventLogger);
} else if (keyguardInputView instanceof KeyguardSimPinView) {
return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 947d90f..2aab1f1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -20,6 +20,8 @@
import android.view.View;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -44,6 +46,7 @@
private View mOkButton = mView.findViewById(R.id.key_enter);
private long mPinLength;
+ private final UiEventLogger mUiEventLogger;
private boolean mDisabledAutoConfirmation;
@@ -56,7 +59,8 @@
EmergencyButtonController emergencyButtonController,
FalsingCollector falsingCollector,
DevicePostureController postureController,
- FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor) {
+ FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor,
+ UiEventLogger uiEventLogger) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
emergencyButtonController, falsingCollector, featureFlags, selectedUserInteractor);
@@ -67,6 +71,7 @@
view.setIsLockScreenLandscapeEnabled(mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE));
mBackspaceKey = view.findViewById(R.id.delete_button);
mPinLength = mLockPatternUtils.getPinLength(selectedUserInteractor.getSelectedUserId());
+ mUiEventLogger = uiEventLogger;
}
@Override
@@ -95,6 +100,7 @@
updateAutoConfirmationState();
if (mPasswordEntry.getText().length() == mPinLength
&& mOkButton.getVisibility() == View.INVISIBLE) {
+ mUiEventLogger.log(PinBouncerUiEvent.ATTEMPT_UNLOCK_WITH_AUTO_CONFIRM_FEATURE);
verifyPasswordAndUnlock();
}
}
@@ -184,4 +190,21 @@
mSelectedUserInteractor.getSelectedUserId())
&& mPinLength != LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
}
+
+ /** UI Events for the auto confirmation feature in*/
+ enum PinBouncerUiEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "Attempting to unlock the device with the auto confirm feature.")
+ ATTEMPT_UNLOCK_WITH_AUTO_CONFIRM_FEATURE(1547);
+
+ private final int mId;
+
+ PinBouncerUiEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 4fbf077..2a54a4e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -56,7 +56,7 @@
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
-import com.android.systemui.plugins.ClockController;
+import com.android.systemui.plugins.clocks.ClockController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
import com.android.systemui.res.R;
@@ -70,13 +70,13 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
+import kotlin.coroutines.CoroutineContext;
+import kotlin.coroutines.EmptyCoroutineContext;
+
import java.io.PrintWriter;
import javax.inject.Inject;
-import kotlin.coroutines.CoroutineContext;
-import kotlin.coroutines.EmptyCoroutineContext;
-
/**
* Injectable controller for {@link KeyguardStatusView}.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c5bb099..37bd9b2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -131,7 +131,7 @@
import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus;
import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus;
import com.android.systemui.log.SessionTracker;
-import com.android.systemui.plugins.WeatherData;
+import com.android.systemui.plugins.clocks.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 2476067..02dd331 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -23,7 +23,7 @@
import androidx.annotation.Nullable;
import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.systemui.plugins.WeatherData;
+import com.android.systemui.plugins.clocks.WeatherData;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.util.annotations.WeaklyReferencedCallback;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
index 9716d98..ee35bb9 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
@@ -20,7 +20,6 @@
import android.content.res.Resources;
import android.view.LayoutInflater;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Background;
@@ -30,6 +29,7 @@
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.dagger.KeyguardClockLog;
import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.shared.clocks.DefaultClockProvider;
@@ -67,7 +67,8 @@
context,
layoutInflater,
resources,
- featureFlags.isEnabled(Flags.STEP_CLOCK_ANIMATION)),
+ featureFlags.isEnabled(Flags.STEP_CLOCK_ANIMATION),
+ featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)),
context.getString(R.string.lockscreen_clock_id_fallback),
logBuffer,
/* keepAllLoaded = */ false,
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardTransitionAnimationLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardTransitionAnimationLogger.kt
new file mode 100644
index 0000000..d9830b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardTransitionAnimationLogger.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.keyguard.logging
+
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.KeyguardTransitionAnimationLog
+import javax.inject.Inject
+
+private const val TAG = "KeyguardTransitionAnimationLog"
+
+/**
+ * Generic logger for keyguard that's wrapping [LogBuffer]. This class should be used for adding
+ * temporary logs or logs for smaller classes when creating whole new [LogBuffer] wrapper might be
+ * an overkill.
+ */
+class KeyguardTransitionAnimationLogger
+@Inject
+constructor(
+ @KeyguardTransitionAnimationLog val buffer: LogBuffer,
+) {
+ @JvmOverloads
+ fun logCreate(
+ name: String? = null,
+ start: Float,
+ ) {
+ if (name == null) return
+
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = name
+ str2 = "$start"
+ },
+ { "[$str1] starts at: $str2" }
+ )
+ }
+
+ @JvmOverloads
+ fun logTransitionStep(
+ name: String? = null,
+ step: TransitionStep,
+ value: Float? = null,
+ ) {
+ if (name == null) return
+
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = "[$name][${step.transitionState}]"
+ str2 = "${step.value}"
+ str3 = "$value"
+ },
+ { "$str1 transitionStep=$str2, animationValue=$str3" }
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index c1871e0..71bac06 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -209,11 +209,11 @@
return result
}
- open fun enableShowProtection(show: Boolean) {
- if (showProtection == show) {
+ open fun enableShowProtection(isCameraActive: Boolean) {
+ if (showProtection == isCameraActive) {
return
}
- showProtection = show
+ showProtection = isCameraActive
updateProtectionBoundingPath()
// Delay the relayout until the end of the animation when hiding the cutout,
// otherwise we'd clip it.
diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
index 95e2dba..3abcb13 100644
--- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
@@ -28,16 +28,12 @@
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
-import android.hardware.biometrics.BiometricSourceType
import android.view.View
import androidx.core.graphics.ColorUtils
import com.android.app.animation.Interpolators
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.settingslib.Utils
import com.android.systemui.biometrics.AuthController
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.util.asIndenting
@@ -56,7 +52,6 @@
val mainExecutor: Executor,
val logger: ScreenDecorationsLogger,
val authController: AuthController,
- val featureFlags: FeatureFlags,
) : ScreenDecorations.DisplayCutoutView(context, pos) {
private var showScanningAnim = false
private val rimPaint = Paint()
@@ -69,26 +64,11 @@
com.android.internal.R.attr.materialColorPrimaryFixed)
private var cameraProtectionAnimator: ValueAnimator? = null
var hideOverlayRunnable: Runnable? = null
- var faceAuthSucceeded = false
init {
visibility = View.INVISIBLE // only show this view when face scanning is happening
}
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
- mainExecutor.execute {
- keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
- }
- }
-
- override fun onDetachedFromWindow() {
- super.onDetachedFromWindow()
- mainExecutor.execute {
- keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
- }
- }
-
override fun setColor(color: Int) {
cameraProtectionColor = color
invalidate()
@@ -106,18 +86,22 @@
}
}
- override fun enableShowProtection(show: Boolean) {
- val animationRequired =
+ override fun enableShowProtection(isCameraActive: Boolean) {
+ val scanningAnimationRequiredWhenCameraActive =
keyguardUpdateMonitor.isFaceDetectionRunning || authController.isShowing
- val showScanningAnimNow = animationRequired && show
- if (showScanningAnimNow == showScanningAnim) {
+ val faceAuthSucceeded = keyguardUpdateMonitor.isFaceAuthenticated
+ val showScanningAnimationNow = scanningAnimationRequiredWhenCameraActive && isCameraActive
+ if (showScanningAnimationNow == showScanningAnim) {
return
}
- logger.cameraProtectionShownOrHidden(keyguardUpdateMonitor.isFaceDetectionRunning,
+ logger.cameraProtectionShownOrHidden(
+ showScanningAnimationNow,
+ keyguardUpdateMonitor.isFaceDetectionRunning,
authController.isShowing,
- show,
+ faceAuthSucceeded,
+ isCameraActive,
showScanningAnim)
- showScanningAnim = showScanningAnimNow
+ showScanningAnim = showScanningAnimationNow
updateProtectionBoundingPath()
// Delay the relayout until the end of the animation when hiding,
// otherwise we'd clip it.
@@ -128,7 +112,7 @@
cameraProtectionAnimator?.cancel()
cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress,
- if (showScanningAnimNow) SHOW_CAMERA_PROTECTION_SCALE
+ if (showScanningAnimationNow) SHOW_CAMERA_PROTECTION_SCALE
else HIDDEN_CAMERA_PROTECTION_SCALE).apply {
startDelay =
if (showScanningAnim) 0
@@ -297,20 +281,10 @@
}
private fun createFaceScanningRimAnimator(): AnimatorSet {
- val dontPulse = featureFlags.isEnabled(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION)
- if (dontPulse) {
- return AnimatorSet().apply {
- playSequentially(
- cameraProtectionAnimator,
- createRimAppearAnimator(),
- )
- }
- }
return AnimatorSet().apply {
playSequentially(
- cameraProtectionAnimator,
- createRimAppearAnimator(),
- createPulseAnimator()
+ cameraProtectionAnimator,
+ createRimAppearAnimator(),
)
}
}
@@ -348,81 +322,16 @@
invalidate()
}
- private fun createPulseAnimator(): ValueAnimator {
- return ValueAnimator.ofFloat(
- PULSE_RADIUS_OUT, PULSE_RADIUS_IN).apply {
- duration = HALF_PULSE_DURATION
- interpolator = Interpolators.STANDARD
- repeatCount = 11 // Pulse inwards and outwards, reversing direction, 6 times
- repeatMode = ValueAnimator.REVERSE
- addUpdateListener(this@FaceScanningOverlay::updateRimProgress)
- }
- }
-
- private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
- override fun onBiometricAuthenticated(
- userId: Int,
- biometricSourceType: BiometricSourceType?,
- isStrongBiometric: Boolean
- ) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- post {
- faceAuthSucceeded = true
- logger.biometricEvent("biometricAuthenticated")
- enableShowProtection(true)
- }
- }
- }
-
- override fun onBiometricAcquired(
- biometricSourceType: BiometricSourceType?,
- acquireInfo: Int
- ) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- post {
- faceAuthSucceeded = false // reset
- }
- }
- }
-
- override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- post {
- faceAuthSucceeded = false
- logger.biometricEvent("biometricFailed")
- enableShowProtection(false)
- }
- }
- }
-
- override fun onBiometricError(
- msgId: Int,
- errString: String?,
- biometricSourceType: BiometricSourceType?
- ) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- post {
- faceAuthSucceeded = false
- logger.biometricEvent("biometricError")
- enableShowProtection(false)
- }
- }
- }
- }
-
companion object {
private const val HIDDEN_RIM_SCALE = HIDDEN_CAMERA_PROTECTION_SCALE
private const val SHOW_CAMERA_PROTECTION_SCALE = 1f
- private const val PULSE_RADIUS_IN = 1.1f
private const val PULSE_RADIUS_OUT = 1.125f
private const val PULSE_RADIUS_SUCCESS = 1.25f
private const val CAMERA_PROTECTION_APPEAR_DURATION = 250L
private const val PULSE_APPEAR_DURATION = 250L // without start delay
- private const val HALF_PULSE_DURATION = 500L
-
private const val PULSE_SUCCESS_DISAPPEAR_DURATION = 400L
private const val CAMERA_PROTECTION_SUCCESS_DISAPPEAR_DURATION = 500L // without start delay
diff --git a/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java
index 494efb7..45cc71e 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java
@@ -36,7 +36,6 @@
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import dagger.Lazy;
import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;
@@ -141,23 +140,23 @@
* reset and restart of guest user.
*/
public static final class ResetSessionDialogFactory {
- private final Lazy<SystemUIDialog> mDialogLazy;
+ private final SystemUIDialog.Factory mDialogFactory;
private final Resources mResources;
private final ResetSessionDialogClickListener.Factory mClickListenerFactory;
@Inject
public ResetSessionDialogFactory(
- Lazy<SystemUIDialog> dialogLazy,
+ SystemUIDialog.Factory dialogFactory,
@Main Resources resources,
ResetSessionDialogClickListener.Factory clickListenerFactory) {
- mDialogLazy = dialogLazy;
+ mDialogFactory = dialogFactory;
mResources = resources;
mClickListenerFactory = clickListenerFactory;
}
/** Create a guest reset dialog instance */
public AlertDialog create(int userId) {
- SystemUIDialog dialog = mDialogLazy.get();
+ SystemUIDialog dialog = mDialogFactory.create();
ResetSessionDialogClickListener listener = mClickListenerFactory.create(
userId, dialog);
dialog.setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title);
@@ -216,22 +215,22 @@
* exit of guest user.
*/
public static final class ExitSessionDialogFactory {
- private final Lazy<SystemUIDialog> mDialogLazy;
+ private final SystemUIDialog.Factory mDialogFactory;
private final ExitSessionDialogClickListener.Factory mClickListenerFactory;
private final Resources mResources;
@Inject
public ExitSessionDialogFactory(
- Lazy<SystemUIDialog> dialogLazy,
+ SystemUIDialog.Factory dialogFactory,
ExitSessionDialogClickListener.Factory clickListenerFactory,
@Main Resources resources) {
- mDialogLazy = dialogLazy;
+ mDialogFactory = dialogFactory;
mClickListenerFactory = clickListenerFactory;
mResources = resources;
}
public AlertDialog create(boolean isEphemeral, int userId) {
- SystemUIDialog dialog = mDialogLazy.get();
+ SystemUIDialog dialog = mDialogFactory.create();
ExitSessionDialogClickListener clickListener = mClickListenerFactory.create(
isEphemeral, userId, dialog);
if (isEphemeral) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 7ccf704..685ea81 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -5,6 +5,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.SearchManager;
import android.app.StatusBarManager;
@@ -146,6 +147,7 @@
private final DisplayTracker mDisplayTracker;
private final SecureSettings mSecureSettings;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final ActivityManager mActivityManager;
private final DeviceProvisionedController mDeviceProvisionedController;
@@ -186,7 +188,8 @@
UserTracker userTracker,
DisplayTracker displayTracker,
SecureSettings secureSettings,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ ActivityManager activityManager) {
mContext = context;
mDeviceProvisionedController = controller;
mCommandQueue = commandQueue;
@@ -199,6 +202,7 @@
mDisplayTracker = displayTracker;
mSecureSettings = secureSettings;
mSelectedUserInteractor = selectedUserInteractor;
+ mActivityManager = activityManager;
registerVoiceInteractionSessionListener();
registerVisualQueryRecognitionStatusListener();
@@ -270,6 +274,9 @@
}
public void startAssist(Bundle args) {
+ if (mActivityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
+ return;
+ }
if (shouldOverrideAssist(args)) {
try {
if (mOverviewProxyService.getProxy() == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 8fe42b5..877afce 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -86,6 +86,8 @@
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -133,7 +135,7 @@
@NonNull private final Provider<PromptSelectorInteractor> mPromptSelectorInteractor;
@NonNull private final Provider<CredentialViewModel> mCredentialViewModelProvider;
@NonNull private final Provider<PromptViewModel> mPromptViewModelProvider;
- @NonNull private final LogContextInteractor mLogContextInteractor;
+ @NonNull private final Lazy<LogContextInteractor> mLogContextInteractor;
private final Display mDisplay;
private float mScaleFactor = 1f;
@@ -156,7 +158,7 @@
@Nullable private UdfpsOverlayParams mUdfpsOverlayParams;
@Nullable private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback;
@Nullable private SideFpsController mSideFpsController;
- @NonNull private UdfpsLogger mUdfpsLogger;
+ @NonNull private Lazy<UdfpsLogger> mUdfpsLogger;
@VisibleForTesting IBiometricSysuiReceiver mReceiver;
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
@@ -309,7 +311,7 @@
});
mUdfpsController.setAuthControllerUpdateUdfpsLocation(this::updateUdfpsLocation);
mUdfpsController.setUdfpsDisplayMode(new UdfpsDisplayMode(mContext, mExecution,
- this, mUdfpsLogger));
+ this, mUdfpsLogger.get()));
mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
}
@@ -755,8 +757,8 @@
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils,
- @NonNull UdfpsLogger udfpsLogger,
- @NonNull LogContextInteractor logContextInteractor,
+ @NonNull Lazy<UdfpsLogger> udfpsLogger,
+ @NonNull Lazy<LogContextInteractor> logContextInteractor,
@NonNull Provider<PromptCredentialInteractor> promptCredentialInteractorProvider,
@NonNull Provider<PromptSelectorInteractor> promptSelectorInteractorProvider,
@NonNull Provider<CredentialViewModel> credentialViewModelProvider,
@@ -903,7 +905,7 @@
@Override
public void setBiometricContextListener(IBiometricContextListener listener) {
- mLogContextInteractor.addBiometricContextListener(listener);
+ mLogContextInteractor.get().addBiometricContextListener(listener);
}
/**
@@ -932,14 +934,14 @@
*/
public void requestMaxRefreshRate(boolean request) throws RemoteException {
if (mUdfpsRefreshRateRequestCallback == null) {
- mUdfpsLogger.log(
+ mUdfpsLogger.get().log(
"PreAuthRefreshRate",
"skip request - refreshRateCallback is null",
LogLevel.DEBUG
);
return;
}
- mUdfpsLogger.requestMaxRefreshRate(request);
+ mUdfpsLogger.get().requestMaxRefreshRate(request);
mUdfpsRefreshRateRequestCallback.onAuthenticationPossible(mContext.getDisplayId(), request);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
index c22a66b..df27cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
@@ -22,7 +22,6 @@
import android.hardware.biometrics.BiometricSourceType;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import javax.inject.Inject;
@@ -41,7 +40,8 @@
private final Context mContext;
private final BiometricNotificationDialogFactory mNotificationDialogFactory;
@Inject
- BiometricNotificationBroadcastReceiver(Context context,
+ BiometricNotificationBroadcastReceiver(
+ Context context,
BiometricNotificationDialogFactory notificationDialogFactory) {
mContext = context;
mNotificationDialogFactory = notificationDialogFactory;
@@ -53,15 +53,16 @@
switch (action) {
case ACTION_SHOW_FACE_REENROLL_DIALOG:
- mNotificationDialogFactory.createReenrollDialog(mContext,
- new SystemUIDialog(mContext),
+ mNotificationDialogFactory.createReenrollDialog(
+ mContext.getUserId(),
+ mContext::startActivity,
BiometricSourceType.FACE)
.show();
break;
case ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG:
mNotificationDialogFactory.createReenrollDialog(
- mContext,
- new SystemUIDialog(mContext),
+ mContext.getUserId(),
+ mContext::startActivity,
BiometricSourceType.FINGERPRINT)
.show();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
index 2962be8..fd0feef 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
@@ -16,9 +16,11 @@
package com.android.systemui.biometrics;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Dialog;
-import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
@@ -29,9 +31,11 @@
import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import javax.inject.Inject;
+import javax.inject.Provider;
/**
* Manages the creation of dialogs to be shown for biometric re enroll notifications.
@@ -39,44 +43,56 @@
@SysUISingleton
public class BiometricNotificationDialogFactory {
private static final String TAG = "BiometricNotificationDialogFactory";
+ private final Resources mResources;
+ private final SystemUIDialog.Factory mSystemUIDialogFactory;
+ @Nullable private final FingerprintManager mFingerprintManager;
+ @Nullable private final FaceManager mFaceManager;
@Inject
- BiometricNotificationDialogFactory() {}
+ BiometricNotificationDialogFactory(
+ @Main Resources resources,
+ SystemUIDialog.Factory systemUIDialogFactory,
+ @Nullable FingerprintManager fingerprintManager,
+ @Nullable FaceManager faceManager) {
+ mResources = resources;
+ mSystemUIDialogFactory = systemUIDialogFactory;
+ mFingerprintManager = fingerprintManager;
+ mFaceManager = faceManager;
+ }
- Dialog createReenrollDialog(final Context context, final SystemUIDialog sysuiDialog,
- BiometricSourceType biometricSourceType) {
+ Dialog createReenrollDialog(
+ int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType) {
+ SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
if (biometricSourceType == BiometricSourceType.FACE) {
- sysuiDialog.setTitle(context.getString(R.string.face_re_enroll_dialog_title));
- sysuiDialog.setMessage(context.getString(R.string.face_re_enroll_dialog_content));
+ sysuiDialog.setTitle(mResources.getString(R.string.face_re_enroll_dialog_title));
+ sysuiDialog.setMessage(mResources.getString(R.string.face_re_enroll_dialog_content));
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
- FingerprintManager fingerprintManager = context.getSystemService(
- FingerprintManager.class);
- sysuiDialog.setTitle(context.getString(R.string.fingerprint_re_enroll_dialog_title));
- if (fingerprintManager.getEnrolledFingerprints().size() == 1) {
- sysuiDialog.setMessage(context.getString(
+ sysuiDialog.setTitle(mResources.getString(R.string.fingerprint_re_enroll_dialog_title));
+ if (mFingerprintManager.getEnrolledFingerprints().size() == 1) {
+ sysuiDialog.setMessage(mResources.getString(
R.string.fingerprint_re_enroll_dialog_content_singular));
} else {
- sysuiDialog.setMessage(context.getString(
+ sysuiDialog.setMessage(mResources.getString(
R.string.fingerprint_re_enroll_dialog_content));
}
}
sysuiDialog.setPositiveButton(R.string.biometric_re_enroll_dialog_confirm,
- (dialog, which) -> onReenrollDialogConfirm(context, biometricSourceType));
+ (dialog, which) -> onReenrollDialogConfirm(
+ userId, biometricSourceType, activityStarter));
sysuiDialog.setNegativeButton(R.string.biometric_re_enroll_dialog_cancel,
(dialog, which) -> {});
return sysuiDialog;
}
- private static Dialog createReenrollFailureDialog(Context context,
- BiometricSourceType biometricType) {
- final SystemUIDialog sysuiDialog = new SystemUIDialog(context);
+ private Dialog createReenrollFailureDialog(BiometricSourceType biometricType) {
+ final SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
if (biometricType == BiometricSourceType.FACE) {
- sysuiDialog.setMessage(context.getString(
+ sysuiDialog.setMessage(mResources.getString(
R.string.face_reenroll_failure_dialog_content));
} else if (biometricType == BiometricSourceType.FINGERPRINT) {
- sysuiDialog.setMessage(context.getString(
+ sysuiDialog.setMessage(mResources.getString(
R.string.fingerprint_reenroll_failure_dialog_content));
}
@@ -84,41 +100,41 @@
return sysuiDialog;
}
- private static void onReenrollDialogConfirm(final Context context,
- BiometricSourceType biometricType) {
+ private void onReenrollDialogConfirm(
+ int userId, BiometricSourceType biometricType, ActivityStarter activityStarter) {
if (biometricType == BiometricSourceType.FACE) {
- reenrollFace(context);
+ reenrollFace(userId, activityStarter);
} else if (biometricType == BiometricSourceType.FINGERPRINT) {
- reenrollFingerprint(context);
+ reenrollFingerprint(userId, activityStarter);
}
}
- private static void reenrollFingerprint(Context context) {
- FingerprintManager fingerprintManager = context.getSystemService(FingerprintManager.class);
- if (fingerprintManager == null) {
+ @SuppressLint("MissingPermission")
+ private void reenrollFingerprint(int userId, ActivityStarter activityStarter) {
+ if (mFingerprintManager == null) {
Log.e(TAG, "Not launching enrollment. Fingerprint manager was null!");
- createReenrollFailureDialog(context, BiometricSourceType.FINGERPRINT).show();
+ createReenrollFailureDialog(BiometricSourceType.FINGERPRINT).show();
return;
}
- if (!fingerprintManager.hasEnrolledTemplates(context.getUserId())) {
- createReenrollFailureDialog(context, BiometricSourceType.FINGERPRINT).show();
+ if (!mFingerprintManager.hasEnrolledTemplates(userId)) {
+ createReenrollFailureDialog(BiometricSourceType.FINGERPRINT).show();
return;
}
// Remove all enrolled fingerprint. Launch enrollment if successful.
- fingerprintManager.removeAll(context.getUserId(),
+ mFingerprintManager.removeAll(userId,
new FingerprintManager.RemovalCallback() {
boolean mDidShowFailureDialog;
@Override
- public void onRemovalError(Fingerprint fingerprint, int errMsgId,
- CharSequence errString) {
+ public void onRemovalError(
+ Fingerprint fingerprint, int errMsgId, CharSequence errString) {
Log.e(TAG, "Not launching enrollment."
+ "Failed to remove existing face(s).");
if (!mDidShowFailureDialog) {
mDidShowFailureDialog = true;
- createReenrollFailureDialog(context, BiometricSourceType.FINGERPRINT)
+ createReenrollFailureDialog(BiometricSourceType.FINGERPRINT)
.show();
}
}
@@ -129,27 +145,27 @@
Intent intent = new Intent(Settings.ACTION_FINGERPRINT_ENROLL);
intent.setPackage("com.android.settings");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ activityStarter.startActivity(intent);
}
}
});
}
- private static void reenrollFace(Context context) {
- FaceManager faceManager = context.getSystemService(FaceManager.class);
- if (faceManager == null) {
+ @SuppressLint("MissingPermission")
+ private void reenrollFace(int userId, ActivityStarter activityStarter) {
+ if (mFaceManager == null) {
Log.e(TAG, "Not launching enrollment. Face manager was null!");
- createReenrollFailureDialog(context, BiometricSourceType.FACE).show();
+ createReenrollFailureDialog(BiometricSourceType.FACE).show();
return;
}
- if (!faceManager.hasEnrolledTemplates(context.getUserId())) {
- createReenrollFailureDialog(context, BiometricSourceType.FACE).show();
+ if (!mFaceManager.hasEnrolledTemplates(userId)) {
+ createReenrollFailureDialog(BiometricSourceType.FACE).show();
return;
}
// Remove all enrolled faces. Launch enrollment if successful.
- faceManager.removeAll(context.getUserId(),
+ mFaceManager.removeAll(userId,
new FaceManager.RemovalCallback() {
boolean mDidShowFailureDialog;
@@ -159,7 +175,7 @@
+ "Failed to remove existing face(s).");
if (!mDidShowFailureDialog) {
mDidShowFailureDialog = true;
- createReenrollFailureDialog(context, BiometricSourceType.FACE).show();
+ createReenrollFailureDialog(BiometricSourceType.FACE).show();
}
}
@@ -169,9 +185,13 @@
Intent intent = new Intent("android.settings.FACE_ENROLL");
intent.setPackage("com.android.settings");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ activityStarter.startActivity(intent);
}
}
});
}
+
+ interface ActivityStarter {
+ void startActivity(Intent intent);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
index 6954eb6..a2ac66f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
@@ -26,11 +26,13 @@
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF
+import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.adapter.UdfpsKeyguardViewControllerAdapter
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -49,7 +51,7 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
/** Class that coordinates non-HBM animations during keyguard authentication. */
@@ -191,8 +193,38 @@
repeatOnLifecycle(Lifecycle.State.CREATED) {
listenForBouncerExpansion(this)
listenForAlternateBouncerVisibility(this)
+ listenForOccludedToAodTransition(this)
listenForGoneToAodTransition(this)
listenForLockscreenAodTransitions(this)
+ listenForAodToOccludedTransitions(this)
+ }
+ }
+ }
+
+ @VisibleForTesting
+ suspend fun listenForAodToOccludedTransitions(scope: CoroutineScope): Job {
+ return scope.launch {
+ transitionInteractor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED).collect {
+ transitionStep ->
+ view.onDozeAmountChanged(
+ 1f - transitionStep.value,
+ 1f - transitionStep.value,
+ UdfpsKeyguardViewLegacy.ANIMATION_NONE,
+ )
+ }
+ }
+ }
+
+ @VisibleForTesting
+ suspend fun listenForOccludedToAodTransition(scope: CoroutineScope): Job {
+ return scope.launch {
+ transitionInteractor.transition(KeyguardState.OCCLUDED, KeyguardState.AOD).collect {
+ transitionStep ->
+ view.onDozeAmountChanged(
+ transitionStep.value,
+ transitionStep.value,
+ ANIMATE_APPEAR_ON_SCREEN_OFF,
+ )
}
}
}
@@ -204,7 +236,7 @@
view.onDozeAmountChanged(
transitionStep.value,
transitionStep.value,
- ANIMATION_UNLOCKED_SCREEN_OFF,
+ ANIMATE_APPEAR_ON_SCREEN_OFF,
)
}
}
@@ -214,11 +246,26 @@
suspend fun listenForLockscreenAodTransitions(scope: CoroutineScope): Job {
return scope.launch {
transitionInteractor.dozeAmountTransition.collect { transitionStep ->
- view.onDozeAmountChanged(
- transitionStep.value,
- transitionStep.value,
- UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN,
- )
+ if (transitionStep.transitionState == TransitionState.CANCELED) {
+ if (
+ transitionInteractor.startedKeyguardTransitionStep.first().to !=
+ KeyguardState.AOD
+ ) {
+ // If the next started transition isn't transitioning back to AOD, force
+ // doze amount to be 0f (as if the transition to the lockscreen completed).
+ view.onDozeAmountChanged(
+ 0f,
+ 0f,
+ UdfpsKeyguardViewLegacy.ANIMATION_NONE,
+ )
+ }
+ } else {
+ view.onDozeAmountChanged(
+ transitionStep.value,
+ transitionStep.value,
+ UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN,
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
index f4ed8ce..6d4eea8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
@@ -133,7 +133,7 @@
// if we're animating from screen off, we can immediately place the icon in the
// AoD-burn in location, else we need to translate the icon from LS => AoD.
- final float darkAmountForAnimation = mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF
+ final float darkAmountForAnimation = mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF
? 1f : mInterpolatedDarkAmount;
final float burnInOffsetX = MathUtils.lerp(0f,
getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
@@ -171,7 +171,7 @@
mAnimationType == ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN
&& (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f);
final boolean doneAnimatingUnlockedScreenOff =
- mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF
+ mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF
&& (mInterpolatedDarkAmount == 1f);
if (doneAnimatingBetweenAodAndLS || doneAnimatingUnlockedScreenOff) {
mAnimationType = ANIMATION_NONE;
@@ -243,10 +243,10 @@
static final int ANIMATION_NONE = 0;
static final int ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN = 1;
- static final int ANIMATION_UNLOCKED_SCREEN_OFF = 2;
+ static final int ANIMATE_APPEAR_ON_SCREEN_OFF = 2;
@Retention(RetentionPolicy.SOURCE)
- @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATION_UNLOCKED_SCREEN_OFF})
+ @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATE_APPEAR_ON_SCREEN_OFF})
private @interface AnimationType {}
void onDozeAmountChanged(float linear, float eased, @AnimationType int animationType) {
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
index 17bf1a7..b78b1f1 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
@@ -16,16 +16,11 @@
package com.android.systemui.bluetooth;
-import android.annotation.Nullable;
-import android.content.Context;
import android.view.View;
-import com.android.internal.logging.UiEventLogger;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.animation.DialogLaunchAnimator;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.media.dialog.MediaOutputDialogFactory;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import javax.inject.Inject;
@@ -35,25 +30,15 @@
@SysUISingleton
public class BroadcastDialogController {
- private Context mContext;
- private UiEventLogger mUiEventLogger;
- private DialogLaunchAnimator mDialogLaunchAnimator;
- private MediaOutputDialogFactory mMediaOutputDialogFactory;
- private final LocalBluetoothManager mLocalBluetoothManager;
- private BroadcastSender mBroadcastSender;
+ private final DialogLaunchAnimator mDialogLaunchAnimator;
+ private final BroadcastDialogDelegate.Factory mBroadcastDialogFactory;
@Inject
- public BroadcastDialogController(Context context, UiEventLogger uiEventLogger,
+ public BroadcastDialogController(
DialogLaunchAnimator dialogLaunchAnimator,
- MediaOutputDialogFactory mediaOutputDialogFactory,
- @Nullable LocalBluetoothManager localBluetoothManager,
- BroadcastSender broadcastSender) {
- mContext = context;
- mUiEventLogger = uiEventLogger;
+ BroadcastDialogDelegate.Factory broadcastDialogFactory) {
mDialogLaunchAnimator = dialogLaunchAnimator;
- mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mLocalBluetoothManager = localBluetoothManager;
- mBroadcastSender = broadcastSender;
+ mBroadcastDialogFactory = broadcastDialogFactory;
}
/** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device
@@ -61,11 +46,10 @@
* @param currentBroadcastAppName Indicates the APP name currently broadcasting
* @param outputPkgName Indicates the output media package name to be switched
*/
- public void createBroadcastDialog(String currentBroadcastAppName, String outputPkgName,
- boolean aboveStatusBar, View view) {
- BroadcastDialog broadcastDialog = new BroadcastDialog(mContext, mMediaOutputDialogFactory,
- mLocalBluetoothManager, currentBroadcastAppName, outputPkgName, mUiEventLogger,
- mBroadcastSender);
+ public void createBroadcastDialog(
+ String currentBroadcastAppName, String outputPkgName, View view) {
+ SystemUIDialog broadcastDialog = mBroadcastDialogFactory.create(
+ currentBroadcastAppName, outputPkgName).createDialog();
if (view != null) {
mDialogLaunchAnimator.showFromView(broadcastDialog, view);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
similarity index 77%
rename from packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
rename to packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
index 00e9527..00bbb20 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,8 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Dialog;
import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.content.Context;
@@ -26,7 +28,6 @@
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.Button;
@@ -38,39 +39,47 @@
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.media.MediaOutputConstants;
-import com.android.systemui.res.R;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.media.controls.util.MediaDataUtils;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
+
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
/**
* Dialog for showing le audio broadcasting dialog.
*/
-public class BroadcastDialog extends SystemUIDialog {
+public class BroadcastDialogDelegate implements SystemUIDialog.Delegate {
private static final String TAG = "BroadcastDialog";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int HANDLE_BROADCAST_FAILED_DELAY = 3000;
+ private static final String CURRENT_BROADCAST_APP = "current_broadcast_app";
+ private static final String OUTPUT_PKG_NAME = "output_pkg_name";
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
- private Context mContext;
- private UiEventLogger mUiEventLogger;
- @VisibleForTesting
- protected View mDialogView;
- private MediaOutputDialogFactory mMediaOutputDialogFactory;
- private LocalBluetoothManager mLocalBluetoothManager;
- private BroadcastSender mBroadcastSender;
- private String mCurrentBroadcastApp;
- private String mOutputPackageName;
- private Executor mExecutor;
+ private final Context mContext;
+ private final UiEventLogger mUiEventLogger;
+ private final MediaOutputDialogFactory mMediaOutputDialogFactory;
+ private final LocalBluetoothManager mLocalBluetoothManager;
+ private final BroadcastSender mBroadcastSender;
+ private final SystemUIDialog.Factory mSystemUIDialogFactory;
+ private final String mCurrentBroadcastApp;
+ private final String mOutputPackageName;
+ private final Executor mExecutor;
private boolean mShouldLaunchLeBroadcastDialog;
private Button mSwitchBroadcast;
+ private final Set<SystemUIDialog> mDialogs = new HashSet<>();
+
private final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
@@ -136,43 +145,64 @@
}
};
- public BroadcastDialog(Context context, MediaOutputDialogFactory mediaOutputDialogFactory,
- LocalBluetoothManager localBluetoothManager, String currentBroadcastApp,
- String outputPkgName, UiEventLogger uiEventLogger, BroadcastSender broadcastSender) {
- super(context);
- if (DEBUG) {
- Log.d(TAG, "Init BroadcastDialog");
- }
+ @AssistedFactory
+ public interface Factory {
+ BroadcastDialogDelegate create(
+ @Assisted(CURRENT_BROADCAST_APP) String currentBroadcastApp,
+ @Assisted(OUTPUT_PKG_NAME) String outputPkgName
+ );
+ }
- mContext = getContext();
+ @AssistedInject
+ BroadcastDialogDelegate(
+ Context context,
+ MediaOutputDialogFactory mediaOutputDialogFactory,
+ @Nullable LocalBluetoothManager localBluetoothManager,
+ UiEventLogger uiEventLogger,
+ Executor executor,
+ BroadcastSender broadcastSender,
+ SystemUIDialog.Factory systemUIDialogFactory,
+ @Assisted(CURRENT_BROADCAST_APP) String currentBroadcastApp,
+ @Assisted(OUTPUT_PKG_NAME) String outputPkgName) {
+ mContext = context;
mMediaOutputDialogFactory = mediaOutputDialogFactory;
mLocalBluetoothManager = localBluetoothManager;
+ mSystemUIDialogFactory = systemUIDialogFactory;
mCurrentBroadcastApp = currentBroadcastApp;
mOutputPackageName = outputPkgName;
mUiEventLogger = uiEventLogger;
- mExecutor = Executors.newSingleThreadExecutor();
+ mExecutor = executor;
mBroadcastSender = broadcastSender;
+
+ if (DEBUG) {
+ Log.d(TAG, "Init BroadcastDialog");
+ }
}
@Override
- public void start() {
+ public SystemUIDialog createDialog() {
+ return mSystemUIDialogFactory.create(this);
+ }
+
+ @Override
+ public void onStart(SystemUIDialog dialog) {
+ mDialogs.add(dialog);
registerBroadcastCallBack(mExecutor, mBroadcastCallback);
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onCreate(SystemUIDialog dialog, Bundle savedInstanceState) {
if (DEBUG) {
Log.d(TAG, "onCreate");
}
mUiEventLogger.log(BroadcastDialogEvent.BROADCAST_DIALOG_SHOW);
- mDialogView = LayoutInflater.from(mContext).inflate(R.layout.broadcast_dialog, null);
- final Window window = getWindow();
- window.setContentView(mDialogView);
+ View dialogView = dialog.getLayoutInflater().inflate(R.layout.broadcast_dialog, null);
+ final Window window = dialog.getWindow();
+ window.setContentView(dialogView);
- TextView title = mDialogView.requireViewById(R.id.dialog_title);
- TextView subTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
+ TextView title = dialogView.requireViewById(R.id.dialog_title);
+ TextView subTitle = dialogView.requireViewById(R.id.dialog_subtitle);
title.setText(mContext.getString(
R.string.bt_le_audio_broadcast_dialog_title, mCurrentBroadcastApp));
String switchBroadcastApp = MediaDataUtils.getAppLabel(mContext, mOutputPackageName,
@@ -180,27 +210,28 @@
subTitle.setText(mContext.getString(
R.string.bt_le_audio_broadcast_dialog_sub_title, switchBroadcastApp));
- mSwitchBroadcast = mDialogView.requireViewById(R.id.switch_broadcast);
- Button changeOutput = mDialogView.requireViewById(R.id.change_output);
- Button cancelBtn = mDialogView.requireViewById(R.id.cancel);
+ mSwitchBroadcast = dialogView.requireViewById(R.id.switch_broadcast);
+ Button changeOutput = dialogView.requireViewById(R.id.change_output);
+ Button cancelBtn = dialogView.requireViewById(R.id.cancel);
mSwitchBroadcast.setText(mContext.getString(
R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp), null);
mSwitchBroadcast.setOnClickListener((view) -> startSwitchBroadcast());
changeOutput.setOnClickListener((view) -> {
mMediaOutputDialogFactory.create(mOutputPackageName, true, null);
- dismiss();
+ dialog.dismiss();
});
cancelBtn.setOnClickListener((view) -> {
if (DEBUG) {
Log.d(TAG, "BroadcastDialog dismiss.");
}
- dismiss();
+ dialog.dismiss();
});
}
@Override
- public void stop() {
+ public void onStop(SystemUIDialog dialog) {
unregisterBroadcastCallBack(mBroadcastCallback);
+ mDialogs.remove(dialog);
}
void refreshSwitchBroadcastButton() {
@@ -271,10 +302,9 @@
}
@Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- if (!hasFocus && isShowing()) {
- dismiss();
+ public void onWindowFocusChanged(SystemUIDialog dialog, boolean hasFocus) {
+ if (!hasFocus && dialog.isShowing()) {
+ dialog.dismiss();
}
}
@@ -333,6 +363,6 @@
.setPackage(mContext.getPackageName())
.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG)
.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, mOutputPackageName));
- dismiss();
+ mDialogs.forEach(Dialog::dismiss);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index 63b4288..e0ce3db 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -27,7 +27,7 @@
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
-import android.os.SystemProperties;
+import android.os.Build;
import android.provider.Settings;
import android.util.Log;
@@ -87,7 +87,7 @@
String clipSource = mClipboardManager.getPrimaryClipSource();
ClipData clipData = mClipboardManager.getPrimaryClip();
- if (shouldSuppressOverlay(clipData, clipSource, isEmulator())) {
+ if (shouldSuppressOverlay(clipData, clipSource, Build.IS_EMULATOR)) {
Log.i(TAG, "Clipboard overlay suppressed.");
return;
}
@@ -141,10 +141,6 @@
return true;
}
- private static boolean isEmulator() {
- return SystemProperties.getBoolean("ro.boot.qemu", false);
- }
-
private boolean isUserSetupComplete() {
return Settings.Secure.getInt(mContext.getContentResolver(),
SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 70736ae..bfc80a7 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -61,12 +61,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.res.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.res.R;
import com.android.systemui.screenshot.TimeoutHandler;
import java.util.Optional;
@@ -297,6 +297,7 @@
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_SHOWN_MINIMIZED);
mIsMinimized = true;
mView.setMinimized(true);
+ animateIn();
} else {
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_SHOWN_EXPANDED);
setExpandedView(this::animateIn);
@@ -318,8 +319,8 @@
} else {
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_SHOWN_EXPANDED);
setExpandedView();
- animateIn();
}
+ animateIn();
mView.announceForAccessibility(
getAccessibilityAnnouncement(mClipboardModel.getType()));
} else if (!mIsMinimized) {
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
new file mode 100644
index 0000000..3648f3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
@@ -0,0 +1,46 @@
+/*
+ * 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
+ */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.common.ui.domain.interactor
+
+import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.onStart
+
+/** Business logic related to configuration changes. */
+@SysUISingleton
+class ConfigurationInteractor @Inject constructor(private val repository: ConfigurationRepository) {
+ /** Given [resourceId], emit the dimension pixel size on config change */
+ fun dimensionPixelSize(resourceId: Int): Flow<Int> {
+ return onAnyConfigurationChange.mapLatest { repository.getDimensionPixelSize(resourceId) }
+ }
+
+ /** Given a set of [resourceId]s, emit Map<ResourceId, DimensionPixelSize> on config change */
+ fun dimensionPixelSize(resourceIds: Set<Int>): Flow<Map<Int, Int>> {
+ return onAnyConfigurationChange.mapLatest {
+ resourceIds.associateWith { repository.getDimensionPixelSize(it) }
+ }
+ }
+
+ /** Emit an event on any config change */
+ val onAnyConfigurationChange: Flow<Unit> =
+ repository.onAnyConfigurationChange.onStart { emit(Unit) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
index ad02f62..4219d6d6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
@@ -2,63 +2,16 @@
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.view.layout.sections.removeView
-import com.android.systemui.res.R
import javax.inject.Inject
/** A keyguard section that hosts the communal hub. */
-class DefaultCommunalHubSection
-@Inject
-constructor(
- private val viewModel: CommunalViewModel,
-) : KeyguardSection() {
- private val communalHubViewId = R.id.communal_hub
-
- override fun addViews(constraintLayout: ConstraintLayout) {
- constraintLayout.addView(
- ComposeFacade.createCommunalView(
- context = constraintLayout.context,
- viewModel = viewModel,
- )
- .apply { id = communalHubViewId },
- )
- }
+class DefaultCommunalHubSection @Inject constructor() : KeyguardSection() {
+ override fun addViews(constraintLayout: ConstraintLayout) {}
override fun bindData(constraintLayout: ConstraintLayout) {}
- override fun applyConstraints(constraintSet: ConstraintSet) {
- constraintSet.apply {
- connect(
- communalHubViewId,
- ConstraintSet.START,
- ConstraintSet.PARENT_ID,
- ConstraintSet.START,
- )
- connect(
- communalHubViewId,
- ConstraintSet.TOP,
- ConstraintSet.PARENT_ID,
- ConstraintSet.TOP,
- )
- connect(
- communalHubViewId,
- ConstraintSet.END,
- ConstraintSet.PARENT_ID,
- ConstraintSet.END,
- )
- connect(
- communalHubViewId,
- ConstraintSet.BOTTOM,
- ConstraintSet.PARENT_ID,
- ConstraintSet.BOTTOM,
- )
- }
- }
+ override fun applyConstraints(constraintSet: ConstraintSet) {}
- override fun removeViews(constraintLayout: ConstraintLayout) {
- constraintLayout.removeView(communalHubViewId)
- }
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 4d8e893..bed4283 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -16,16 +16,22 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
+import android.os.SystemClock
+import android.view.MotionEvent
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
/** The base view model for the communal hub. */
abstract class BaseCommunalViewModel(
private val communalInteractor: CommunalInteractor,
+ private val shadeViewController: ShadeViewController,
+ private val powerManager: PowerManager,
val mediaHost: MediaHost,
) {
val isKeyguardVisible: Flow<Boolean> = communalInteractor.isKeyguardVisible
@@ -36,6 +42,26 @@
communalInteractor.onSceneChanged(scene)
}
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't block
+ // touches anymore.
+ /** Called when a touch is received outside the edge swipe area when hub mode is closed. */
+ fun onOuterTouch(motionEvent: MotionEvent) {
+ // Forward the touch to the shade so that basic gestures like swipe up/down for
+ // shade/bouncer work.
+ shadeViewController.handleExternalTouch(motionEvent)
+ }
+
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't block
+ // touches anymore.
+ /** Called to refresh the screen timeout when a user touch is received. */
+ fun onUserActivity() {
+ powerManager.userActivity(
+ SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_TOUCH,
+ 0
+ )
+ }
+
/** A list of all the communal content to be displayed in the communal hub. */
abstract val communalContent: Flow<List<CommunalContentModel>>
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
index 111f8b4..b6843c5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
@@ -16,11 +16,13 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.dagger.MediaModule
+import com.android.systemui.shade.ShadeViewController
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.flow.Flow
@@ -31,8 +33,10 @@
@Inject
constructor(
private val communalInteractor: CommunalInteractor,
+ shadeViewController: ShadeViewController,
+ powerManager: PowerManager,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
-) : BaseCommunalViewModel(communalInteractor, mediaHost) {
+) : BaseCommunalViewModel(communalInteractor, shadeViewController, powerManager, mediaHost) {
override val isEditMode = true
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 11bde6b..d7dcdb9 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -16,12 +16,14 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.dagger.MediaModule
+import com.android.systemui.shade.ShadeViewController
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -37,8 +39,10 @@
constructor(
private val communalInteractor: CommunalInteractor,
tutorialInteractor: CommunalTutorialInteractor,
+ shadeViewController: ShadeViewController,
+ powerManager: PowerManager,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
-) : BaseCommunalViewModel(communalInteractor, mediaHost) {
+) : BaseCommunalViewModel(communalInteractor, shadeViewController, powerManager, mediaHost) {
@OptIn(ExperimentalCoroutinesApi::class)
override val communalContent: Flow<List<CommunalContentModel>> =
tutorialInteractor.isTutorialAvailable.flatMapLatest { isTutorialMode ->
diff --git a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogActivity.kt b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogActivity.kt
index 70d7138..4e40042 100644
--- a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogActivity.kt
@@ -16,31 +16,19 @@
package com.android.systemui.contrast
import android.app.Activity
-import android.app.UiModeManager
-import android.content.Context
import android.os.Bundle
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.util.settings.SecureSettings
-import java.util.concurrent.Executor
import javax.inject.Inject
-/** Trampoline activity responsible for creating a [ContrastDialog] */
+/** Trampoline activity responsible for creating a [ContrastDialogDelegate] */
class ContrastDialogActivity
@Inject
constructor(
- private val context: Context,
- @Main private val mainExecutor: Executor,
- private val uiModeManager: UiModeManager,
- private val userTracker: UserTracker,
- private val secureSettings: SecureSettings
+ private val contrastDialogDelegate : ContrastDialogDelegate
) : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val contrastDialog =
- ContrastDialog(context, mainExecutor, uiModeManager, userTracker, secureSettings)
- contrastDialog.show()
+ contrastDialogDelegate.createDialog().show()
finish()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialog.kt b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
similarity index 67%
rename from packages/SystemUI/src/com/android/systemui/contrast/ContrastDialog.kt
rename to packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
index e9b5930..63b01ed 100644
--- a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
@@ -21,54 +21,58 @@
import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD
import android.app.UiModeManager.ContrastUtils.fromContrastLevel
import android.app.UiModeManager.ContrastUtils.toContrastLevel
-import android.content.Context
import android.os.Bundle
import android.provider.Settings
-import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.res.R
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.settings.SecureSettings
import java.util.concurrent.Executor
+import javax.inject.Inject
/** Dialog to select contrast options */
-class ContrastDialog(
- context: Context?,
+class ContrastDialogDelegate @Inject constructor(
+ private val sysuiDialogFactory : SystemUIDialog.Factory,
@Main private val mainExecutor: Executor,
private val uiModeManager: UiModeManager,
private val userTracker: UserTracker,
private val secureSettings: SecureSettings,
-) : SystemUIDialog(context), UiModeManager.ContrastChangeListener {
+) : SystemUIDialog.Delegate, UiModeManager.ContrastChangeListener {
+
+ override fun createDialog(): SystemUIDialog {
+ return sysuiDialogFactory.create(this)
+ }
@VisibleForTesting lateinit var contrastButtons: Map<Int, FrameLayout>
lateinit var dialogView: View
@VisibleForTesting var initialContrast: Float = fromContrastLevel(CONTRAST_LEVEL_STANDARD)
- public override fun onCreate(savedInstanceState: Bundle?) {
- dialogView = LayoutInflater.from(context).inflate(R.layout.contrast_dialog, null)
- setView(dialogView)
+ override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ dialogView = dialog.layoutInflater.inflate(R.layout.contrast_dialog, null)
+ with(dialog) {
+ setView(dialogView)
- setTitle(R.string.quick_settings_contrast_label)
- setNeutralButton(R.string.cancel) { _, _ ->
- secureSettings.putFloatForUser(
- Settings.Secure.CONTRAST_LEVEL,
- initialContrast,
- userTracker.userId
- )
- dismiss()
+ setTitle(R.string.quick_settings_contrast_label)
+ setNeutralButton(R.string.cancel) { _, _ ->
+ secureSettings.putFloatForUser(
+ Settings.Secure.CONTRAST_LEVEL,
+ initialContrast,
+ userTracker.userId
+ )
+ dialog.dismiss()
+ }
+ setPositiveButton(com.android.settingslib.R.string.done) { _, _ -> dialog.dismiss() }
}
- setPositiveButton(com.android.settingslib.R.string.done) { _, _ -> dismiss() }
- super.onCreate(savedInstanceState)
-
contrastButtons =
mapOf(
- CONTRAST_LEVEL_STANDARD to requireViewById(R.id.contrast_button_standard),
- CONTRAST_LEVEL_MEDIUM to requireViewById(R.id.contrast_button_medium),
- CONTRAST_LEVEL_HIGH to requireViewById(R.id.contrast_button_high)
+ CONTRAST_LEVEL_STANDARD to dialogView.requireViewById(
+ R.id.contrast_button_standard),
+ CONTRAST_LEVEL_MEDIUM to dialogView.requireViewById(R.id.contrast_button_medium),
+ CONTRAST_LEVEL_HIGH to dialogView.requireViewById(R.id.contrast_button_high)
)
contrastButtons.forEach { (contrastLevel, contrastButton) ->
@@ -86,11 +90,11 @@
highlightContrast(toContrastLevel(initialContrast))
}
- override fun start() {
+ override fun onStart(dialog: SystemUIDialog) {
uiModeManager.addContrastChangeListener(mainExecutor, this)
}
- override fun stop() {
+ override fun onStop(dialog: SystemUIDialog) {
uiModeManager.removeContrastChangeListener(this)
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index e7b8773..9672fac 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -36,8 +36,6 @@
import com.android.systemui.unfold.FoldStateLoggingProvider;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
-import com.android.systemui.unfold.dagger.UnfoldBg;
-import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.desktopmode.DesktopMode;
@@ -139,26 +137,19 @@
c.getUnfoldHapticsPlayer();
c.getNaturalRotationUnfoldProgressProvider().init();
c.getUnfoldLatencyTracker().init();
+ c.getFoldStateLoggingProvider()
+ .ifPresent(FoldStateLoggingProvider::init);
+ c.getFoldStateLogger().ifPresent(FoldStateLogger::init);
+ final UnfoldTransitionProgressProvider progressProvider =
+ Flags.unfoldAnimationBackgroundProgress()
+ ? c.getBgUnfoldTransitionProgressProvider()
+ : c.getUnfoldTransitionProgressProvider();
+ progressProvider.addCallback(c.getUnfoldTransitionProgressForwarder());
});
// No init method needed, just needs to be gotten so that it's created.
getMediaMuteAwaitConnectionCli();
getNearbyMediaDevicesManager();
getConnectingDisplayViewModel().init();
- getFoldStateLoggingProvider().ifPresent(FoldStateLoggingProvider::init);
- getFoldStateLogger().ifPresent(FoldStateLogger::init);
-
- Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider;
-
- if (Flags.unfoldAnimationBackgroundProgress()) {
- unfoldTransitionProgressProvider = getBgUnfoldTransitionProgressProvider();
- } else {
- unfoldTransitionProgressProvider = getUnfoldTransitionProgressProvider();
- }
- unfoldTransitionProgressProvider
- .ifPresent(
- (progressProvider) ->
- getUnfoldTransitionProgressForwarder()
- .ifPresent(progressProvider::addCallback));
}
/**
@@ -180,37 +171,6 @@
ContextComponentHelper getContextComponentHelper();
/**
- * Creates a UnfoldTransitionProgressProvider that calculates progress in the background.
- */
- @SysUISingleton
- @UnfoldBg
- Optional<UnfoldTransitionProgressProvider> getBgUnfoldTransitionProgressProvider();
-
- /**
- * Creates a UnfoldTransitionProgressProvider that calculates progress in the main thread.
- */
- @SysUISingleton
- Optional<UnfoldTransitionProgressProvider> getUnfoldTransitionProgressProvider();
-
- /**
- * Creates a UnfoldTransitionProgressForwarder.
- */
- @SysUISingleton
- Optional<UnfoldTransitionProgressForwarder> getUnfoldTransitionProgressForwarder();
-
- /**
- * Creates a FoldStateLoggingProvider.
- */
- @SysUISingleton
- Optional<FoldStateLoggingProvider> getFoldStateLoggingProvider();
-
- /**
- * Creates a FoldStateLogger.
- */
- @SysUISingleton
- Optional<FoldStateLogger> getFoldStateLogger();
-
- /**
* Main dependency providing module.
*/
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
index 4bfc9484..615b503 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
@@ -34,7 +34,6 @@
import com.android.systemui.biometrics.AuthController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import java.util.concurrent.Executor
@@ -48,7 +47,6 @@
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@Main private val mainExecutor: Executor,
private val logger: ScreenDecorationsLogger,
- private val featureFlags: FeatureFlags,
) : DecorProviderFactory() {
private val display = context.display
private val displayInfo = DisplayInfo()
@@ -88,7 +86,6 @@
keyguardUpdateMonitor,
mainExecutor,
logger,
- featureFlags,
)
)
}
@@ -113,7 +110,6 @@
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val mainExecutor: Executor,
private val logger: ScreenDecorationsLogger,
- private val featureFlags: FeatureFlags,
) : BoundDecorProvider() {
override val viewId: Int = com.android.systemui.res.R.id.face_scanning_anim
@@ -148,7 +144,6 @@
mainExecutor,
logger,
authController,
- featureFlags
)
view.id = viewId
view.setColor(tintColor)
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index ff65b31..7cb2c6e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -253,12 +253,6 @@
val KEYGUARD_WM_STATE_REFACTOR: UnreleasedFlag =
unreleasedFlag("keyguard_wm_state_refactor")
- /** Flag to disable the face scanning animation pulsing. */
- // TODO(b/295245791): Tracking bug.
- @JvmField val STOP_PULSING_FACE_SCANNING_ANIMATION = resourceBooleanFlag(
- R.bool.flag_stop_pulsing_face_scanning_animation,
- "stop_pulsing_face_scanning_animation")
-
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag("power_menu_lite")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index c8c06ae..01ba0d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -41,6 +41,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.Flags.fastUnlockTransition
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.shared.recents.utilities.Utilities
import com.android.systemui.shared.system.ActivityManagerWrapper
@@ -98,7 +99,8 @@
* from a tap on the unlock icon, or from the bouncer. This is not relevant if the lockscreen is
* swiped away via a touch gesture, or when it's flinging expanded/collapsed after a swipe.
*/
-const val UNLOCK_ANIMATION_DURATION_MS = 200L
+const val LEGACY_UNLOCK_ANIMATION_DURATION_MS = 200L
+const val UNLOCK_ANIMATION_DURATION_MS = 167L
/**
* How long the in-window launcher icon animation takes. This is used if the launcher is underneath
@@ -112,19 +114,22 @@
/**
* How long to wait for the shade to get out of the way before starting the canned unlock animation.
*/
-const val CANNED_UNLOCK_START_DELAY = 100L
+const val LEGACY_CANNED_UNLOCK_START_DELAY = 100L
+const val CANNED_UNLOCK_START_DELAY = 67L
/**
* Duration for the alpha animation on the surface behind. This plays to fade in the surface during
* a swipe to unlock (and to fade it back out if the swipe is cancelled).
*/
-const val SURFACE_BEHIND_SWIPE_FADE_DURATION_MS = 175L
+const val LEGACY_SURFACE_BEHIND_SWIPE_FADE_DURATION_MS = 175L
+const val SURFACE_BEHIND_FADE_OUT_DURATION_MS = 83L
/**
* Start delay for the surface behind animation, used so that the lockscreen can get out of the way
* before the surface begins appearing.
*/
-const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
+const val LEGACY_UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
+const val SURFACE_BEHIND_FADE_OUT_START_DELAY_MS = 0L
/**
* Initiates, controls, and ends the keyguard unlock animation.
@@ -327,7 +332,7 @@
init {
with(surfaceBehindAlphaAnimator) {
- duration = SURFACE_BEHIND_SWIPE_FADE_DURATION_MS
+ duration = surfaceBehindFadeOutDurationMs()
interpolator = Interpolators.LINEAR
addUpdateListener { valueAnimator: ValueAnimator ->
surfaceBehindAlpha = valueAnimator.animatedValue as Float
@@ -355,8 +360,10 @@
}
with(wallpaperCannedUnlockAnimator) {
- duration = LAUNCHER_ICONS_ANIMATION_DURATION_MS
- interpolator = Interpolators.ALPHA_OUT
+ duration = if (fastUnlockTransition()) UNLOCK_ANIMATION_DURATION_MS
+ else LAUNCHER_ICONS_ANIMATION_DURATION_MS
+ interpolator = if (fastUnlockTransition()) Interpolators.LINEAR
+ else Interpolators.ALPHA_OUT
addUpdateListener { valueAnimator: ValueAnimator ->
setWallpaperAppearAmount(valueAnimator.animatedValue as Float)
}
@@ -370,8 +377,8 @@
}
with(surfaceBehindEntryAnimator) {
- duration = UNLOCK_ANIMATION_DURATION_MS
- startDelay = UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS
+ duration = unlockAnimationDurationMs()
+ startDelay = surfaceBehindFadeOutStartDelayMs()
interpolator = Interpolators.TOUCH_RESPONSE
addUpdateListener { valueAnimator: ValueAnimator ->
surfaceBehindAlpha = valueAnimator.animatedValue as Float
@@ -573,7 +580,7 @@
try {
launcherUnlockController?.playUnlockAnimation(
true,
- UNLOCK_ANIMATION_DURATION_MS + CANNED_UNLOCK_START_DELAY,
+ unlockAnimationDurationMs() + cannedUnlockStartDelayMs(),
0 /* startDelay */)
} catch (e: DeadObjectException) {
// Hello! If you are here investigating a bug where Launcher is blank (no icons)
@@ -602,12 +609,15 @@
// Notify if waking from AOD only
val isWakeAndUnlockNotFromDream = biometricUnlockControllerLazy.get().isWakeAndUnlock &&
biometricUnlockControllerLazy.get().mode != MODE_WAKE_AND_UNLOCK_FROM_DREAM
+
+ val duration = if (fastUnlockTransition()) UNLOCK_ANIMATION_DURATION_MS
+ else LAUNCHER_ICONS_ANIMATION_DURATION_MS
listeners.forEach {
it.onUnlockAnimationStarted(
playingCannedUnlockAnimation /* playingCannedAnimation */,
isWakeAndUnlockNotFromDream /* isWakeAndUnlockNotFromDream */,
- CANNED_UNLOCK_START_DELAY /* unlockStartDelay */,
- LAUNCHER_ICONS_ANIMATION_DURATION_MS /* unlockAnimationDuration */) }
+ cannedUnlockStartDelayMs() /* unlockStartDelay */,
+ duration /* unlockAnimationDuration */) }
// Finish the keyguard remote animation if the dismiss amount has crossed the threshold.
// Check it here in case there is no more change to the dismiss amount after the last change
@@ -675,7 +685,7 @@
launcherUnlockController?.playUnlockAnimation(
true /* unlocked */,
LAUNCHER_ICONS_ANIMATION_DURATION_MS /* duration */,
- CANNED_UNLOCK_START_DELAY /* startDelay */)
+ cannedUnlockStartDelayMs() /* startDelay */)
} catch (e: DeadObjectException) {
// Hello! If you are here investigating a bug where Launcher is blank (no icons)
// then the below assumption about Launcher's destruction was incorrect. This
@@ -696,9 +706,10 @@
lockscreenSmartspace?.visibility = View.INVISIBLE
}
- // As soon as the shade has animated out of the way, start the canned unlock animation,
+ // As soon as the shade starts animating out of the way, start the canned unlock animation,
// which will finish keyguard exit when it completes. The in-window animations in the
// Launcher window will end on their own.
+ if (fastUnlockTransition()) hideKeyguardViewAfterRemoteAnimation()
handler.postDelayed({
if (keyguardViewMediator.get().isShowingAndNotOccluded &&
!keyguardStateController.isKeyguardGoingAway) {
@@ -709,12 +720,12 @@
if ((wallpaperTargets?.isNotEmpty() == true)) {
fadeInWallpaper()
- hideKeyguardViewAfterRemoteAnimation()
+ if (!fastUnlockTransition()) hideKeyguardViewAfterRemoteAnimation()
} else {
keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
}
- }, CANNED_UNLOCK_START_DELAY)
+ }, cannedUnlockStartDelayMs())
}
/**
@@ -1130,6 +1141,43 @@
?: false
}
+ /**
+ * Temporary method for b/298186160
+ * TODO (b/298186160) replace references with the constant itself when flag is removed
+ */
+ private fun cannedUnlockStartDelayMs(): Long {
+ return if (fastUnlockTransition()) CANNED_UNLOCK_START_DELAY
+ else LEGACY_CANNED_UNLOCK_START_DELAY
+ }
+
+ /**
+ * Temporary method for b/298186160
+ * TODO (b/298186160) replace references with the constant itself when flag is removed
+ */
+ private fun unlockAnimationDurationMs(): Long {
+ return if (fastUnlockTransition()) UNLOCK_ANIMATION_DURATION_MS
+ else LEGACY_UNLOCK_ANIMATION_DURATION_MS
+ }
+
+ /**
+ * Temporary method for b/298186160
+ * TODO (b/298186160) replace references with the constant itself when flag is removed
+ */
+ private fun surfaceBehindFadeOutDurationMs(): Long {
+ return if (fastUnlockTransition()) SURFACE_BEHIND_FADE_OUT_DURATION_MS
+ else LEGACY_SURFACE_BEHIND_SWIPE_FADE_DURATION_MS
+ }
+
+ /**
+ * Temporary method for b/298186160
+ * TODO (b/298186160) replace references with the constant itself when flag is removed
+ */
+ private fun surfaceBehindFadeOutStartDelayMs(): Long {
+ return if (fastUnlockTransition()) SURFACE_BEHIND_FADE_OUT_START_DELAY_MS
+ else LEGACY_UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS
+ }
+
+
companion object {
fun isFoldable(context: Context): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 36412e3..e47c448 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -187,8 +187,7 @@
faceManager?.sensorPropertiesInternal?.firstOrNull()?.supportsFaceDetection ?: false
private val _isAuthRunning = MutableStateFlow(false)
- override val isAuthRunning: StateFlow<Boolean>
- get() = _isAuthRunning
+ override val isAuthRunning: StateFlow<Boolean> = _isAuthRunning
private val keyguardSessionId: InstanceId?
get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)
@@ -254,6 +253,13 @@
)
.andAllFlows("canFaceAuthRun", faceAuthLog)
.flowOn(backgroundDispatcher)
+ .onEach {
+ faceAuthLogger.canFaceAuthRunChanged(it)
+ if (!it) {
+ // Cancel currently running auth if any of the gating checks are false.
+ cancel()
+ }
+ }
.stateIn(applicationScope, SharingStarted.Eagerly, false)
// Face detection can run only when lockscreen bypass is enabled
@@ -281,9 +287,12 @@
)
.andAllFlows("canFaceDetectRun", faceDetectLog)
.flowOn(backgroundDispatcher)
+ .onEach {
+ if (!it) {
+ cancelDetection()
+ }
+ }
.stateIn(applicationScope, SharingStarted.Eagerly, false)
- observeFaceAuthGatingChecks()
- observeFaceDetectGatingChecks()
observeFaceAuthResettingConditions()
listenForSchedulingWatchdog()
processPendingAuthRequests()
@@ -317,6 +326,7 @@
it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
},
)
+ .flowOn(backgroundDispatcher)
.onEach { anyOfThemIsTrue ->
if (anyOfThemIsTrue) {
clearPendingAuthRequest("Resetting auth status")
@@ -337,17 +347,6 @@
pendingAuthenticateRequest.value = null
}
- private fun observeFaceDetectGatingChecks() {
- canRunDetection
- .onEach {
- if (!it) {
- cancelDetection()
- }
- }
- .flowOn(mainDispatcher)
- .launchIn(applicationScope)
- }
-
private fun isUdfps() =
deviceEntryFingerprintAuthRepository.availableFpSensorType.map {
it == BiometricType.UNDER_DISPLAY_FINGERPRINT
@@ -406,20 +405,6 @@
)
}
- private fun observeFaceAuthGatingChecks() {
- canRunFaceAuth
- .onEach {
- faceAuthLogger.canFaceAuthRunChanged(it)
- if (!it) {
- // Cancel currently running auth if any of the gating checks are false.
- faceAuthLogger.cancellingFaceAuth()
- cancel()
- }
- }
- .flowOn(mainDispatcher)
- .launchIn(applicationScope)
- }
-
private val faceAuthCallback =
object : FaceManager.AuthenticationCallback() {
override fun onAuthenticationFailed() {
@@ -554,7 +539,7 @@
authenticate(it.uiEvent, it.fallbackToDetection)
}
}
- .flowOn(mainDispatcher)
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
}
@@ -650,6 +635,7 @@
override fun cancel() {
if (authCancellationSignal == null) return
+ faceAuthLogger.cancellingFaceAuth()
authCancellationSignal?.cancel()
cancelNotReceivedHandlerJob?.cancel()
cancelNotReceivedHandlerJob =
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 d1c6218..5e3779a 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
@@ -19,34 +19,71 @@
import android.os.UserHandle
import android.provider.Settings
import androidx.annotation.VisibleForTesting
-import com.android.keyguard.KeyguardClockSwitch.SMALL
+import com.android.keyguard.ClockEventController
+import com.android.keyguard.KeyguardClockSwitch.ClockSize
+import com.android.keyguard.KeyguardClockSwitch.LARGE
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.shared.model.SettingsClockSize
-import com.android.systemui.plugins.ClockId
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.shared.clocks.ClockRegistry
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
+interface KeyguardClockRepository {
+ /** clock size determined by notificationPanelViewController, LARGE or SMALL */
+ val clockSize: StateFlow<Int>
+
+ /** clock size selected in picker, DYNAMIC or SMALL */
+ val selectedClockSize: Flow<SettingsClockSize>
+
+ /** clock id, selected from clock carousel in wallpaper picker */
+ val currentClockId: Flow<ClockId>
+
+ val currentClock: StateFlow<ClockController?>
+
+ val clockEventController: ClockEventController
+ fun setClockSize(@ClockSize size: Int)
+}
+
@SysUISingleton
-class KeyguardClockRepository
+class KeyguardClockRepositoryImpl
@Inject
constructor(
private val secureSettings: SecureSettings,
private val clockRegistry: ClockRegistry,
+ override val clockEventController: ClockEventController,
@Background private val backgroundDispatcher: CoroutineDispatcher,
-) {
+ @Application private val applicationScope: CoroutineScope,
+) : KeyguardClockRepository {
- val selectedClockSize: Flow<SettingsClockSize> =
+ /** Receive SMALL or LARGE clock should be displayed on keyguard. */
+ private val _clockSize: MutableStateFlow<Int> = MutableStateFlow(LARGE)
+ override val clockSize: StateFlow<Int> = _clockSize.asStateFlow()
+
+ override fun setClockSize(size: Int) {
+ _clockSize.value = size
+ }
+
+ override val selectedClockSize: Flow<SettingsClockSize> =
secureSettings
.observerFlow(
names = arrayOf(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
@@ -55,7 +92,7 @@
.onStart { emit(Unit) } // Forces an initial update.
.map { getClockSize() }
- val currentClockId: Flow<ClockId> =
+ override val currentClockId: Flow<ClockId> =
callbackFlow {
fun send() {
trySend(clockRegistry.currentClockId)
@@ -72,8 +109,16 @@
awaitClose { clockRegistry.unregisterClockChangeListener(listener) }
}
.mapNotNull { it }
+ .distinctUntilChanged()
- val currentClock = currentClockId.map { clockRegistry.createCurrentClock() }
+ override val currentClock: StateFlow<ClockController?> =
+ currentClockId
+ .map { clockRegistry.createCurrentClock() }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = clockRegistry.createCurrentClock()
+ )
@VisibleForTesting
suspend fun getClockSize(): SettingsClockSize {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 6ff446e..2d6c0e1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -18,8 +18,6 @@
import android.graphics.Point
import android.hardware.biometrics.BiometricSourceType
-import com.android.keyguard.KeyguardClockSwitch.ClockSize
-import com.android.keyguard.KeyguardClockSwitch.LARGE
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.biometrics.AuthController
@@ -39,7 +37,6 @@
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -180,9 +177,6 @@
/** Whether quick settings or quick-quick settings is visible. */
val isQuickSettingsVisible: Flow<Boolean>
- /** Represents the current state of the KeyguardRootView visibility */
- val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState>
-
/** Receive an event for doze time tick */
val dozeTimeTick: Flow<Long>
@@ -192,9 +186,6 @@
/** Observable updated when keyguardDone should be called either now or soon. */
val keyguardDone: Flow<KeyguardDone>
- /** Receive SMALL or LARGE clock should be displayed on keyguard. */
- val clockSize: Flow<Int>
-
/** Receive whether clock should be centered on lockscreen. */
val clockShouldBeCentered: Flow<Boolean>
@@ -216,12 +207,6 @@
/** Sets the current amount of alpha that should be used for rendering the keyguard. */
fun setKeyguardAlpha(alpha: Float)
- fun setKeyguardVisibility(
- statusBarState: Int,
- goingToFullShade: Boolean,
- occlusionTransitionRunning: Boolean
- )
-
/**
* Sets the relative offset of the lock-screen clock from its natural position on the screen.
*/
@@ -247,8 +232,6 @@
suspend fun setKeyguardDone(keyguardDoneType: KeyguardDone)
- fun setClockSize(@ClockSize size: Int)
-
fun setClockShouldBeCentered(shouldBeCentered: Boolean)
}
@@ -293,9 +276,6 @@
private val _clockPosition = MutableStateFlow(Position(0, 0))
override val clockPosition = _clockPosition.asStateFlow()
- private val _clockSize = MutableStateFlow(LARGE)
- override val clockSize: Flow<Int> = _clockSize.asStateFlow()
-
private val _clockShouldBeCentered = MutableStateFlow(true)
override val clockShouldBeCentered: Flow<Boolean> = _clockShouldBeCentered.asStateFlow()
@@ -631,17 +611,6 @@
private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
override val isActiveDreamLockscreenHosted = _isActiveDreamLockscreenHosted.asStateFlow()
- private val _keyguardRootViewVisibility =
- MutableStateFlow(
- KeyguardRootViewVisibilityState(
- com.android.systemui.statusbar.StatusBarState.SHADE,
- goingToFullShade = false,
- occlusionTransitionRunning = false,
- )
- )
- override val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState> =
- _keyguardRootViewVisibility.asStateFlow()
-
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate
}
@@ -654,19 +623,6 @@
_keyguardAlpha.value = alpha
}
- override fun setKeyguardVisibility(
- statusBarState: Int,
- goingToFullShade: Boolean,
- occlusionTransitionRunning: Boolean
- ) {
- _keyguardRootViewVisibility.value =
- KeyguardRootViewVisibilityState(
- statusBarState,
- goingToFullShade,
- occlusionTransitionRunning
- )
- }
-
override fun setClockPosition(x: Int, y: Int) {
_clockPosition.value = Position(x, y)
}
@@ -681,10 +637,6 @@
_isActiveDreamLockscreenHosted.value = isLockscreenHosted
}
- override fun setClockSize(@ClockSize size: Int) {
- _clockSize.value = size
- }
-
override fun setClockShouldBeCentered(shouldBeCentered: Boolean) {
_clockShouldBeCentered.value = shouldBeCentered
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 5659623..6138330 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -74,4 +74,6 @@
fun bind(impl: BouncerMessageAuditLogger): CoreStartable
@Binds fun trustRepository(impl: TrustRepositoryImpl): TrustRepository
+
+ @Binds fun keyguardClockRepository(impl: KeyguardClockRepositoryImpl): KeyguardClockRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 5c76be8..0e487d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -103,7 +103,7 @@
private val _transitions =
MutableSharedFlow<TransitionStep>(
replay = 2,
- extraBufferCapacity = 10,
+ extraBufferCapacity = 20,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
override val transitions = _transitions.asSharedFlow().distinctUntilChanged()
@@ -227,10 +227,7 @@
private fun emitTransition(nextStep: TransitionStep, isManual: Boolean = false) {
logAndTrace(nextStep, isManual)
- val emitted = _transitions.tryEmit(nextStep)
- if (!emitted) {
- Log.w(TAG, "Failed to emit next value without suspending")
- }
+ _transitions.tryEmit(nextStep)
lastStep = nextStep
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index 2f103f6..356c408 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -18,13 +18,15 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.keyguard.ClockEventController
+import com.android.keyguard.KeyguardClockSwitch.ClockSize
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
import com.android.systemui.keyguard.shared.model.SettingsClockSize
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockId
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockId
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
private val TAG = KeyguardClockInteractor::class.simpleName
/** Manages keyguard clock for the lockscreen root view. */
@@ -33,7 +35,6 @@
class KeyguardClockInteractor
@Inject
constructor(
- val eventController: ClockEventController,
private val keyguardClockRepository: KeyguardClockRepository,
) {
@@ -41,11 +42,17 @@
val currentClockId: Flow<ClockId> = keyguardClockRepository.currentClockId
- val currentClock: Flow<ClockController> = keyguardClockRepository.currentClock
+ val currentClock: StateFlow<ClockController?> = keyguardClockRepository.currentClock
- var clock: ClockController?
- get() = eventController.clock
- set(value) {
- eventController.clock = value
+ var clock: ClockController? by keyguardClockRepository.clockEventController::clock
+
+ val clockSize: StateFlow<Int> = keyguardClockRepository.clockSize
+ fun setClockSize(@ClockSize size: Int) {
+ keyguardClockRepository.setClockSize(size)
+ }
+
+ val clockEventController: ClockEventController
+ get() {
+ return keyguardClockRepository.clockEventController
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index e58d771..b8c3925 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -23,13 +23,12 @@
import android.graphics.Point
import android.util.MathUtils
import com.android.app.animation.Interpolators
-import com.android.keyguard.KeyguardClockSwitch.ClockSize
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.common.shared.model.Position
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
@@ -77,7 +76,7 @@
powerInteractor: PowerInteractor,
sceneContainerFlags: SceneContainerFlags,
bouncerRepository: KeyguardBouncerRepository,
- configurationRepository: ConfigurationRepository,
+ configurationInteractor: ConfigurationInteractor,
shadeRepository: ShadeRepository,
sceneInteractorProvider: Provider<SceneInteractor>,
) {
@@ -213,37 +212,29 @@
/** The approximate location on the screen of the face unlock sensor, if one is available. */
val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
- /** Notifies when a new configuration is set */
- val configurationChange: Flow<Unit> =
- configurationRepository.onAnyConfigurationChange.onStart { emit(Unit) }
-
/** The position of the keyguard clock. */
val clockPosition: Flow<Position> = repository.clockPosition
val keyguardAlpha: Flow<Float> = repository.keyguardAlpha
val keyguardTranslationY: Flow<Float> =
- configurationChange.flatMapLatest {
- val translationDistance =
- configurationRepository.getDimensionPixelSize(
- R.dimen.keyguard_translate_distance_on_swipe_up
- )
- shadeRepository.shadeModel.map {
- if (it.expansionAmount == 0f) {
- // Reset the translation value
- 0f
- } else {
- // On swipe up, translate the keyguard to reveal the bouncer
- MathUtils.lerp(
- translationDistance,
- 0,
- Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it.expansionAmount)
- )
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.keyguard_translate_distance_on_swipe_up)
+ .flatMapLatest { translationDistance ->
+ shadeRepository.shadeModel.map {
+ if (it.expansionAmount == 0f) {
+ // Reset the translation value
+ 0f
+ } else {
+ // On swipe up, translate the keyguard to reveal the bouncer
+ MathUtils.lerp(
+ translationDistance,
+ 0,
+ Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it.expansionAmount)
+ )
+ }
}
}
- }
-
- val clockSize: Flow<Int> = repository.clockSize.distinctUntilChanged()
val clockShouldBeCentered: Flow<Boolean> = repository.clockShouldBeCentered
@@ -297,18 +288,6 @@
repository.setQuickSettingsVisible(isVisible)
}
- fun setKeyguardRootVisibility(
- statusBarState: Int,
- goingToFullShade: Boolean,
- isOcclusionTransitionRunning: Boolean
- ) {
- repository.setKeyguardVisibility(
- statusBarState,
- goingToFullShade,
- isOcclusionTransitionRunning
- )
- }
-
fun setClockPosition(x: Int, y: Int) {
repository.setClockPosition(x, y)
}
@@ -321,10 +300,6 @@
repository.setAnimateDozingTransitions(animate)
}
- fun setClockSize(@ClockSize size: Int) {
- repository.setClockSize(size)
- }
-
fun setClockShouldBeCentered(shouldBeCentered: Boolean) {
repository.setClockShouldBeCentered(shouldBeCentered)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index ae356cd..532df4a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -29,6 +29,7 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
@@ -69,6 +70,7 @@
private val context: Context,
@Application private val applicationScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
private val repository: DeviceEntryFaceAuthRepository,
private val primaryBouncerInteractor: Lazy<PrimaryBouncerInteractor>,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
@@ -104,6 +106,7 @@
fallbackToDetect = false
)
}
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
alternateBouncerInteractor.isVisible
@@ -115,6 +118,7 @@
fallbackToDetect = false
)
}
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
merge(
@@ -143,6 +147,7 @@
fallbackToDetect = true
)
}
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
deviceEntryFingerprintAuthRepository.isLockedOut
@@ -155,6 +160,7 @@
}
}
}
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
// User switching should stop face auth and then when it is complete we should trigger face
@@ -178,6 +184,7 @@
)
}
}
+ .flowOn(backgroundDispatcher)
.launchIn(applicationScope)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardRootViewVisibilityState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardRootViewVisibilityState.kt
deleted file mode 100644
index 9a57aef..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardRootViewVisibilityState.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.keyguard.shared.model
-
-/**
- * Provides a stateful representation of the visibility of the KeyguardRootView
- *
- * @param statusBarState State of the status bar represented by [StatusBarState]
- * @param goingToFullShade Whether status bar is going to full shade
- * @param occlusionTransitionRunning Whether the occlusion transition is running in this instant
- */
-data class KeyguardRootViewVisibilityState(
- val statusBarState: Int,
- val goingToFullShade: Boolean,
- val occlusionTransitionRunning: Boolean,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index d5ad7ab..64ff3b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -17,97 +17,134 @@
import android.view.animation.Interpolator
import com.android.app.animation.Interpolators.LINEAR
+import com.android.keyguard.logging.KeyguardTransitionAnimationLogger
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.shared.model.TransitionStep
+import javax.inject.Inject
import kotlin.math.max
import kotlin.math.min
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
/**
- * For the given transition params, construct a flow using [createFlow] for the specified portion of
- * the overall transition.
+ * Assists in creating sub-flows for a KeyguardTransition. Call [setup] once for a transition, and
+ * then [sharedFlow] for each sub animation that should be trigged when the overall transition runs.
*/
-class KeyguardTransitionAnimationFlow(
- private val transitionDuration: Duration,
- private val transitionFlow: Flow<TransitionStep>,
+@SysUISingleton
+class KeyguardTransitionAnimationFlow
+@Inject
+constructor(
+ @Application private val scope: CoroutineScope,
+ private val logger: KeyguardTransitionAnimationLogger,
) {
+
/**
- * Transitions will occur over a [transitionDuration] with [TransitionStep]s being emitted in
- * the range of [0, 1]. View animations should begin and end within a subset of this range. This
- * function maps the [startTime] and [duration] into [0, 1], when this subset is valid.
+ * Invoke once per transition between FROM->TO states to get access to
+ * [SharedFlowBuilder#sharedFlow].
*/
- fun createFlow(
+ fun setup(
duration: Duration,
- onStep: (Float) -> Float,
- startTime: Duration = 0.milliseconds,
- onStart: (() -> Unit)? = null,
- onCancel: (() -> Float)? = null,
- onFinish: (() -> Float)? = null,
- interpolator: Interpolator = LINEAR,
- ): Flow<Float> {
- if (!duration.isPositive()) {
- throw IllegalArgumentException("duration must be a positive number: $duration")
- }
- if ((startTime + duration).compareTo(transitionDuration) > 0) {
- throw IllegalArgumentException(
- "startTime($startTime) + duration($duration) must be" +
- " <= transitionDuration($transitionDuration)"
- )
- }
+ stepFlow: Flow<TransitionStep>,
+ ) = SharedFlowBuilder(duration, stepFlow)
- val start = (startTime / transitionDuration).toFloat()
- val chunks = (transitionDuration / duration).toFloat()
- var isComplete = true
-
- fun stepToValue(step: TransitionStep): Float? {
- val value = (step.value - start) * chunks
- return when (step.transitionState) {
- // When starting, make sure to always emit. If a transition is started from the
- // middle, it is possible this animation is being skipped but we need to inform
- // the ViewModels of the last update
- STARTED -> {
- isComplete = false
- onStart?.invoke()
- max(0f, min(1f, value))
- }
- // Always send a final value of 1. Because of rounding, [value] may never be
- // exactly 1.
- RUNNING ->
- if (isComplete) {
- null
- } else if (value >= 1f) {
- isComplete = true
- 1f
- } else if (value >= 0f) {
- value
- } else {
- null
- }
- else -> null
- }?.let { onStep(interpolator.getInterpolation(it)) }
- }
-
- return transitionFlow
- .map { step ->
- when (step.transitionState) {
- STARTED -> stepToValue(step)
- RUNNING -> stepToValue(step)
- CANCELED -> onCancel?.invoke()
- FINISHED -> onFinish?.invoke()
- }
+ inner class SharedFlowBuilder(
+ private val transitionDuration: Duration,
+ private val stepFlow: Flow<TransitionStep>,
+ ) {
+ /**
+ * Transitions will occur over a [transitionDuration] with [TransitionStep]s being emitted
+ * in the range of [0, 1]. View animations should begin and end within a subset of this
+ * range. This function maps the [startTime] and [duration] into [0, 1], when this subset is
+ * valid.
+ *
+ * Will produce a [SharedFlow], so that identical animations can use the same value.
+ */
+ fun sharedFlow(
+ duration: Duration,
+ onStep: (Float) -> Float,
+ startTime: Duration = 0.milliseconds,
+ onStart: (() -> Unit)? = null,
+ onCancel: (() -> Float)? = null,
+ onFinish: (() -> Float)? = null,
+ interpolator: Interpolator = LINEAR,
+ name: String? = null
+ ): SharedFlow<Float> {
+ if (!duration.isPositive()) {
+ throw IllegalArgumentException("duration must be a positive number: $duration")
}
- .filterNotNull()
- }
+ if ((startTime + duration).compareTo(transitionDuration) > 0) {
+ throw IllegalArgumentException(
+ "startTime($startTime) + duration($duration) must be" +
+ " <= transitionDuration($transitionDuration)"
+ )
+ }
- /** Immediately (after 1ms) emits the given value for every step of the KeyguardTransition. */
- fun immediatelyTransitionTo(value: Float): Flow<Float> {
- return createFlow(duration = 1.milliseconds, onStep = { value }, onFinish = { value })
+ val start = (startTime / transitionDuration).toFloat()
+ val chunks = (transitionDuration / duration).toFloat()
+ logger.logCreate(name, start)
+ var isComplete = true
+
+ fun stepToValue(step: TransitionStep): Float? {
+ val value = (step.value - start) * chunks
+ return when (step.transitionState) {
+ // When starting, make sure to always emit. If a transition is started from the
+ // middle, it is possible this animation is being skipped but we need to inform
+ // the ViewModels of the last update
+ STARTED -> {
+ isComplete = false
+ onStart?.invoke()
+ max(0f, min(1f, value))
+ }
+ // Always send a final value of 1. Because of rounding, [value] may never be
+ // exactly 1.
+ RUNNING ->
+ if (isComplete) {
+ null
+ } else if (value >= 1f) {
+ isComplete = true
+ 1f
+ } else if (value >= 0f) {
+ value
+ } else {
+ null
+ }
+ else -> null
+ }?.let { onStep(interpolator.getInterpolation(it)) }
+ }
+
+ return stepFlow
+ .map { step ->
+ val value =
+ when (step.transitionState) {
+ STARTED -> stepToValue(step)
+ RUNNING -> stepToValue(step)
+ CANCELED -> onCancel?.invoke()
+ FINISHED -> onFinish?.invoke()
+ }
+ logger.logTransitionStep(name, step, value)
+ value
+ }
+ .filterNotNull()
+ .shareIn(scope, SharingStarted.WhileSubscribed())
+ }
+
+ /**
+ * Immediately (after 1ms) emits the given value for every step of the KeyguardTransition.
+ */
+ fun immediatelyTransitionTo(value: Float): Flow<Float> {
+ return sharedFlow(duration = 1.milliseconds, onStep = { value }, onFinish = { value })
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
index c688cfff..b1c40b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
@@ -17,18 +17,19 @@
package com.android.systemui.keyguard.ui.binder
import android.transition.TransitionManager
+import androidx.annotation.VisibleForTesting
+import androidx.constraintlayout.helper.widget.Layer
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.ui.view.layout.items.ClockSection
+import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import kotlinx.coroutines.launch
@@ -40,13 +41,12 @@
clockSection: ClockSection,
keyguardRootView: ConstraintLayout,
viewModel: KeyguardClockViewModel,
- keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
keyguardClockInteractor: KeyguardClockInteractor,
featureFlags: FeatureFlagsClassic,
) {
keyguardRootView.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
- keyguardClockInteractor.eventController.registerListeners(keyguardRootView)
+ keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView)
}
}
keyguardRootView.repeatWhenAttached {
@@ -54,10 +54,11 @@
launch {
if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) return@launch
viewModel.currentClock.collect { currentClock ->
- viewModel.clock?.let { clock -> cleanupClockViews(clock, keyguardRootView) }
+ cleanupClockViews(viewModel.clock, keyguardRootView, viewModel.burnInLayer)
viewModel.clock = currentClock
- addClockViews(currentClock, keyguardRootView)
- keyguardBlueprintInteractor.refreshBlueprint()
+ addClockViews(currentClock, keyguardRootView, viewModel.burnInLayer)
+ viewModel.burnInLayer?.updatePostLayout(keyguardRootView)
+ applyConstraints(clockSection, keyguardRootView, true)
}
}
// TODO: Weather clock dozing animation
@@ -71,13 +72,61 @@
}
launch {
if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) return@launch
- viewModel.clockShouldBeCentered.collect { shouldBeCentered ->
- clockSection.setClockShouldBeCentered(
- viewModel.useLargeClock && shouldBeCentered
- )
+ viewModel.clockShouldBeCentered.collect {
applyConstraints(clockSection, keyguardRootView, true)
}
}
+ launch {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) return@launch
+ viewModel.hasCustomWeatherDataDisplay.collect {
+ applyConstraints(clockSection, keyguardRootView, true)
+ }
+ }
+ }
+ }
+ }
+
+ private fun cleanupClockViews(
+ clockController: ClockController?,
+ rootView: ConstraintLayout,
+ burnInLayer: Layer?
+ ) {
+ clockController?.let { clock ->
+ clock.smallClock.layout.views.forEach {
+ burnInLayer?.removeView(it)
+ rootView.removeView(it)
+ }
+ // add large clock to burn in layer only when it will have same transition with other
+ // components in AOD
+ // otherwise, it will have a separate scale transition while other components only have
+ // translate transition
+ if (clock.config.useAlternateSmartspaceAODTransition) {
+ clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) }
+ }
+ clock.largeClock.layout.views.forEach { rootView.removeView(it) }
+ }
+ }
+
+ @VisibleForTesting
+ fun addClockViews(
+ clockController: ClockController?,
+ rootView: ConstraintLayout,
+ burnInLayer: Layer?
+ ) {
+ clockController?.let { clock ->
+ clock.smallClock.layout.views[0].id = R.id.lockscreen_clock_view
+ if (clock.largeClock.layout.views.size == 1) {
+ clock.largeClock.layout.views[0].id = R.id.lockscreen_clock_view_large
+ }
+ // small clock should either be a single view or container with id
+ // `lockscreen_clock_view`
+ clock.smallClock.layout.views.forEach {
+ rootView.addView(it)
+ burnInLayer?.addView(it)
+ }
+ clock.largeClock.layout.views.forEach { rootView.addView(it) }
+ if (clock.config.useAlternateSmartspaceAODTransition) {
+ clock.largeClock.layout.views.forEach { burnInLayer?.addView(it) }
}
}
}
@@ -92,22 +141,6 @@
if (animated) {
TransitionManager.beginDelayedTransition(rootView)
}
-
constraintSet.applyTo(rootView)
}
-
- private fun cleanupClockViews(clock: ClockController, rootView: ConstraintLayout) {
- clock.smallClock.layout.views.forEach { rootView.removeView(it) }
- clock.largeClock.layout.views.forEach { rootView.removeView(it) }
- }
-
- private fun addClockViews(clock: ClockController, rootView: ConstraintLayout) {
- clock.smallClock.layout.views[0].id = R.id.lockscreen_clock_view
- if (clock.largeClock.layout.views.size == 1) {
- clock.largeClock.layout.views[0].id = R.id.lockscreen_clock_view_large
- }
- // small clock should either be a single view or container with id `lockscreen_clock_view`
- clock.smallClock.layout.views.forEach { rootView.addView(it) }
- clock.largeClock.layout.views.forEach { rootView.addView(it) }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
index 1a8f625..4efd9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
@@ -23,10 +23,10 @@
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.Flags.keyguardBottomAreaRefactor
-import com.android.systemui.res.R
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.ExperimentalCoroutinesApi
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 c0d3d33..ebc9c5b 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
@@ -41,12 +41,13 @@
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.CrossFadeHelper
@@ -88,7 +89,7 @@
vibratorHelper: VibratorHelper?,
): DisposableHandle {
var onLayoutChangeListener: OnLayoutChange? = null
- val childViews = mutableMapOf<Int, View?>()
+ val childViews = mutableMapOf<Int, View>()
val statusViewId = R.id.keyguard_status_view
val burnInLayerId = R.id.burn_in_layer
val aodNotificationIconContainerId = R.id.aod_notification_icon_container
@@ -113,7 +114,12 @@
}
if (keyguardBottomAreaRefactor()) {
- launch { viewModel.alpha.collect { alpha -> view.alpha = alpha } }
+ launch {
+ viewModel.alpha.collect { alpha ->
+ view.alpha = alpha
+ childViews[statusViewId]?.alpha = alpha
+ }
+ }
}
if (KeyguardShadeMigrationNssl.isEnabled) {
@@ -140,25 +146,35 @@
}
launch {
+ // When translation happens in burnInLayer, it won't be weather clock
+ // large clock isn't added to burnInLayer due to its scale transition
+ // so we also need to add translation to it here
+ // same as translationX
viewModel.translationY.collect { y ->
childViews[burnInLayerId]?.translationY = y
+ childViews[largeClockId]?.translationY = y
}
}
launch {
viewModel.translationX.collect { x ->
childViews[burnInLayerId]?.translationX = x
+ childViews[largeClockId]?.translationX = x
}
}
launch {
viewModel.scale.collect { (scale, scaleClockOnly) ->
if (scaleClockOnly) {
+ // For clocks except weather clock, we have scale transition
+ // besides translate
childViews[largeClockId]?.let {
it.scaleX = scale
it.scaleY = scale
}
} else {
+ // For weather clock, large clock should have only scale
+ // transition with other parts in burnInLayer
childViews[burnInLayerId]?.scaleX = scale
childViews[burnInLayerId]?.scaleY = scale
}
@@ -247,7 +263,10 @@
}
}
}
- viewModel.clockControllerProvider = clockControllerProvider
+
+ if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ viewModel.clockControllerProvider = clockControllerProvider
+ }
onLayoutChangeListener = OnLayoutChange(viewModel)
view.addOnLayoutChangeListener(onLayoutChangeListener)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
index 41a2e50..954d2cf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.systemui.keyguard.ui.binder
import androidx.constraintlayout.widget.ConstraintLayout
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 59c798b..4eecfde 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -27,6 +27,8 @@
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
+import android.provider.Settings
+import android.util.Log
import android.view.ContextThemeWrapper
import android.view.Display
import android.view.Display.DEFAULT_DISPLAY
@@ -47,6 +49,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.ui.ConfigurationState
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.FeatureFlagsClassic
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
@@ -64,8 +67,9 @@
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.monet.ColorScheme
-import com.android.systemui.plugins.ClockController
+import com.android.systemui.monet.Style
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shared.clocks.ClockRegistry
@@ -79,13 +83,21 @@
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
+import com.android.systemui.util.settings.SecureSettings
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import org.json.JSONException
+import org.json.JSONObject
/** Renders the preview of the lock screen. */
class KeyguardPreviewRenderer
@@ -93,8 +105,10 @@
@AssistedInject
constructor(
@Application private val context: Context,
+ @Application applicationScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
@Main private val mainHandler: Handler,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
private val clockViewModel: KeyguardPreviewClockViewModel,
private val smartspaceViewModel: KeyguardPreviewSmartspaceViewModel,
private val bottomAreaViewModel: KeyguardBottomAreaViewModel,
@@ -118,8 +132,8 @@
private val chipbarCoordinator: ChipbarCoordinator,
private val screenOffAnimationController: ScreenOffAnimationController,
private val shadeInteractor: ShadeInteractor,
+ private val secureSettings: SecureSettings,
) {
-
val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
private val width: Int = bundle.getInt(KEY_VIEW_WIDTH)
private val height: Int = bundle.getInt(KEY_VIEW_HEIGHT)
@@ -157,7 +171,13 @@
private val shortcutsBindings = mutableSetOf<KeyguardQuickAffordanceViewBinder.Binding>()
+ private val coroutineScope: CoroutineScope
+ private var themeStyle: Style? = null
+
init {
+ coroutineScope = CoroutineScope(applicationScope.coroutineContext + Job())
+ disposables.add(DisposableHandle { coroutineScope.cancel() })
+
if (keyguardBottomAreaRefactor()) {
quickAffordancesCombinedViewModel.enablePreviewMode(
initiallySelectedSlotId =
@@ -554,29 +574,54 @@
}
private fun onClockChanged() {
- val clock = clockRegistry.createCurrentClock()
- clockController.clock = clock
+ coroutineScope.launch {
+ val clock = clockRegistry.createCurrentClock()
+ clockController.clock = clock
- if (clockRegistry.seedColor == null) {
- // Seed color null means users do override any color on the clock. The default color
- // will need to use wallpaper's extracted color and consider if the wallpaper's color
- // is dark or a light.
- // TODO(b/277832214) we can potentially simplify this code by checking for
- // wallpaperColors being null in the if clause above and removing the many ?.
- val wallpaperColorScheme = wallpaperColors?.let { ColorScheme(it, darkTheme = false) }
- val lightClockColor = wallpaperColorScheme?.accent1?.s100
- val darkClockColor = wallpaperColorScheme?.accent2?.s600
+ val colors = wallpaperColors
+ if (clockRegistry.seedColor == null && colors != null) {
+ // Seed color null means users do not override any color on the clock. The default
+ // color will need to use wallpaper's extracted color and consider if the
+ // wallpaper's color is dark or light.
+ val style = themeStyle ?: fetchThemeStyleFromSetting().also { themeStyle = it }
+ val wallpaperColorScheme = ColorScheme(colors, darkTheme = false, style)
+ val lightClockColor = wallpaperColorScheme.accent1.s100
+ val darkClockColor = wallpaperColorScheme.accent2.s600
- // Note that when [wallpaperColors] is null, isWallpaperDark is true.
- val isWallpaperDark: Boolean =
- (wallpaperColors?.colorHints?.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) == 0
- clock.events.onSeedColorChanged(
- if (isWallpaperDark) lightClockColor else darkClockColor
- )
+ // Note that when [wallpaperColors] is null, isWallpaperDark is true.
+ val isWallpaperDark: Boolean =
+ (colors.colorHints.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) == 0
+ clock.events.onSeedColorChanged(
+ if (isWallpaperDark) lightClockColor else darkClockColor
+ )
+ }
+
+ updateLargeClock(clock)
+ updateSmallClock(clock)
}
+ }
- updateLargeClock(clock)
- updateSmallClock(clock)
+ private suspend fun fetchThemeStyleFromSetting(): Style {
+ val overlayPackageJson =
+ withContext(backgroundDispatcher) {
+ secureSettings.getString(
+ Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
+ )
+ }
+ return if (!overlayPackageJson.isNullOrEmpty()) {
+ try {
+ val jsonObject = JSONObject(overlayPackageJson)
+ Style.valueOf(jsonObject.getString(OVERLAY_CATEGORY_THEME_STYLE))
+ } catch (e: (JSONException)) {
+ Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e)
+ Style.TONAL_SPOT
+ } catch (e: IllegalArgumentException) {
+ Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e)
+ Style.TONAL_SPOT
+ }
+ } else {
+ Style.TONAL_SPOT
+ }
}
private fun updateLargeClock(clock: ClockController) {
@@ -602,6 +647,8 @@
}
companion object {
+ private const val TAG = "KeyguardPreviewRenderer"
+ private const val OVERLAY_CATEGORY_THEME_STYLE = "android.theme.customization.theme_style"
private const val KEY_HOST_TOKEN = "host_token"
private const val KEY_VIEW_WIDTH = "width"
private const val KEY_VIEW_HEIGHT = "height"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index fa27442..1c6a2ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -21,9 +21,9 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.view.layout.items.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
+import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntrySection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultNotificationStackScrollLayoutSection
@@ -75,10 +75,10 @@
defaultStatusBarSection,
defaultNotificationStackScrollLayoutSection,
aodNotificationIconsSection,
+ smartspaceSection,
aodBurnInSection,
communalTutorialIndicatorSection,
clockSection,
- smartspaceSection,
defaultDeviceEntrySection, // Add LAST: Intentionally has z-order above other views.
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
index 484d351..df9ae41 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
@@ -22,8 +22,12 @@
import androidx.constraintlayout.helper.widget.Layer
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.res.R
import javax.inject.Inject
@@ -32,21 +36,31 @@
@Inject
constructor(
private val context: Context,
+ private val clockViewModel: KeyguardClockViewModel,
+ private val smartspaceViewModel: KeyguardSmartspaceViewModel,
+ private val featureFlags: FeatureFlagsClassic,
) : KeyguardSection() {
+ lateinit var burnInLayer: Layer
override fun addViews(constraintLayout: ConstraintLayout) {
if (!KeyguardShadeMigrationNssl.isEnabled) {
return
}
- val statusView = constraintLayout.requireViewById<View>(R.id.keyguard_status_view)
val nic = constraintLayout.requireViewById<View>(R.id.aod_notification_icon_container)
- val burnInLayer =
+ burnInLayer =
Layer(context).apply {
id = R.id.burn_in_layer
addView(nic)
- addView(statusView)
+ if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ val statusView =
+ constraintLayout.requireViewById<View>(R.id.keyguard_status_view)
+ addView(statusView)
+ }
}
+ if (featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ addSmartspaceViews(constraintLayout)
+ }
constraintLayout.addView(burnInLayer)
}
@@ -54,6 +68,9 @@
if (!KeyguardShadeMigrationNssl.isEnabled) {
return
}
+ if (featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ clockViewModel.burnInLayer = burnInLayer
+ }
}
override fun applyConstraints(constraintSet: ConstraintSet) {
@@ -65,4 +82,22 @@
override fun removeViews(constraintLayout: ConstraintLayout) {
constraintLayout.removeView(R.id.burn_in_layer)
}
+
+ private fun addSmartspaceViews(constraintLayout: ConstraintLayout) {
+ burnInLayer.apply {
+ if (smartspaceViewModel.isSmartspaceEnabled) {
+ val smartspaceView =
+ constraintLayout.requireViewById<View>(smartspaceViewModel.smartspaceViewId)
+ addView(smartspaceView)
+ if (smartspaceViewModel.isDateWeatherDecoupled) {
+ val dateView =
+ constraintLayout.requireViewById<View>(smartspaceViewModel.dateId)
+ val weatherView =
+ constraintLayout.requireViewById<View>(smartspaceViewModel.weatherId)
+ addView(weatherView)
+ addView(dateView)
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index 941c295..c8b2d39 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.keyguard.ui.view.layout.items
+package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.Context
import android.view.View
@@ -28,18 +28,16 @@
import androidx.constraintlayout.widget.ConstraintSet.TOP
import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.binder.KeyguardClockViewBinder
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockFaceLayout
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockFaceLayout
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.util.Utils
-import dagger.Lazy
import javax.inject.Inject
internal fun ConstraintSet.setVisibility(
@@ -60,7 +58,6 @@
val smartspaceViewModel: KeyguardSmartspaceViewModel,
private val context: Context,
private val splitShadeStateController: SplitShadeStateController,
- private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
private val featureFlags: FeatureFlagsClassic,
) : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {}
@@ -70,7 +67,6 @@
this,
constraintLayout,
keyguardClockViewModel,
- keyguardBlueprintInteractor.get(),
clockInteractor,
featureFlags
)
@@ -109,15 +105,15 @@
return previousValue != largeClockEndGuideline
}
- fun getTargetClockFace(clock: ClockController): ClockFaceLayout =
+ private fun getTargetClockFace(clock: ClockController): ClockFaceLayout =
if (keyguardClockViewModel.useLargeClock) getLargeClockFace(clock)
else getSmallClockFace(clock)
- fun getNonTargetClockFace(clock: ClockController): ClockFaceLayout =
+ private fun getNonTargetClockFace(clock: ClockController): ClockFaceLayout =
if (keyguardClockViewModel.useLargeClock) getSmallClockFace(clock)
else getLargeClockFace(clock)
- fun getLargeClockFace(clock: ClockController): ClockFaceLayout = clock.largeClock.layout
- fun getSmallClockFace(clock: ClockController): ClockFaceLayout = clock.smallClock.layout
+ private fun getLargeClockFace(clock: ClockController): ClockFaceLayout = clock.largeClock.layout
+ private fun getSmallClockFace(clock: ClockController): ClockFaceLayout = clock.smallClock.layout
fun applyDefaultConstraints(constraints: ConstraintSet) {
constraints.apply {
connect(R.id.lockscreen_clock_view_large, START, PARENT_ID, START)
@@ -138,6 +134,7 @@
)
}
connect(R.id.lockscreen_clock_view_large, TOP, PARENT_ID, TOP, largeClockTopMargin)
+ constrainHeight(R.id.lockscreen_clock_view_large, WRAP_CONTENT)
constrainWidth(R.id.lockscreen_clock_view_large, WRAP_CONTENT)
constrainWidth(R.id.lockscreen_clock_view, WRAP_CONTENT)
constrainHeight(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
index 8aef7c2..56f717d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
@@ -22,12 +22,12 @@
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.Flags.keyguardBottomAreaRefactor
-import com.android.systemui.res.R
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
+import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import javax.inject.Inject
import kotlinx.coroutines.DisposableHandle
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
index 4abcca9..851a45f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
@@ -53,7 +53,7 @@
private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
private val keyguardMediaController: KeyguardMediaController,
- private val splitShadeStateController: SplitShadeStateController
+ private val splitShadeStateController: SplitShadeStateController,
) : KeyguardSection() {
private val statusViewId = R.id.keyguard_status_view
@@ -76,6 +76,9 @@
keyguardStatusView.findViewById<View>(R.id.left_aligned_notification_icon_container)?.let {
it.setVisibility(View.GONE)
}
+ // Should keep this even if flag, migrating clocks to blueprint, is on
+ // cause some events in clockEventController rely on keyguardStatusViewController
+ // TODO(b/313499340): clean up
constraintLayout.addView(keyguardStatusView)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
index 25931a6..a005692 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
@@ -47,9 +47,9 @@
val keyguardUnlockAnimationController: KeyguardUnlockAnimationController,
val featureFlags: FeatureFlagsClassic,
) : KeyguardSection() {
- var smartspaceView: View? = null
- var weatherView: View? = null
- var dateView: View? = null
+ private var smartspaceView: View? = null
+ private var weatherView: View? = null
+ private var dateView: View? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (!featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
@@ -65,16 +65,11 @@
constraintLayout.addView(dateView)
}
}
-
keyguardUnlockAnimationController.lockscreenSmartspace = smartspaceView
}
override fun bindData(constraintLayout: ConstraintLayout) {
- KeyguardSmartspaceViewBinder.bind(
- this,
- constraintLayout,
- keyguardClockViewModel,
- )
+ KeyguardSmartspaceViewBinder.bind(this, constraintLayout, keyguardClockViewModel)
}
override fun applyConstraints(constraintSet: ConstraintSet) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
index bb7bcd9..8e729f7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
@@ -38,15 +38,17 @@
constructor(
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
transitionInteractor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
// When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be:
private val alternateBouncerScrimAlpha = .66f
private val toAlternateBouncerTransition =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TRANSITION_DURATION_MS,
- transitionFlow = transitionInteractor.anyStateToAlternateBouncerTransition,
+ animationFlow
+ .setup(
+ duration = TRANSITION_DURATION_MS,
+ stepFlow = transitionInteractor.anyStateToAlternateBouncerTransition,
)
- .createFlow(
+ .sharedFlow(
duration = TRANSITION_DURATION_MS,
onStep = { it },
onFinish = { 1f },
@@ -55,11 +57,12 @@
interpolator = Interpolators.FAST_OUT_SLOW_IN,
)
private val fromAlternateBouncerTransition =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TRANSITION_DURATION_MS,
- transitionFlow = transitionInteractor.transitionStepsFromState(ALTERNATE_BOUNCER),
+ animationFlow
+ .setup(
+ TRANSITION_DURATION_MS,
+ transitionInteractor.transitionStepsFromState(ALTERNATE_BOUNCER),
)
- .createFlow(
+ .sharedFlow(
duration = TRANSITION_DURATION_MS,
onStep = { 1f - it },
// Reset on cancel
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
index 4d2af0c..2b14521 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
@@ -32,12 +32,13 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromAodTransitionInteractor.TO_GONE_DURATION,
- transitionFlow = interactor.transition(KeyguardState.AOD, KeyguardState.GONE),
+ animationFlow.setup(
+ duration = FromAodTransitionInteractor.TO_GONE_DURATION,
+ stepFlow = interactor.transition(KeyguardState.AOD, KeyguardState.GONE),
)
override val deviceEntryParentViewAlpha = transitionAnimation.immediatelyTransitionTo(0f)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
index 1864437..5e552e1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
@@ -39,24 +39,25 @@
constructor(
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.aodToLockscreenTransition,
+ animationFlow.setup(
+ duration = TO_LOCKSCREEN_DURATION,
+ stepFlow = interactor.aodToLockscreenTransition,
)
/** Ensure alpha is set to be visible */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 500.milliseconds,
onStart = { 1f },
onStep = { 1f },
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 167.milliseconds,
startTime = 67.milliseconds,
onStep = { it },
@@ -67,7 +68,7 @@
deviceEntryUdfpsInteractor.isUdfpsSupported.flatMapLatest { isUdfps ->
if (isUdfps) {
// fade in
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
onFinish = { 1f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModel.kt
index 06661d0..d283af3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModel.kt
@@ -30,11 +30,12 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromAodTransitionInteractor.TO_OCCLUDED_DURATION,
- transitionFlow = interactor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED),
+ animationFlow.setup(
+ duration = FromAodTransitionInteractor.TO_OCCLUDED_DURATION,
+ stepFlow = interactor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED),
)
override val deviceEntryParentViewAlpha = transitionAnimation.immediatelyTransitionTo(0f)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index da74f2f..41dc157 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -47,6 +47,7 @@
private val keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>,
private val featureFlags: FeatureFlagsClassic,
private val shadeInteractor: ShadeInteractor,
+ private val animationFlow: KeyguardTransitionAnimationFlow,
) {
/** Common fade for scrim alpha values during *BOUNCER->GONE */
fun scrimAlpha(duration: Duration, fromState: KeyguardState): Flow<ScrimAlpha> {
@@ -73,14 +74,14 @@
var leaveShadeOpen: Boolean = false
var willRunDismissFromKeyguard: Boolean = false
val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = duration,
- transitionFlow = interactor.transition(fromState, GONE)
+ animationFlow.setup(
+ duration = duration,
+ stepFlow = interactor.transition(fromState, GONE)
)
return shadeInteractor.shadeExpansion.flatMapLatest { shadeExpansion ->
transitionAnimation
- .createFlow(
+ .sharedFlow(
duration = duration,
interpolator = EMPHASIZED_ACCELERATE,
onStart = {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index 5b5a103..bd6aae8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -57,7 +57,6 @@
private val sceneContainerFlags: SceneContainerFlags,
private val keyguardViewController: Lazy<KeyguardViewController>,
private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
- udfpsInteractor: DeviceEntryUdfpsInteractor,
private val deviceEntryInteractor: DeviceEntryInteractor,
) {
private val intEvaluator = IntEvaluator()
@@ -149,7 +148,7 @@
}
val iconType: Flow<DeviceEntryIconView.IconType> =
combine(
- udfpsInteractor.isListeningForUdfps,
+ deviceEntryUdfpsInteractor.isListeningForUdfps,
deviceEntryInteractor.isUnlocked,
) { isListeningForUdfps, isUnlocked ->
if (isUnlocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
index a728a28..0b34326 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
@@ -35,15 +35,16 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
- private val transitionAnimation: KeyguardTransitionAnimationFlow =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromDozingTransitionInteractor.TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.dozingToLockscreenTransition,
+ private val transitionAnimation =
+ animationFlow.setup(
+ duration = FromDozingTransitionInteractor.TO_LOCKSCREEN_DURATION,
+ stepFlow = interactor.dozingToLockscreenTransition,
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 150.milliseconds,
onStep = { it },
onCancel = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt
index 58235ae..8bcf3f8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt
@@ -29,16 +29,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.dreamingLockscreenHostedToLockscreenTransition
+ animationFlow.setup(
+ duration = TO_LOCKSCREEN_DURATION,
+ stepFlow = interactor.dreamingLockscreenHostedToLockscreenTransition,
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
onCancel = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index f943bdf..5f620af 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -45,13 +45,14 @@
keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor,
private val deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition()
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = keyguardTransitionInteractor.dreamingToLockscreenTransition,
+ animationFlow.setup(
+ duration = TO_LOCKSCREEN_DURATION,
+ stepFlow = keyguardTransitionInteractor.dreamingToLockscreenTransition,
)
val transitionEnded =
@@ -62,7 +63,7 @@
/** Dream overlay y-translation on exit */
fun dreamOverlayTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = TO_LOCKSCREEN_DURATION,
onStep = { it * translatePx },
interpolator = EMPHASIZED,
@@ -71,14 +72,14 @@
/** Dream overlay views alpha - fade out */
val dreamOverlayAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
)
/** Lockscreen views y-translation */
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = TO_LOCKSCREEN_DURATION,
onStep = { value -> -translatePx + value * translatePx },
// Reset on cancel or finish
@@ -90,14 +91,14 @@
/** Lockscreen views alpha */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
startTime = 233.milliseconds,
duration = 250.milliseconds,
onStep = { it },
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
startTime = 233.milliseconds,
duration = 250.milliseconds,
onStep = { it },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
index 62b2281..3f27eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
@@ -38,17 +38,18 @@
constructor(
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_AOD_DURATION,
- transitionFlow = interactor.goneToAodTransition,
+ animationFlow.setup(
+ duration = TO_AOD_DURATION,
+ stepFlow = interactor.goneToAodTransition,
)
/** y-translation from the top of the screen for AOD */
fun enterFromTopTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
startTime = 600.milliseconds,
duration = 500.milliseconds,
onStart = { translatePx },
@@ -61,7 +62,7 @@
/** alpha animation upon entering AOD */
val enterFromTopAnimationAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
startTime = 600.milliseconds,
duration = 500.milliseconds,
onStart = { 0f },
@@ -74,7 +75,7 @@
if (udfpsEnrolled) {
// fade in at the end of the transition to give time for FP to start running
// and avoid a flicker of the unlocked icon
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
startTime = 1100.milliseconds,
duration = 200.milliseconds,
onStep = { it },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingLockscreenHostedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingLockscreenHostedTransitionViewModel.kt
index 113f01c..bba790a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingLockscreenHostedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingLockscreenHostedTransitionViewModel.kt
@@ -33,17 +33,18 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_DREAMING_DURATION,
- transitionFlow = interactor.goneToDreamingLockscreenHostedTransition,
+ animationFlow.setup(
+ duration = TO_DREAMING_DURATION,
+ stepFlow = interactor.goneToDreamingLockscreenHostedTransition,
)
/** Lockscreen views alpha - hide immediately */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 1.milliseconds,
onStep = { 0f },
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
index c135786..6762ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
@@ -31,17 +31,18 @@
@Inject
constructor(
private val interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_DREAMING_DURATION,
- transitionFlow = interactor.goneToDreamingTransition,
+ animationFlow.setup(
+ duration = TO_DREAMING_DURATION,
+ stepFlow = interactor.goneToDreamingTransition,
)
/** Lockscreen views y-translation */
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = 500.milliseconds,
onStep = { it * translatePx },
// Reset on cancel or finish
@@ -53,7 +54,7 @@
/** Lockscreen views alpha */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt
index 5804a20..adae8ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt
@@ -29,16 +29,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.goneToLockscreenTransition
+ animationFlow.setup(
+ duration = TO_LOCKSCREEN_DURATION,
+ stepFlow = interactor.goneToLockscreenTransition
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
onCancel = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index c54f47b..3aeff61 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import androidx.constraintlayout.helper.widget.Layer
import com.android.keyguard.KeyguardClockSwitch.LARGE
import com.android.keyguard.KeyguardClockSwitch.SMALL
import com.android.systemui.dagger.SysUISingleton
@@ -23,13 +24,12 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.SettingsClockSize
-import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.clocks.ClockController
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.stateIn
@SysUISingleton
@@ -40,19 +40,14 @@
val keyguardClockInteractor: KeyguardClockInteractor,
@Application private val applicationScope: CoroutineScope,
) {
+ var burnInLayer: Layer? = null
val useLargeClock: Boolean
get() = clockSize.value == LARGE
- var clock: ClockController?
- set(value) {
- keyguardClockInteractor.clock = value
- }
- get() {
- return keyguardClockInteractor.clock
- }
+ var clock: ClockController? by keyguardClockInteractor::clock
val clockSize =
- combine(keyguardClockInteractor.selectedClockSize, keyguardInteractor.clockSize) {
+ combine(keyguardClockInteractor.selectedClockSize, keyguardClockInteractor.clockSize) {
selectedSize,
clockSize ->
if (selectedSize == SettingsClockSize.SMALL) {
@@ -61,7 +56,6 @@
clockSize
}
}
- .distinctUntilChanged()
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
@@ -72,16 +66,23 @@
val hasCustomWeatherDataDisplay =
combine(clockSize, currentClock) { size, clock ->
- (if (size == LARGE) clock.largeClock.config.hasCustomWeatherDataDisplay
- else clock.smallClock.config.hasCustomWeatherDataDisplay)
+ clock?.let {
+ (if (size == LARGE) clock.largeClock.config.hasCustomWeatherDataDisplay
+ else clock.smallClock.config.hasCustomWeatherDataDisplay)
+ }
+ ?: false
}
- .distinctUntilChanged()
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = false
+ initialValue = currentClock.value?.largeClock?.config?.hasCustomWeatherDataDisplay
+ ?: false
)
val clockShouldBeCentered: Flow<Boolean> =
- keyguardInteractor.clockShouldBeCentered.distinctUntilChanged()
+ keyguardInteractor.clockShouldBeCentered.stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = true
+ )
}
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 2327c02..6458eda 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
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.Flags.keyguardBottomAreaRefactor
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -35,10 +36,11 @@
keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
private val burnInHelperWrapper: BurnInHelperWrapper,
private val shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
+ configurationInteractor: ConfigurationInteractor,
) {
/** Notifies when a new configuration is set */
- val configurationChange: Flow<Unit> = keyguardInteractor.configurationChange
+ val configurationChange: Flow<Unit> = configurationInteractor.onAnyConfigurationChange
/** An observable for the alpha level for the entire bottom area. */
val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha
@@ -47,17 +49,18 @@
val isIndicationAreaPadded: Flow<Boolean> =
if (keyguardBottomAreaRefactor()) {
combine(shortcutsCombinedViewModel.startButton, shortcutsCombinedViewModel.endButton) {
- startButtonModel,
- endButtonModel ->
- startButtonModel.isVisible || endButtonModel.isVisible
- }
+ startButtonModel,
+ endButtonModel ->
+ startButtonModel.isVisible || endButtonModel.isVisible
+ }
.distinctUntilChanged()
} else {
- combine(keyguardBottomAreaViewModel.startButton, keyguardBottomAreaViewModel.endButton) {
- startButtonModel,
- endButtonModel ->
- startButtonModel.isVisible || endButtonModel.isVisible
- }
+ combine(
+ keyguardBottomAreaViewModel.startButton,
+ keyguardBottomAreaViewModel.endButton
+ ) { startButtonModel, endButtonModel ->
+ startButtonModel.isVisible || endButtonModel.isVisible
+ }
.distinctUntilChanged()
}
/** An observable for the x-offset by which the indication area should be translated. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index f63afeb..d250c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -17,22 +17,26 @@
package com.android.systemui.keyguard.ui.viewmodel
-import android.content.Context
import android.util.MathUtils
import android.view.View.VISIBLE
import com.android.app.animation.Interpolators
+import com.android.keyguard.KeyguardClockSwitch.LARGE
import com.android.systemui.Flags.newAodTransition
import com.android.systemui.common.shared.model.NotificationContainerBounds
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
-import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
import com.android.systemui.statusbar.phone.DozeParameters
@@ -61,18 +65,29 @@
class KeyguardRootViewModel
@Inject
constructor(
- private val context: Context,
+ configurationInteractor: ConfigurationInteractor,
private val deviceEntryInteractor: DeviceEntryInteractor,
private val dozeParameters: DozeParameters,
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor,
private val burnInInteractor: BurnInInteractor,
+ private val keyguardClockViewModel: KeyguardClockViewModel,
private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
+ private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
screenOffAnimationController: ScreenOffAnimationController,
+ // TODO(b/310989341): remove after changing migrate_clocks_to_blueprint to aconfig
+ private val featureFlags: FeatureFlagsClassic,
) {
var clockControllerProvider: Provider<ClockController>? = null
+ get() {
+ if (featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ return Provider { keyguardClockViewModel.clock }
+ } else {
+ return field
+ }
+ }
/** System insets that keyguard needs to stay out of */
var topInset: Int = 0
@@ -84,14 +99,18 @@
.filter { it == AOD || it == LOCKSCREEN }
.map { VISIBLE }
- val goneToAodTransition = keyguardTransitionInteractor.goneToAodTransition
+ val goneToAodTransition = keyguardTransitionInteractor.transition(from = GONE, to = AOD)
/** the shared notification container bounds *on the lockscreen* */
val notificationBounds: StateFlow<NotificationContainerBounds> =
keyguardInteractor.notificationContainerBounds
/** An observable for the alpha level for the entire keyguard root view. */
- val alpha: Flow<Float> = keyguardInteractor.keyguardAlpha.distinctUntilChanged()
+ val alpha: Flow<Float> =
+ merge(
+ keyguardInteractor.keyguardAlpha.distinctUntilChanged(),
+ occludedToLockscreenTransitionViewModel.lockscreenAlpha,
+ )
private fun burnIn(): Flow<BurnInModel> {
val dozingAmount: Flow<Float> =
@@ -103,7 +122,8 @@
return combine(dozingAmount, burnInInteractor.keyguardBurnIn) { dozeAmount, burnIn ->
val interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(dozeAmount)
val useScaleOnly =
- clockControllerProvider?.get()?.config?.useAlternateSmartspaceAODTransition ?: false
+ (clockControllerProvider?.get()?.config?.useAlternateSmartspaceAODTransition
+ ?: false) && keyguardClockViewModel.clockSize.value == LARGE
if (useScaleOnly) {
BurnInModel(
translationX = 0,
@@ -113,7 +133,12 @@
} else {
// Ensure the desired translation doesn't encroach on the top inset
val burnInY = MathUtils.lerp(0, burnIn.translationY, interpolation).toInt()
- val translationY = -(statusViewTop - Math.max(topInset, statusViewTop + burnInY))
+ val translationY =
+ if (featureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
+ burnInY
+ } else {
+ -(statusViewTop - Math.max(topInset, statusViewTop + burnInY))
+ }
BurnInModel(
translationX = MathUtils.lerp(0, burnIn.translationX, interpolation).toInt(),
translationY = translationY,
@@ -131,22 +156,28 @@
val burnInLayerAlpha: Flow<Float> = goneToAodTransitionViewModel.enterFromTopAnimationAlpha
val translationY: Flow<Float> =
- keyguardInteractor.configurationChange.flatMapLatest { _ ->
- val enterFromTopAmount =
- context.resources.getDimensionPixelSize(
- R.dimen.keyguard_enter_from_top_translation_y
- )
- combine(
- keyguardInteractor.keyguardTranslationY.onStart { emit(0f) },
- burnIn().map { it.translationY.toFloat() }.onStart { emit(0f) },
- goneToAodTransitionViewModel.enterFromTopTranslationY(enterFromTopAmount).onStart {
- emit(0f)
- },
- ) { keyguardTransitionY, burnInTranslationY, goneToAodTransitionTranslationY ->
- // All 3 values need to be combined for a smooth translation
- keyguardTransitionY + burnInTranslationY + goneToAodTransitionTranslationY
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.keyguard_enter_from_top_translation_y)
+ .flatMapLatest { enterFromTopAmount ->
+ combine(
+ keyguardInteractor.keyguardTranslationY.onStart { emit(0f) },
+ burnIn().map { it.translationY.toFloat() }.onStart { emit(0f) },
+ goneToAodTransitionViewModel
+ .enterFromTopTranslationY(enterFromTopAmount)
+ .onStart { emit(0f) },
+ occludedToLockscreenTransitionViewModel.lockscreenTranslationY,
+ ) {
+ keyguardTransitionY,
+ burnInTranslationY,
+ goneToAodTransitionTranslationY,
+ occludedToLockscreenTransitionTranslationY ->
+ // All values need to be combined for a smooth translation
+ keyguardTransitionY +
+ burnInTranslationY +
+ goneToAodTransitionTranslationY +
+ occludedToLockscreenTransitionTranslationY
+ }
}
- }
val translationX: Flow<Float> = burnIn().map { it.translationX.toFloat() }
@@ -194,7 +225,6 @@
.distinctUntilChanged()
fun onNotificationContainerBoundsChanged(top: Float, bottom: Float) {
-
keyguardInteractor.setNotificationContainerBounds(NotificationContainerBounds(top, bottom))
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
index 8e33651..4541458 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
@@ -30,16 +30,21 @@
val isWeatherEnabled: Boolean = smartspaceController.isWeatherEnabled()
val isDateWeatherDecoupled: Boolean = smartspaceController.isDateWeatherDecoupled()
val smartspaceViewId: Int
- get() {
- return context.resources
- .getIdentifier("bc_smartspace_view", "id", context.packageName)
- .also {
- if (it == 0) {
- Log.d(TAG, "Cannot resolve id bc_smartspace_view")
- }
- }
- }
+ get() = getId("bc_smartspace_view")
+ val dateId: Int
+ get() = getId("date_smartspace_view")
+
+ val weatherId: Int
+ get() = getId("weather_smartspace_view")
+
+ private fun getId(name: String): Int {
+ return context.resources.getIdentifier(name, "id", context.packageName).also {
+ if (it == 0) {
+ Log.d(TAG, "Cannot resolve id $name")
+ }
+ }
+ }
fun getDimen(name: String): Int {
val res = context.packageManager.getResourcesForApplication(context.packageName)
val id = res.getIdentifier(name, "dimen", context.packageName)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
index 8e8fd75c..65614f4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
@@ -39,19 +39,20 @@
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
shadeDependentFlows: ShadeDependentFlows,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromLockscreenTransitionInteractor.TO_AOD_DURATION,
- transitionFlow = interactor.lockscreenToAodTransition,
+ animationFlow.setup(
+ duration = FromLockscreenTransitionInteractor.TO_AOD_DURATION,
+ stepFlow = interactor.lockscreenToAodTransition,
)
val deviceEntryBackgroundViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
flowWhenShadeIsNotExpanded =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
@@ -59,7 +60,7 @@
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
@@ -72,7 +73,7 @@
if (isUdfpsEnrolledAndEnabled) {
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded = // fade in
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { it },
onFinish = { 1f },
@@ -83,7 +84,7 @@
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
flowWhenShadeIsNotExpanded = // fade out
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 200.milliseconds,
onStep = { 1f - it },
onFinish = { 0f },
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 263ed11..accb20c 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
@@ -29,16 +29,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_DOZING_DURATION,
- transitionFlow = interactor.lockscreenToDozingTransition
+ animationFlow.setup(
+ duration = TO_DOZING_DURATION,
+ stepFlow = interactor.lockscreenToDozingTransition
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt
index 1701505..c649b12 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt
@@ -29,16 +29,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_DREAMING_HOSTED_DURATION,
- transitionFlow = interactor.lockscreenToDreamingLockscreenHostedTransition
+ animationFlow.setup(
+ duration = TO_DREAMING_HOSTED_DURATION,
+ stepFlow = interactor.lockscreenToDreamingLockscreenHostedTransition
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index 401c0ff..7f75b54 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -36,16 +36,17 @@
constructor(
interactor: KeyguardTransitionInteractor,
shadeDependentFlows: ShadeDependentFlows,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_DREAMING_DURATION,
- transitionFlow = interactor.lockscreenToDreamingTransition,
+ animationFlow.setup(
+ duration = TO_DREAMING_DURATION,
+ stepFlow = interactor.lockscreenToDreamingTransition,
)
/** Lockscreen views y-translation */
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = 500.milliseconds,
onStep = { it * translatePx },
// Reset on cancel or finish
@@ -57,13 +58,13 @@
/** Lockscreen views alpha */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
index cfb4bf5..9e19713 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
@@ -36,16 +36,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromLockscreenTransitionInteractor.TO_GONE_DURATION,
- transitionFlow = interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.GONE),
+ animationFlow.setup(
+ duration = FromLockscreenTransitionInteractor.TO_GONE_DURATION,
+ stepFlow = interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.GONE),
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
index a6136f9..9db0b77 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
@@ -17,14 +17,17 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_OCCLUDED_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.res.R
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
/**
* Breaks down LOCKSCREEN->OCCLUDED transition into discrete steps for corresponding views to
@@ -36,22 +39,26 @@
constructor(
interactor: KeyguardTransitionInteractor,
shadeDependentFlows: ShadeDependentFlows,
+ configurationInteractor: ConfigurationInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
+
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_OCCLUDED_DURATION,
- transitionFlow = interactor.lockscreenToOccludedTransition,
+ animationFlow.setup(
+ duration = TO_OCCLUDED_DURATION,
+ stepFlow = interactor.lockscreenToOccludedTransition,
)
/** Lockscreen views alpha */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
+ name = "LOCKSCREEN->OCCLUDED: lockscreenAlpha",
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1 - it },
onFinish = { 0f },
@@ -59,16 +66,19 @@
)
/** Lockscreen views y-translation */
- fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
- duration = TO_OCCLUDED_DURATION,
- onStep = { value -> value * translatePx },
- // Reset on cancel or finish
- onFinish = { 0f },
- onCancel = { 0f },
- interpolator = EMPHASIZED_ACCELERATE,
- )
- }
+ val lockscreenTranslationY: Flow<Float> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y)
+ .flatMapLatest { translatePx ->
+ transitionAnimation.sharedFlow(
+ duration = TO_OCCLUDED_DURATION,
+ onStep = { value -> value * translatePx },
+ // Reset on cancel or finish
+ onFinish = { 0f },
+ onCancel = { 0f },
+ interpolator = EMPHASIZED_ACCELERATE,
+ )
+ }
override val deviceEntryParentViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index 07dd4ef..52e3257 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -39,11 +39,12 @@
constructor(
interactor: KeyguardTransitionInteractor,
shadeDependentFlows: ShadeDependentFlows,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
- transitionFlow =
+ animationFlow.setup(
+ duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
+ stepFlow =
interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER),
)
@@ -55,7 +56,7 @@
override val deviceEntryParentViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsNotExpanded =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { 1f - it },
onFinish = { 0f }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
index f7cff9b..ed5e83c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
@@ -37,11 +37,12 @@
constructor(
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromOccludedTransitionInteractor.TO_AOD_DURATION,
- transitionFlow = interactor.transition(KeyguardState.OCCLUDED, KeyguardState.AOD),
+ animationFlow.setup(
+ duration = FromOccludedTransitionInteractor.TO_AOD_DURATION,
+ stepFlow = interactor.transition(KeyguardState.OCCLUDED, KeyguardState.AOD),
)
val deviceEntryBackgroundViewAlpha: Flow<Float> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index 58be093..4c24f83 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -17,12 +17,14 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.res.R
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -40,26 +42,32 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
- deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor
+ deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ configurationInteractor: ConfigurationInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
+
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.occludedToLockscreenTransition,
+ animationFlow.setup(
+ duration = TO_LOCKSCREEN_DURATION,
+ stepFlow = interactor.occludedToLockscreenTransition,
)
/** Lockscreen views y-translation */
- fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return transitionAnimation.createFlow(
- duration = TO_LOCKSCREEN_DURATION,
- onStep = { value -> -translatePx + value * translatePx },
- interpolator = EMPHASIZED_DECELERATE,
- onCancel = { 0f },
- )
- }
+ val lockscreenTranslationY: Flow<Float> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y)
+ .flatMapLatest { translatePx ->
+ transitionAnimation.sharedFlow(
+ duration = TO_LOCKSCREEN_DURATION,
+ onStep = { value -> -translatePx + value * translatePx },
+ interpolator = EMPHASIZED_DECELERATE,
+ onCancel = { 0f },
+ )
+ }
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
onCancel = { 0f },
@@ -67,10 +75,12 @@
/** Lockscreen views alpha */
val lockscreenAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
startTime = 233.milliseconds,
duration = 250.milliseconds,
onStep = { it },
+ onStart = { 0f },
+ name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha",
)
val deviceEntryBackgroundViewAlpha: Flow<Float> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
index c3bc799..93482ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
@@ -28,16 +28,17 @@
@Inject
constructor(
interactor: KeyguardTransitionInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = 250.milliseconds,
- transitionFlow = interactor.offToLockscreenTransition
+ animationFlow.setup(
+ duration = 250.milliseconds,
+ stepFlow = interactor.offToLockscreenTransition
)
val shortcutsAlpha: Flow<Float> =
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 250.milliseconds,
onStep = { it },
onCancel = { 0f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
index 05a6d58..b0e2aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
@@ -41,12 +41,12 @@
constructor(
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromPrimaryBouncerTransitionInteractor.TO_AOD_DURATION,
- transitionFlow =
- interactor.transition(KeyguardState.PRIMARY_BOUNCER, KeyguardState.AOD),
+ animationFlow.setup(
+ duration = FromPrimaryBouncerTransitionInteractor.TO_AOD_DURATION,
+ stepFlow = interactor.transition(KeyguardState.PRIMARY_BOUNCER, KeyguardState.AOD),
)
val deviceEntryBackgroundViewAlpha: Flow<Float> =
@@ -62,7 +62,7 @@
deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest {
isUdfpsEnrolledAndEnabled ->
if (isUdfpsEnrolledAndEnabled) {
- transitionAnimation.createFlow(
+ transitionAnimation.sharedFlow(
duration = 300.milliseconds,
onStep = { it },
onFinish = { 1f },
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index 0e95be2..9dbe97f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -50,11 +50,12 @@
keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>,
featureFlags: FeatureFlagsClassic,
bouncerToGoneFlows: BouncerToGoneFlows,
+ animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = TO_GONE_DURATION,
- transitionFlow = interactor.transition(PRIMARY_BOUNCER, GONE)
+ animationFlow.setup(
+ duration = TO_GONE_DURATION,
+ stepFlow = interactor.transition(PRIMARY_BOUNCER, GONE)
)
private var leaveShadeOpen: Boolean = false
@@ -71,7 +72,7 @@
createBouncerAlphaFlow(primaryBouncerInteractor::willRunDismissFromKeyguard)
}
private fun createBouncerAlphaFlow(willRunAnimationOnKeyguard: () -> Boolean): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = 200.milliseconds,
onStart = { willRunDismissFromKeyguard = willRunAnimationOnKeyguard() },
onStep = {
@@ -95,7 +96,7 @@
createLockscreenAlpha(primaryBouncerInteractor::willRunDismissFromKeyguard)
}
private fun createLockscreenAlpha(willRunAnimationOnKeyguard: () -> Boolean): Flow<Float> {
- return transitionAnimation.createFlow(
+ return transitionAnimation.sharedFlow(
duration = 50.milliseconds,
onStart = {
leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
index 7ef8374..b2eed60 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
@@ -41,11 +41,12 @@
constructor(
interactor: KeyguardTransitionInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
private val transitionAnimation =
- KeyguardTransitionAnimationFlow(
- transitionDuration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION,
- transitionFlow =
+ animationFlow.setup(
+ duration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION,
+ stepFlow =
interactor.transition(KeyguardState.PRIMARY_BOUNCER, KeyguardState.LOCKSCREEN),
)
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 702a23e..e1c6f41 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -35,7 +35,7 @@
*
* To enable logcat echoing for an entire buffer:
* ```
- * adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
+ * adb shell cmd statusbar echo -b ScreenDecorationsLog:<logLevel>
*
* ```
*/
@@ -134,33 +134,35 @@
}
fun cameraProtectionShownOrHidden(
+ showAnimationNow: Boolean,
faceDetectionRunning: Boolean,
biometricPromptShown: Boolean,
- requestedState: Boolean,
+ faceAuthenticated: Boolean,
+ isCameraActive: Boolean,
currentlyShowing: Boolean
) {
logBuffer.log(
TAG,
DEBUG,
{
+ str1 = "$showAnimationNow"
bool1 = faceDetectionRunning
bool2 = biometricPromptShown
- bool3 = requestedState
+ str2 = "$faceAuthenticated"
+ bool3 = isCameraActive
bool4 = currentlyShowing
},
{
- "isFaceDetectionRunning: $bool1, " +
+ "cameraProtectionShownOrHidden showAnimationNow: $str1, " +
+ "isFaceDetectionRunning: $bool1, " +
"isBiometricPromptShowing: $bool2, " +
- "requestedState: $bool3, " +
+ "faceAuthenticated: $str2, " +
+ "isCameraActive: $bool3, " +
"currentState: $bool4"
}
)
}
- fun biometricEvent(@CompileTimeConstant info: String) {
- logBuffer.log(TAG, DEBUG, info)
- }
-
fun cameraProtectionEvent(@CompileTimeConstant cameraProtectionEvent: String) {
logBuffer.log(TAG, DEBUG, cameraProtectionEvent)
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardTransitionAnimationLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardTransitionAnimationLog.kt
new file mode 100644
index 0000000..ef06588
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardTransitionAnimationLog.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.log.dagger
+
+import javax.inject.Qualifier
+
+/**
+ * A [com.android.systemui.log.LogBuffer] for keyguard transition animations. Should be used mostly
+ * for adding temporary logs or logging from smaller classes when creating new separate log class
+ * might be an overkill.
+ */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class KeyguardTransitionAnimationLog
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 0b3bbb5..dc55179f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -525,6 +525,16 @@
}
/**
+ * Provides a {@link LogBuffer} for keyguard transition animation logs.
+ */
+ @Provides
+ @SysUISingleton
+ @KeyguardTransitionAnimationLog
+ public static LogBuffer provideKeyguardTransitionAnimationLogBuffer(LogBufferFactory factory) {
+ return factory.create("KeyguardTransitionAnimationLog", 250);
+ }
+
+ /**
* Provides a {@link LogBuffer} for Scrims like LightRevealScrim.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 04883c3..2551da8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -676,7 +676,7 @@
mLogger.logOpenBroadcastDialog(mUid, mPackageName, mInstanceId);
mCurrentBroadcastApp = device.getName().toString();
mBroadcastDialogController.createBroadcastDialog(mCurrentBroadcastApp,
- mPackageName, true, mMediaViewHolder.getSeamlessButton());
+ mPackageName, mMediaViewHolder.getSeamlessButton());
} else {
mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
mMediaOutputDialogFactory.create(mPackageName, true,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 35456d5..0385aeb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -461,6 +461,15 @@
// the
// location of the previous state to still be up to date when the animation
// starts
+ if (
+ newState == StatusBarState.SHADE_LOCKED &&
+ oldState == StatusBarState.KEYGUARD &&
+ fullShadeTransitionProgress < 1.0f
+ ) {
+ // Since the new state is SHADE_LOCKED, we need to set the transition amount
+ // to maximum if the progress is not 1f.
+ setTransitionToFullShadeAmount(distanceForFullShadeTransition.toFloat())
+ }
statusbarState = newState
updateDesiredLocation()
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index e2e94da..0a72a2f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -400,8 +400,8 @@
}
@Override
- public void animateNavBarLongPress(boolean isTouchDown, long durationMs) {
- mView.getHomeHandle().animateLongPress(isTouchDown, durationMs);
+ public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
+ mView.getHomeHandle().animateLongPress(isTouchDown, shrink, durationMs);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
index 5fe830e..5739abc 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
@@ -247,10 +247,10 @@
}
}
- public void animateLongPress(boolean isTouchDown, long durationMs) {
+ public void animateLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
for (int i = 0; i < mViews.size(); i++) {
if (mViews.get(i) instanceof ButtonInterface) {
- ((ButtonInterface) mViews.get(i)).animateLongPress(isTouchDown, durationMs);
+ ((ButtonInterface) mViews.get(i)).animateLongPress(isTouchDown, shrink, durationMs);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
index 356b2f7..5f8fafd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
@@ -35,9 +35,10 @@
* Animate the button being long-pressed.
*
* @param isTouchDown {@code true} if the button is starting to be pressed ({@code false} if
- * released or canceled)
- * @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
- * should be the same as the amount of time to trigger a long-press)
+ * released or canceled)
+ * @param shrink {@code true} if the handle should shrink, {@code false} if it should grow
+ * @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
+ * should be the same as the amount of time to trigger a long-press)
*/
- default void animateLongPress(boolean isTouchDown, long durationMs) {}
+ default void animateLongPress(boolean isTouchDown, boolean shrink, long durationMs) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
index 039d0e0..d1ce1f6 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
@@ -44,7 +44,9 @@
protected final float mBottom;
private final float mAdditionalWidthForAnimation;
private final float mAdditionalHeightForAnimation;
+ private final float mShrinkWidthForAnimation;
private boolean mRequiresInvalidate;
+ private boolean mShrink;
private ObjectAnimator mPulseAnimator = null;
private float mPulseAnimationProgress;
@@ -75,6 +77,8 @@
res.getDimension(R.dimen.navigation_home_handle_additional_width_for_animation);
mAdditionalHeightForAnimation =
res.getDimension(R.dimen.navigation_home_handle_additional_height_for_animation);
+ mShrinkWidthForAnimation =
+ res.getDimension(R.dimen.navigation_home_handle_shrink_width_for_animation);
final int dualToneDarkTheme = Utils.getThemeAttr(context, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme);
@@ -101,9 +105,17 @@
// Draw that bar
int navHeight = getHeight();
- float additionalHeight = mAdditionalHeightForAnimation * mPulseAnimationProgress;
+ float additionalHeight;
+ float additionalWidth;
+ if (mShrink) {
+ additionalHeight = 0;
+ additionalWidth = -mShrinkWidthForAnimation * mPulseAnimationProgress;
+ } else {
+ additionalHeight = mAdditionalHeightForAnimation * mPulseAnimationProgress;
+ additionalWidth = mAdditionalWidthForAnimation * mPulseAnimationProgress;
+ }
+
float height = mRadius * 2 + additionalHeight;
- float additionalWidth = mAdditionalWidthForAnimation * mPulseAnimationProgress;
float width = getWidth() + additionalWidth;
float x = -additionalWidth;
float y = navHeight - mBottom - height + (additionalHeight / 2);
@@ -138,26 +150,32 @@
public void setDelayTouchFeedback(boolean shouldDelay) {}
@Override
- public void animateLongPress(boolean isTouchDown, long durationMs) {
+ public void animateLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
if (mPulseAnimator != null) {
mPulseAnimator.cancel();
}
+ mShrink = shrink;
Interpolator interpolator;
- if (isTouchDown) {
- // For now we animate the navbar expanding and contracting so that the navbar is the
- // original size by the end of {@code duration}. This is because a screenshot is taken
- // at that point and we don't want to capture the larger navbar.
- // TODO(b/306400785): Determine a way to exclude navbar from the screenshot.
+ if (shrink) {
+ interpolator = Interpolators.LEGACY_DECELERATE;
+ } else {
+ if (isTouchDown) {
+ // For now we animate the navbar expanding and contracting so that the navbar is
+ // the original size by the end of {@code duration}. This is because a screenshot
+ // is taken at that point and we don't want to capture the larger navbar.
+ // TODO(b/306400785): Determine a way to exclude navbar from the screenshot.
- // Fraction of the touch down animation to expand; remaining is used to contract again.
- float expandFraction = 0.9f;
- interpolator = t -> t <= expandFraction
+ // Fraction of the touch down animation to expand; remaining is used to contract
+ // again.
+ float expandFraction = 0.9f;
+ interpolator = t -> t <= expandFraction
? Interpolators.clampToProgress(Interpolators.LEGACY, t, 0, expandFraction)
: 1 - Interpolators.clampToProgress(
Interpolators.LINEAR, t, expandFraction, 1);
- } else {
- interpolator = Interpolators.LEGACY_DECELERATE;
+ } else {
+ interpolator = Interpolators.LEGACY_DECELERATE;
+ }
}
mPulseAnimator =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
index 5e19439..9fe316f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles.base.viewmodel
import android.os.UserHandle
+import com.android.systemui.Dumpable
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
@@ -34,6 +35,7 @@
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.throttle
import com.android.systemui.util.time.SystemClock
+import java.io.PrintWriter
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -81,7 +83,7 @@
private val systemClock: SystemClock,
private val backgroundDispatcher: CoroutineDispatcher,
private val tileScope: CoroutineScope = CoroutineScope(SupervisorJob()),
-) : QSTileViewModel {
+) : QSTileViewModel, Dumpable {
private val users: MutableStateFlow<UserHandle> =
MutableStateFlow(userRepository.getSelectedUserInfo().userHandle)
@@ -137,6 +139,13 @@
tileScope.cancel()
}
+ override fun dump(pw: PrintWriter, args: Array<out String>) =
+ with(pw) {
+ println("${config.tileSpec.spec}:")
+ print(" ")
+ println(state.replayCache.lastOrNull().toString())
+ }
+
private fun createTileDataFlow(): SharedFlow<DATA_TYPE> =
users
.flatMapLatest { user ->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
new file mode 100644
index 0000000..6386577
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain
+
+import android.content.res.Resources
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+import java.util.TimeZone
+import javax.inject.Inject
+
+/** Maps [AlarmTileModel] to [QSTileState]. */
+class AlarmTileMapper @Inject constructor(@Main private val resources: Resources) :
+ QSTileDataToStateMapper<AlarmTileModel> {
+ companion object {
+ val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a")
+ val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm")
+ }
+ override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState =
+ QSTileState.build(resources, config.uiConfig) {
+ when (data) {
+ is AlarmTileModel.NextAlarmSet -> {
+ activationState = QSTileState.ActivationState.ACTIVE
+
+ val localDateTime =
+ LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(data.alarmClockInfo.triggerTime),
+ TimeZone.getDefault().toZoneId()
+ )
+ secondaryLabel =
+ if (data.is24HourFormat) formatter24Hour.format(localDateTime)
+ else formatter12Hour.format(localDateTime)
+ }
+ is AlarmTileModel.NoAlarmSet -> {
+ activationState = QSTileState.ActivationState.INACTIVE
+ secondaryLabel = resources.getString(R.string.qs_alarm_tile_no_alarm)
+ }
+ }
+
+ contentDescription = label
+ supportedActions = setOf(QSTileState.UserAction.CLICK)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractor.kt
new file mode 100644
index 0000000..51cd501
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileDataInteractor.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain.interactor
+
+import android.os.UserHandle
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+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.alarm.domain.model.AlarmTileModel
+import com.android.systemui.statusbar.policy.NextAlarmController
+import com.android.systemui.util.time.DateFormatUtil
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+
+/** Observes alarm state changes providing the [AlarmTileModel]. */
+class AlarmTileDataInteractor
+@Inject
+constructor(
+ private val alarmController: NextAlarmController,
+ private val dateFormatUtil: DateFormatUtil
+) : QSTileDataInteractor<AlarmTileModel> {
+
+ override fun tileData(
+ user: UserHandle,
+ triggers: Flow<DataUpdateTrigger>
+ ): Flow<AlarmTileModel> =
+ ConflatedCallbackFlow.conflatedCallbackFlow {
+ val alarmCallback =
+ NextAlarmController.NextAlarmChangeCallback {
+ val model =
+ if (it == null) AlarmTileModel.NoAlarmSet
+ else AlarmTileModel.NextAlarmSet(dateFormatUtil.is24HourFormat, it)
+ trySend(model)
+ }
+ alarmController.addCallback(alarmCallback)
+
+ awaitClose { alarmController.removeCallback(alarmCallback) }
+ }
+
+ override fun availability(user: UserHandle): Flow<Boolean> = flowOf(true)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt
new file mode 100644
index 0000000..afca57c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.alarm.domain.interactor
+
+import android.content.Intent
+import android.provider.AlarmClock
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import javax.inject.Inject
+
+/** Handles alarm tile clicks. */
+class AlarmTileUserActionInteractor
+@Inject
+constructor(
+ private val activityStarter: ActivityStarter,
+) : QSTileUserActionInteractor<AlarmTileModel> {
+ override suspend fun handleInput(input: QSTileInput<AlarmTileModel>): Unit =
+ with(input) {
+ when (action) {
+ is QSTileUserAction.Click -> {
+ val animationController =
+ action.view?.let {
+ ActivityLaunchAnimator.Controller.fromView(
+ it,
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
+ )
+ }
+ if (
+ data is AlarmTileModel.NextAlarmSet &&
+ data.alarmClockInfo.showIntent != null
+ ) {
+ val pendingIndent = data.alarmClockInfo.showIntent
+ activityStarter.postStartActivityDismissingKeyguard(
+ pendingIndent,
+ animationController
+ )
+ } else {
+ activityStarter.postStartActivityDismissingKeyguard(
+ Intent(AlarmClock.ACTION_SHOW_ALARMS),
+ 0,
+ animationController
+ )
+ }
+ }
+ is QSTileUserAction.LongClick -> {}
+ }
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/model/AlarmTileModel.kt
similarity index 63%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/model/AlarmTileModel.kt
index 4098987..7647d7c 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/model/AlarmTileModel.kt
@@ -14,10 +14,15 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.qs.tiles.impl.alarm.domain.model
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import android.app.AlarmManager
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+/** Alarm tile model */
+sealed interface AlarmTileModel {
+ data object NoAlarmSet : AlarmTileModel
+ data class NextAlarmSet(
+ val is24HourFormat: Boolean,
+ val alarmClockInfo: AlarmManager.AlarmClockInfo
+ ) : AlarmTileModel
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index e8623f9..977df81 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -22,6 +22,7 @@
import android.view.View
import androidx.annotation.GuardedBy
import com.android.internal.logging.InstanceId
+import com.android.systemui.Dumpable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.plugins.qs.QSTile
@@ -31,6 +32,7 @@
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import java.io.PrintWriter
import java.util.function.Supplier
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@@ -47,7 +49,7 @@
@Application private val applicationScope: CoroutineScope,
private val qsHost: QSHost,
@Assisted private val qsTileViewModel: QSTileViewModel,
-) : QSTile {
+) : QSTile, Dumpable {
private val context
get() = qsHost.context
@@ -201,6 +203,10 @@
override fun getTileSpec(): String = qsTileViewModel.config.tileSpec.spec
+ override fun dump(pw: PrintWriter, args: Array<out String>) =
+ (qsTileViewModel as? Dumpable)?.dump(pw, args)
+ ?: pw.println("${getTileSpec()}: QSTileViewModel isn't dumpable")
+
private companion object {
const val DEBUG = false
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 377803f..45917e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -248,9 +248,9 @@
}
@Override
- public void animateNavBarLongPress(boolean isTouchDown, long durationMs) {
+ public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
verifyCallerAndClearCallingIdentityPostMain("animateNavBarLongPress", () ->
- notifyAnimateNavBarLongPress(isTouchDown, durationMs));
+ notifyAnimateNavBarLongPress(isTouchDown, shrink, durationMs));
}
@Override
@@ -929,9 +929,10 @@
}
}
- private void notifyAnimateNavBarLongPress(boolean isTouchDown, long durationMs) {
+ private void notifyAnimateNavBarLongPress(boolean isTouchDown, boolean shrink,
+ long durationMs) {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
- mConnectionCallbacks.get(i).animateNavBarLongPress(isTouchDown, durationMs);
+ mConnectionCallbacks.get(i).animateNavBarLongPress(isTouchDown, shrink, durationMs);
}
}
@@ -1079,7 +1080,7 @@
default void onAssistantGestureCompletion(float velocity) {}
default void startAssistant(Bundle bundle) {}
default void setAssistantOverridesRequested(int[] invocationTypes) {}
- default void animateNavBarLongPress(boolean isTouchDown, long durationMs) {}
+ default void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {}
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
index bff0b93..62d8fb9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
@@ -177,7 +177,8 @@
activityStarter,
mUserContextProvider,
onStartRecordingClicked,
- mMediaProjectionMetricsLogger))
+ mMediaProjectionMetricsLogger,
+ mDialogFactory))
: new ScreenRecordDialog(
context,
/* controller= */ this,
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
index 3f6c58d..10d51a5 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
@@ -28,6 +28,7 @@
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
+import android.view.accessibility.AccessibilityNodeInfo
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
@@ -54,6 +55,7 @@
private val userContextProvider: UserContextProvider,
private val onStartRecordingClicked: Runnable?,
mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
) :
BaseMediaProjectionPermissionDialogDelegate<SystemUIDialog>(
createOptionList(),
@@ -62,14 +64,18 @@
mediaProjectionMetricsLogger,
R.drawable.ic_screenrecord,
R.color.screenrecord_icon_color
- ) {
+ ), SystemUIDialog.Delegate {
private lateinit var tapsSwitch: Switch
private lateinit var tapsView: View
private lateinit var audioSwitch: Switch
private lateinit var options: Spinner
+ override fun createDialog(): SystemUIDialog {
+ return systemUIDialogFactory.create(this)
+ }
+
override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
- super.onCreate(dialog, savedInstanceState)
+ super<BaseMediaProjectionPermissionDialogDelegate>.onCreate(dialog, savedInstanceState)
setDialogTitle(R.string.screenrecord_permission_dialog_title)
dialog.setTitle(R.string.screenrecord_title)
setStartButtonText(R.string.screenrecord_permission_dialog_continue)
@@ -129,6 +135,19 @@
options.setOnItemClickListenerInt { _: AdapterView<*>?, _: View?, _: Int, _: Long ->
audioSwitch.isChecked = true
}
+
+ // disable redundant Touch & Hold accessibility action for Switch Access
+ options.accessibilityDelegate =
+ object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK)
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ }
+ }
+ options.isLongClickable = false
}
override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 67ec03f..fa3e172 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -130,6 +130,7 @@
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewConfigurator;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -542,6 +543,7 @@
private final NPVCDownEventState.Buffer mLastDownEvents;
private final KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
private final KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+ private final KeyguardClockInteractor mKeyguardClockInteractor;
private float mMinExpandHeight;
private boolean mPanelUpdateWhenAnimatorEnds;
private boolean mHasVibratedOnOpen = false;
@@ -561,7 +563,6 @@
private boolean mHasLayoutedSinceDown;
private float mUpdateFlingVelocity;
private boolean mUpdateFlingOnLayout;
- private boolean mClosing;
private boolean mTouchSlopExceeded;
private int mTrackingPointer;
private int mTouchSlop;
@@ -615,10 +616,8 @@
private boolean mIsOcclusionTransitionRunning = false;
private boolean mIsGoneToDreamingLockscreenHostedTransitionRunning;
private int mDreamingToLockscreenTransitionTranslationY;
- private int mOccludedToLockscreenTransitionTranslationY;
private int mLockscreenToDreamingTransitionTranslationY;
private int mGoneToDreamingTransitionTranslationY;
- private int mLockscreenToOccludedTransitionTranslationY;
private SplitShadeStateController mSplitShadeStateController;
private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -760,6 +759,7 @@
SystemClock systemClock,
KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
+ KeyguardClockInteractor keyguardClockInteractor,
AlternateBouncerInteractor alternateBouncerInteractor,
DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel,
OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel,
@@ -964,6 +964,7 @@
updateUserSwitcherFlags();
mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel;
mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
+ mKeyguardClockInteractor = keyguardClockInteractor;
KeyguardLongPressViewBinder.bind(
mView.requireViewById(R.id.keyguard_long_press),
keyguardLongPressViewModel,
@@ -1157,11 +1158,13 @@
// Occluded->Lockscreen
collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
mOccludedToLockscreenTransition, mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
- mOccludedToLockscreenTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView,
+ mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY(),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ }
// Lockscreen->Dreaming
collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
@@ -1187,8 +1190,7 @@
mLockscreenToOccludedTransition, mMainDispatcher);
collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
- mLockscreenToOccludedTransitionTranslationY),
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
// Primary bouncer->Gone (ensures lockscreen content is not visible on successful auth)
@@ -1220,14 +1222,10 @@
R.dimen.split_shade_scrim_transition_distance);
mDreamingToLockscreenTransitionTranslationY = mResources.getDimensionPixelSize(
R.dimen.dreaming_to_lockscreen_transition_lockscreen_translation_y);
- mOccludedToLockscreenTransitionTranslationY = mResources.getDimensionPixelSize(
- R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y);
mLockscreenToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
R.dimen.lockscreen_to_dreaming_transition_lockscreen_translation_y);
mGoneToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
R.dimen.gone_to_dreaming_transition_lockscreen_translation_y);
- mLockscreenToOccludedTransitionTranslationY = mResources.getDimensionPixelSize(
- R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y);
// TODO (b/265193930): remove this and make QsController listen to NotificationPanelViews
mQsController.loadDimens();
}
@@ -1610,7 +1608,7 @@
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
boolean shouldAnimateClockChange = mScreenOffAnimationController.shouldAnimateClockChange();
if (mFeatureFlags.isEnabled(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT)) {
- mKeyguardInteractor.setClockSize(computeDesiredClockSize());
+ mKeyguardClockInteractor.setClockSize(computeDesiredClockSize());
} else {
mKeyguardStatusViewController.displayClock(computeDesiredClockSize(),
shouldAnimateClockChange);
@@ -2935,10 +2933,7 @@
@VisibleForTesting
void setClosing(boolean isClosing) {
- if (mClosing != isClosing) {
- mClosing = isClosing;
- mShadeExpansionStateManager.notifyPanelCollapsingChanged(isClosing);
- }
+ mShadeRepository.setLegacyIsClosing(isClosing);
mAmbientState.setIsClosing(isClosing);
}
@@ -3469,7 +3464,7 @@
ipw.print("mHasLayoutedSinceDown="); ipw.println(mHasLayoutedSinceDown);
ipw.print("mUpdateFlingVelocity="); ipw.println(mUpdateFlingVelocity);
ipw.print("mUpdateFlingOnLayout="); ipw.println(mUpdateFlingOnLayout);
- ipw.print("mClosing="); ipw.println(mClosing);
+ ipw.print("isClosing()="); ipw.println(isClosing());
ipw.print("mTouchSlopExceeded="); ipw.println(mTouchSlopExceeded);
ipw.print("mTrackingPointer="); ipw.println(mTrackingPointer);
ipw.print("mTouchSlop="); ipw.println(mTouchSlop);
@@ -3808,7 +3803,7 @@
}
private void endClosing() {
- if (mClosing) {
+ if (isClosing()) {
setClosing(false);
onClosingFinished();
}
@@ -3928,7 +3923,7 @@
mExpandedHeight = Math.min(h, maxPanelHeight);
// If we are closing the panel and we are almost there due to a slow decelerating
// interpolator, abort the animation.
- if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
+ if (mExpandedHeight < 1f && mExpandedHeight != 0f && isClosing()) {
mExpandedHeight = 0f;
if (mHeightAnimator != null) {
mHeightAnimator.end();
@@ -4003,7 +3998,7 @@
@Override
public boolean isCollapsing() {
- return mClosing || mIsLaunchAnimationRunning;
+ return isClosing() || mIsLaunchAnimationRunning;
}
public boolean isTracking() {
@@ -4012,7 +4007,7 @@
@Override
public boolean canBeCollapsed() {
- return !isFullyCollapsed() && !isTracking() && !mClosing;
+ return !isFullyCollapsed() && !isTracking() && !isClosing();
}
@Override
@@ -4127,7 +4122,7 @@
@VisibleForTesting
boolean isClosing() {
- return mClosing;
+ return mShadeRepository.getLegacyIsClosing().getValue();
}
@Override
@@ -4834,15 +4829,17 @@
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- mCentralSurfaces.userActivity();
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
+ mCentralSurfaces.userActivity();
+ }
mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
mMinExpandHeight = 0.0f;
mDownTime = mSystemClock.uptimeMillis();
- if (mAnimatingOnDown && mClosing) {
+ if (mAnimatingOnDown && isClosing()) {
cancelHeightAnimator();
mTouchSlopExceeded = true;
mShadeLog.v("NotificationPanelViewController MotionEvent intercepted:"
- + " mAnimatingOnDown: true, mClosing: true");
+ + " mAnimatingOnDown: true, isClosing(): true");
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index cf1dfdc..73537ed 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -311,6 +311,9 @@
mTouchActive = true;
mTouchCancelled = false;
mDownEvent = ev;
+ if (KeyguardShadeMigrationNssl.isEnabled()) {
+ mService.userActivity();
+ }
} else if (ev.getActionMasked() == MotionEvent.ACTION_UP
|| ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
mTouchActive = false;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
index 53eccfd..832fefc 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
@@ -17,6 +17,8 @@
package com.android.systemui.shade
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorEmptyImpl
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractorEmptyImpl
import dagger.Binds
@@ -36,4 +38,10 @@
@Binds
@SysUISingleton
abstract fun bindsShadeInteractor(si: ShadeInteractorEmptyImpl): ShadeInteractor
+
+ @Binds
+ @SysUISingleton
+ abstract fun bindsShadeAnimationInteractor(
+ sai: ShadeAnimationInteractorEmptyImpl
+ ): ShadeAnimationInteractor
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index e20534c..d6db19e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -163,12 +163,6 @@
}
}
- fun notifyPanelCollapsingChanged(isCollapsing: Boolean) {
- for (cb in shadeStateEventsListeners) {
- cb.onPanelCollapsingChanged(isCollapsing)
- }
- }
-
private fun debugLog(msg: String) {
if (!DEBUG) return
Log.v(TAG, msg)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 54467cf..d9b298d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -19,6 +19,9 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.domain.interactor.BaseShadeInteractor
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorSceneContainerImpl
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl
import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl
@@ -45,6 +48,20 @@
sceneContainerOff.get()
}
}
+
+ @Provides
+ @SysUISingleton
+ fun provideShadeAnimationInteractor(
+ sceneContainerFlags: SceneContainerFlags,
+ sceneContainerOn: Provider<ShadeAnimationInteractorSceneContainerImpl>,
+ sceneContainerOff: Provider<ShadeAnimationInteractorLegacyImpl>
+ ): ShadeAnimationInteractor {
+ return if (sceneContainerFlags.isEnabled()) {
+ sceneContainerOn.get()
+ } else {
+ sceneContainerOff.get()
+ }
+ }
}
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeStateEvents.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeStateEvents.kt
index c8511d7..ff96ca3c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeStateEvents.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeStateEvents.kt
@@ -27,10 +27,6 @@
/** Callbacks for certain notification panel events. */
interface ShadeStateEventsListener {
-
- /** Invoked when the notification panel starts or stops collapsing. */
- fun onPanelCollapsingChanged(isCollapsing: Boolean) {}
-
/**
* Invoked when the notification panel starts or stops launching an [android.app.Activity].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 47b08fe..e94a3eb 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -105,6 +105,12 @@
/** True when QS is taking up the entire screen, i.e. fully expanded on a non-unfolded phone. */
@Deprecated("Use ShadeInteractor instead") val legacyQsFullscreen: StateFlow<Boolean>
+ /** NPVC.mClosing as a flow. */
+ @Deprecated("Use ShadeAnimationInteractor instead") val legacyIsClosing: StateFlow<Boolean>
+
+ /** Sets whether a closing animation is happening. */
+ @Deprecated("Use ShadeAnimationInteractor instead") fun setLegacyIsClosing(isClosing: Boolean)
+
/** */
@Deprecated("Use ShadeInteractor instead")
fun setLegacyQsFullscreen(legacyQsFullscreen: Boolean)
@@ -261,6 +267,15 @@
_legacyShadeTracking.value = tracking
}
+ private val _legacyIsClosing = MutableStateFlow(false)
+ @Deprecated("Use ShadeInteractor instead")
+ override val legacyIsClosing: StateFlow<Boolean> = _legacyIsClosing.asStateFlow()
+
+ @Deprecated("Use ShadeInteractor instead")
+ override fun setLegacyIsClosing(isClosing: Boolean) {
+ _legacyIsClosing.value = isClosing
+ }
+
@Deprecated("Should only be called by NPVC and tests")
override fun setLegacyLockscreenShadeTracking(tracking: Boolean) {
legacyLockscreenShadeTracking.value = tracking
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt
new file mode 100644
index 0000000..ff422b7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import kotlinx.coroutines.flow.Flow
+
+/** Business logic related to shade animations and transitions. */
+interface ShadeAnimationInteractor {
+ /**
+ * Whether a short animation to close the shade or QS is running. This will be false if the user
+ * is manually closing the shade or QS but true if they lift their finger and an animation
+ * completes the close. Important: if QS is collapsing back to shade, this will be false because
+ * that is not considered "closing".
+ */
+ val isAnyCloseAnimationRunning: Flow<Boolean>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt
new file mode 100644
index 0000000..b4a134f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.flowOf
+
+/** Implementation of ShadeAnimationInteractor for shadeless SysUI variants. */
+@SysUISingleton
+class ShadeAnimationInteractorEmptyImpl @Inject constructor() : ShadeAnimationInteractor {
+ override val isAnyCloseAnimationRunning = flowOf(false)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt
new file mode 100644
index 0000000..d514093
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.data.repository.ShadeRepository
+import javax.inject.Inject
+
+/** Implementation of ShadeAnimationInteractor compatible with NPVC. */
+@SysUISingleton
+class ShadeAnimationInteractorLegacyImpl
+@Inject
+constructor(
+ shadeRepository: ShadeRepository,
+) : ShadeAnimationInteractor {
+ override val isAnyCloseAnimationRunning = shadeRepository.legacyIsClosing
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
new file mode 100644
index 0000000..7c0762d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.ObservableTransitionState
+import com.android.systemui.scene.shared.model.SceneKey
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+/** Implementation of ShadeAnimationInteractor compatible with the scene container framework. */
+@SysUISingleton
+class ShadeAnimationInteractorSceneContainerImpl
+@Inject
+constructor(
+ sceneInteractor: SceneInteractor,
+) : ShadeAnimationInteractor {
+ @OptIn(ExperimentalCoroutinesApi::class)
+ override val isAnyCloseAnimationRunning =
+ sceneInteractor.transitionState
+ .flatMapLatest { state ->
+ when (state) {
+ is ObservableTransitionState.Idle -> flowOf(false)
+ is ObservableTransitionState.Transition ->
+ if (
+ (state.fromScene == SceneKey.Shade &&
+ state.toScene != SceneKey.QuickSettings) ||
+ (state.fromScene == SceneKey.QuickSettings &&
+ state.toScene != SceneKey.Shade)
+ ) {
+ state.isUserInputOngoing.map { !it }
+ } else {
+ flowOf(false)
+ }
+ }
+ }
+ .distinctUntilChanged()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
index 7cff8ea..3fd070c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
@@ -71,14 +71,11 @@
override val isQsBypassingShade: Flow<Boolean> =
sceneInteractor.transitionState
- .flatMapLatest { state ->
+ .map { state ->
when (state) {
- is ObservableTransitionState.Idle -> flowOf(false)
+ is ObservableTransitionState.Idle -> false
is ObservableTransitionState.Transition ->
- flowOf(
- state.toScene == SceneKey.QuickSettings &&
- state.fromScene != SceneKey.Shade
- )
+ state.toScene == SceneKey.QuickSettings && state.fromScene != SceneKey.Shade
}
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index ef87406..599600d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -52,7 +52,7 @@
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.WeatherData
+import com.android.systemui.plugins.clocks.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.regionsampling.RegionSampler
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 a2379b2..46e2391 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
@@ -29,6 +29,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeStateEvents;
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -39,6 +40,7 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Compile;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.kotlin.JavaAdapter;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -62,7 +64,9 @@
private final DelayableExecutor mDelayableExecutor;
private final HeadsUpManager mHeadsUpManager;
private final ShadeStateEvents mShadeStateEvents;
+ private final ShadeAnimationInteractor mShadeAnimationInteractor;
private final StatusBarStateController mStatusBarStateController;
+ private final JavaAdapter mJavaAdapter;
private final VisibilityLocationProvider mVisibilityLocationProvider;
private final VisualStabilityProvider mVisualStabilityProvider;
private final WakefulnessLifecycle mWakefulnessLifecycle;
@@ -95,11 +99,15 @@
DumpManager dumpManager,
HeadsUpManager headsUpManager,
ShadeStateEvents shadeStateEvents,
+ ShadeAnimationInteractor shadeAnimationInteractor,
+ JavaAdapter javaAdapter,
StatusBarStateController statusBarStateController,
VisibilityLocationProvider visibilityLocationProvider,
VisualStabilityProvider visualStabilityProvider,
WakefulnessLifecycle wakefulnessLifecycle) {
mHeadsUpManager = headsUpManager;
+ mShadeAnimationInteractor = shadeAnimationInteractor;
+ mJavaAdapter = javaAdapter;
mVisibilityLocationProvider = visibilityLocationProvider;
mVisualStabilityProvider = visualStabilityProvider;
mWakefulnessLifecycle = wakefulnessLifecycle;
@@ -119,6 +127,8 @@
mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
mPulsing = mStatusBarStateController.isPulsing();
mShadeStateEvents.addShadeStateEventsListener(this);
+ mJavaAdapter.alwaysCollectFlow(mShadeAnimationInteractor.isAnyCloseAnimationRunning(),
+ this::onShadeOrQsClosingChanged);
pipeline.setVisualStabilityManager(mNotifStabilityManager);
}
@@ -322,10 +332,9 @@
}
}
- @Override
- public void onPanelCollapsingChanged(boolean isCollapsing) {
- mNotifPanelCollapsing = isCollapsing;
- updateAllowedStates("notifPanelCollapsing", isCollapsing);
+ private void onShadeOrQsClosingChanged(boolean isClosing) {
+ mNotifPanelCollapsing = isClosing;
+ updateAllowedStates("notifPanelCollapsing", isClosing);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
index b1e52af..ecca973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
@@ -305,8 +305,6 @@
}
}
}
- // Recalculate all icon positions, to reflect our updates.
- view.calculateIconXTranslations()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
index 3a2e21a..0331654 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
@@ -21,6 +21,7 @@
import com.android.internal.util.ContrastColorUtil
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.StatusBarIconView.NO_COLOR
import com.android.systemui.statusbar.notification.NotificationUtils
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconColors
import kotlinx.coroutines.flow.Flow
@@ -54,7 +55,8 @@
iconColors.collect { colors ->
val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L)
val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil)
- view.staticDrawableColor = colors.staticDrawableColor(view.viewBounds, isColorized)
+ view.staticDrawableColor =
+ if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR
view.setDecorColor(colors.tint)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconColors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconColors.kt
index 97d1e1b..2365db4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconColors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconColors.kt
@@ -35,5 +35,5 @@
* Returns the color to be applied to an icon, based on that icon's view bounds and whether or
* not the notification icon is colorized.
*/
- fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int
+ fun staticDrawableColor(viewBounds: Rect): Int
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
index af37e49..6e5ac47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
@@ -117,8 +117,8 @@
override val tint: Int,
private val areas: Collection<Rect>,
) : NotificationIconColors {
- override fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int {
- return if (isColorized && DarkIconDispatcher.isInAreas(areas, viewBounds)) {
+ override fun staticDrawableColor(viewBounds: Rect): Int {
+ return if (DarkIconDispatcher.isInAreas(areas, viewBounds)) {
tint
} else {
DarkIconDispatcher.DEFAULT_ICON_TINT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 8eda96f..f6431a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -156,7 +156,7 @@
new int[]{com.android.internal.R.attr.state_hovered},
new int[]{}},
- new int[]{tintColor, tintColor, tintColor}
+ new int[]{tintColor, 0, tintColor}
);
mBackground.setTintMode(PorterDuff.Mode.SRC_ATOP);
mBackground.setTintList(stateList);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index 5e60b5f..7b2caea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -82,6 +82,8 @@
}
launch { viewModel.translationY.collect { controller.setTranslationY(it) } }
+
+ launch { viewModel.alpha.collect { controller.setMaxAlphaForExpansion(it) } }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 1febaf9..da847c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -24,6 +24,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.util.kotlin.sample
@@ -38,6 +39,7 @@
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
@@ -50,6 +52,7 @@
keyguardInteractor: KeyguardInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val shadeInteractor: ShadeInteractor,
+ occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
) {
private val statesForConstrainedNotifications =
setOf(
@@ -144,14 +147,20 @@
initialValue = NotificationContainerBounds(0f, 0f),
)
+ val alpha: Flow<Float> = occludedToLockscreenTransitionViewModel.lockscreenAlpha
+
/**
* Under certain scenarios, such as swiping up on the lockscreen, the container will need to be
* translated as the keyguard fades out.
*/
val translationY: Flow<Float> =
- combine(isOnLockscreen, keyguardInteractor.keyguardTranslationY) {
+ combine(
isOnLockscreen,
- translationY ->
+ merge(
+ keyguardInteractor.keyguardTranslationY,
+ occludedToLockscreenTransitionViewModel.lockscreenTranslationY,
+ )
+ ) { isOnLockscreen, translationY ->
if (isOnLockscreen) {
translationY
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 824de01..2df30dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -90,8 +90,13 @@
private int mLastConfigurationWidthDp = -1;
private int mLastConfigurationHeightDp = -1;
- private List<Runnable> mOnCreateRunnables = new ArrayList<>();
+ private final List<Runnable> mOnCreateRunnables = new ArrayList<>();
+ /**
+ * @deprecated Don't subclass SystemUIDialog. Please subclass {@link Delegate} and pass it to
+ * {@link Factory#create(DialogDelegate)} to create a custom dialog.
+ */
+ @Deprecated
public SystemUIDialog(Context context) {
this(context, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK);
}
@@ -109,27 +114,7 @@
Dependency.get(SystemUIDialogManager.class),
Dependency.get(SysUiState.class),
Dependency.get(BroadcastDispatcher.class),
- Dependency.get(DialogLaunchAnimator.class),
- new DialogDelegate<>() {});
- }
-
- @Inject
- public SystemUIDialog(
- @Application Context context,
- FeatureFlags featureFlags,
- SystemUIDialogManager systemUIDialogManager,
- SysUiState sysUiState,
- BroadcastDispatcher broadcastDispatcher,
- DialogLaunchAnimator dialogLaunchAnimator) {
- this(context,
- DEFAULT_THEME,
- DEFAULT_DISMISS_ON_DEVICE_LOCK,
- featureFlags,
- systemUIDialogManager,
- sysUiState,
- broadcastDispatcher,
- dialogLaunchAnimator,
- new DialogDelegate<>(){});
+ Dependency.get(DialogLaunchAnimator.class));
}
public static class Factory {
@@ -156,11 +141,25 @@
mDialogLaunchAnimator = dialogLaunchAnimator;
}
+ /** Creates a new instance of {@link SystemUIDialog} with no customized behavior.
+ *
+ * When you just need a dialog, call this.
+ */
+ public SystemUIDialog create() {
+ return create(new DialogDelegate<>(){});
+ }
+
/**
* Creates a new instance of {@link SystemUIDialog} with {@code delegate} as the {@link
- * DialogDelegate}.
+ * Delegate}.
+ *
+ * When you need to customize the dialog, pass it a delegate.
*/
- public SystemUIDialog create(DialogDelegate<SystemUIDialog> delegate) {
+ public SystemUIDialog create(Delegate delegate) {
+ return create((DialogDelegate<SystemUIDialog>) delegate);
+ }
+
+ private SystemUIDialog create(DialogDelegate<SystemUIDialog> dialogDelegate) {
return new SystemUIDialog(
mContext,
DEFAULT_THEME,
@@ -170,7 +169,7 @@
mSysUiState,
mBroadcastDispatcher,
mDialogLaunchAnimator,
- delegate);
+ dialogDelegate);
}
}
@@ -588,4 +587,18 @@
mDialog.dismiss();
}
}
+
+ /**
+ * A delegate class that should be implemented in place of sublcassing {@link SystemUIDialog}.
+ *
+ * Implement this interface and then pass an instance of your implementation to
+ * {@link SystemUIDialog.Factory#create(Delegate)}.
+ */
+ public interface Delegate extends DialogDelegate<SystemUIDialog> {
+ /**
+ * Returns a new {@link SystemUIDialog} which has been passed this Delegate in its
+ * construction.
+ */
+ SystemUIDialog createDialog();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
index f5e9034..93db916 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
@@ -46,7 +46,8 @@
/** Model for {@link #darkChangeFlow()} */
class DarkChange {
- public static final DarkChange EMPTY = new DarkChange(new ArrayList<>(), 0, 0);
+ public static final DarkChange EMPTY =
+ new DarkChange(new ArrayList<>(), /* darkIntensity= */ 0f, DEFAULT_ICON_TINT);
public DarkChange(Collection<Rect> areas, float darkIntensity, int tint) {
this.areas = areas;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
index 75ae16e..0f2da2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
@@ -26,6 +26,10 @@
import com.android.systemui.qs.tiles.UiModeNightTile
import com.android.systemui.qs.tiles.WorkModeTile
import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
+import com.android.systemui.qs.tiles.impl.alarm.domain.AlarmTileMapper
+import com.android.systemui.qs.tiles.impl.alarm.domain.interactor.AlarmTileDataInteractor
+import com.android.systemui.qs.tiles.impl.alarm.domain.interactor.AlarmTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
import com.android.systemui.qs.tiles.impl.flashlight.domain.FlashlightMapper
import com.android.systemui.qs.tiles.impl.flashlight.domain.interactor.FlashlightTileDataInteractor
import com.android.systemui.qs.tiles.impl.flashlight.domain.interactor.FlashlightTileUserActionInteractor
@@ -59,6 +63,7 @@
companion object {
const val FLASHLIGHT_TILE_SPEC = "flashlight"
const val LOCATION_TILE_SPEC = "location"
+ const val ALARM_TILE_SPEC = "alarm"
/** Inject flashlight config */
@Provides
@@ -123,6 +128,38 @@
stateInteractor,
mapper,
)
+
+ /** Inject alarm config */
+ @Provides
+ @IntoMap
+ @StringKey(ALARM_TILE_SPEC)
+ fun provideAlarmTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(ALARM_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.ic_alarm,
+ labelRes = R.string.status_bar_alarm,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
+
+ /** Inject AlarmTile into tileViewModelMap in QSModule */
+ @Provides
+ @IntoMap
+ @StringKey(ALARM_TILE_SPEC)
+ fun provideAlarmTileViewModel(
+ factory: QSTileViewModelFactory.Static<AlarmTileModel>,
+ mapper: AlarmTileMapper,
+ stateInteractor: AlarmTileDataInteractor,
+ userActionInteractor: AlarmTileUserActionInteractor
+ ): QSTileViewModel =
+ factory.create(
+ TileSpec.create(ALARM_TILE_SPEC),
+ userActionInteractor,
+ stateInteractor,
+ mapper,
+ )
}
/** Inject FlashlightTile into tileMap in QSModule */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 39cdfa3..fa0cb5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -143,6 +143,8 @@
mSetupObserver.register();
mUserManager = context.getSystemService(UserManager.class);
mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(handler));
+ // This registers the alarm broadcast receiver for the current user
+ mUserChangedCallback.onUserChanged(getCurrentUser(), context);
dumpManager.registerDumpable(getClass().getSimpleName(), this);
}
@@ -214,6 +216,7 @@
@Override
public long getNextAlarm() {
+ // TODO(b/314799105): Migrate usages to NextAlarmController
final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
return info != null ? info.getTriggerTime() : 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
index 10fc83c..ff73e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
@@ -21,6 +21,7 @@
import com.android.systemui.shade.NotificationPanelUnfoldAnimationController
import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController
import com.android.systemui.unfold.dagger.UnfoldBg
+import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
@@ -106,4 +107,20 @@
fun getUnfoldLatencyTracker(): UnfoldLatencyTracker
fun getNaturalRotationUnfoldProgressProvider(): NaturalRotationUnfoldProgressProvider
+
+ /** Creates a UnfoldTransitionProgressProvider that calculates progress in the main thread. */
+ fun getUnfoldTransitionProgressProvider(): UnfoldTransitionProgressProvider
+
+ /** Creates a UnfoldTransitionProgressProvider that calculates progress in the background. */
+ @UnfoldBg
+ fun getBgUnfoldTransitionProgressProvider(): UnfoldTransitionProgressProvider
+
+ /** Creates a UnfoldTransitionProgressForwarder. */
+ fun getUnfoldTransitionProgressForwarder(): UnfoldTransitionProgressForwarder
+
+ /** Creates a FoldStateLoggingProvider. */
+ fun getFoldStateLoggingProvider(): Optional<FoldStateLoggingProvider>
+
+ /** Creates a FoldStateLogger. */
+ fun getFoldStateLogger(): Optional<FoldStateLogger>
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index e7e907a..e4f1c87 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -25,6 +25,7 @@
import android.content.IntentFilter;
import android.debug.IAdbManager;
import android.hardware.usb.UsbManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ServiceManager;
@@ -69,8 +70,7 @@
super.onCreate(icicle);
// Emulator does not support reseating the usb cable to reshow the dialog.
- boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1");
- if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !isEmulator) {
+ if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !Build.IS_EMULATOR) {
mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
mBroadcastDispatcher.registerReceiver(mDisconnectedReceiver, filter);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index b403d1d..6f58bc2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -31,15 +31,16 @@
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.log.LogBuffer
-import com.android.systemui.plugins.ClockAnimations
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockEvents
-import com.android.systemui.plugins.ClockFaceConfig
-import com.android.systemui.plugins.ClockFaceController
-import com.android.systemui.plugins.ClockFaceEvents
-import com.android.systemui.plugins.ClockTickRate
+import com.android.systemui.plugins.clocks.ClockAnimations
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockEvents
+import com.android.systemui.plugins.clocks.ClockFaceConfig
+import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockFaceEvents
+import com.android.systemui.plugins.clocks.ClockTickRate
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -97,6 +98,7 @@
@Mock private lateinit var largeLogBuffer: LogBuffer
@Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
private lateinit var underTest: ClockEventController
+ @Mock private lateinit var zenModeController: ZenModeController
@Before
fun setUp() {
@@ -140,7 +142,8 @@
bgExecutor,
smallLogBuffer,
largeLogBuffer,
- withDeps.featureFlags
+ withDeps.featureFlags,
+ zenModeController
)
underTest.clock = clock
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
index adf0ada..2bbf0df 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
@@ -44,13 +44,13 @@
import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel;
import com.android.systemui.log.LogBuffer;
-import com.android.systemui.plugins.ClockAnimations;
-import com.android.systemui.plugins.ClockController;
-import com.android.systemui.plugins.ClockEvents;
-import com.android.systemui.plugins.ClockFaceConfig;
-import com.android.systemui.plugins.ClockFaceController;
-import com.android.systemui.plugins.ClockFaceEvents;
-import com.android.systemui.plugins.ClockTickRate;
+import com.android.systemui.plugins.clocks.ClockAnimations;
+import com.android.systemui.plugins.clocks.ClockController;
+import com.android.systemui.plugins.clocks.ClockEvents;
+import com.android.systemui.plugins.clocks.ClockFaceConfig;
+import com.android.systemui.plugins.clocks.ClockFaceController;
+import com.android.systemui.plugins.clocks.ClockFaceEvents;
+import com.android.systemui.plugins.clocks.ClockTickRate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.AnimatableClockView;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index cb26e61..e8d86dd 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -35,8 +35,8 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.plugins.ClockFaceConfig;
-import com.android.systemui.plugins.ClockTickRate;
+import com.android.systemui.plugins.clocks.ClockFaceConfig;
+import com.android.systemui.plugins.clocks.ClockTickRate;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.statusbar.StatusBarState;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index e54b184..4508aea 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -40,10 +40,10 @@
import android.widget.FrameLayout;
import android.widget.TextView;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ClockController;
-import com.android.systemui.plugins.ClockFaceController;
+import com.android.systemui.plugins.clocks.ClockController;
+import com.android.systemui.plugins.clocks.ClockFaceController;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.StatusBarState;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 9c3288b..fad8552 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -37,8 +37,8 @@
import com.android.app.animation.Interpolators;
import com.android.systemui.animation.ViewHierarchyAnimator;
-import com.android.systemui.plugins.ClockConfig;
-import com.android.systemui.plugins.ClockController;
+import com.android.systemui.plugins.clocks.ClockConfig;
+import com.android.systemui.plugins.clocks.ClockController;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt
index 6c91c98..2d5c2ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt
@@ -27,8 +27,6 @@
import com.android.systemui.biometrics.AuthController
import com.android.systemui.decor.FaceScanningProviderFactory
import com.android.systemui.dump.logcatLogBuffer
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.util.mockito.whenever
@@ -55,8 +53,6 @@
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock private lateinit var display: Display
-
private val displayId = 2
@Before
@@ -82,8 +78,6 @@
R.bool.config_fillMainBuiltInDisplayCutout,
true
)
- val featureFlags = FakeFeatureFlags()
- featureFlags.set(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION, true)
underTest =
FaceScanningProviderFactory(
authController,
@@ -92,7 +86,6 @@
keyguardUpdateMonitor,
mock(Executor::class.java),
ScreenDecorationsLogger(logcatLogBuffer("FaceScanningProviderFactoryTest")),
- featureFlags,
)
whenever(authController.faceSensorLocation).thenReturn(Point(10, 10))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index af88df7..639276e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -78,7 +78,6 @@
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.systemui.res.R;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.decor.CornerDecorProvider;
@@ -93,10 +92,9 @@
import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl;
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegate;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.log.ScreenDecorationsLogger;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.commandline.CommandRegistry;
@@ -229,16 +227,13 @@
doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders();
doReturn(mMockCutoutList).when(mCutoutFactory).getProviders();
- FakeFeatureFlags featureFlags = new FakeFeatureFlags();
- featureFlags.set(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION, true);
mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
BOUNDS_POSITION_TOP,
mAuthController,
mStatusBarStateController,
mKeyguardUpdateMonitor,
mExecutor,
- new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")),
- featureFlags));
+ new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer"))));
mScreenDecorations = spy(new ScreenDecorations(mContext, mSecureSettings,
mCommandRegistry, mUserTracker, mDisplayTracker, mDotViewController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
index 0ff8da5..8c8544c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
@@ -20,16 +20,14 @@
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
@@ -60,14 +58,13 @@
@Rule
public MockitoRule rule = MockitoJUnit.rule();
- @Mock
- FingerprintManager mFingerprintManager;
- @Mock
- FaceManager mFaceManager;
- @Mock
- SystemUIDialog mDialog;
+ @Mock Resources mResources;
+ @Mock FingerprintManager mFingerprintManager;
+ @Mock FaceManager mFaceManager;
+ @Mock SystemUIDialog.Factory mSystemUIDialogFactory;
+ @Mock SystemUIDialog mDialog;
+ @Mock BiometricNotificationDialogFactory.ActivityStarter mActivityStarter;
- private Context mContextSpy;
private final ArgumentCaptor<DialogInterface.OnClickListener> mOnClickListenerArgumentCaptor =
ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
private final ArgumentCaptor<Intent> mIntentArgumentCaptor =
@@ -76,15 +73,16 @@
@Before
public void setUp() throws ExecutionException, InterruptedException {
- mContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
- mContext.addMockSystemService(FaceManager.class, mFaceManager);
- mContextSpy = spy(mContext);
-
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
- doNothing().when(mContextSpy).startActivity(any());
+ when(mSystemUIDialogFactory.create()).thenReturn(mDialog);
- mDialogFactory = new BiometricNotificationDialogFactory();
+ mDialogFactory = new BiometricNotificationDialogFactory(
+ mResources,
+ mSystemUIDialogFactory,
+ mFingerprintManager,
+ mFaceManager
+ );
}
@Test
@@ -92,8 +90,7 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
- mDialogFactory.createReenrollDialog(mContextSpy, mDialog,
- BiometricSourceType.FINGERPRINT);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -108,7 +105,7 @@
removalCallbackArgumentCaptor.getValue().onRemovalSucceeded(null /* fp */,
0 /* remaining */);
- verify(mContextSpy).startActivity(mIntentArgumentCaptor.capture());
+ verify(mActivityStarter).startActivity(mIntentArgumentCaptor.capture());
assertThat(mIntentArgumentCaptor.getValue().getAction()).isEqualTo(
Settings.ACTION_FINGERPRINT_ENROLL);
}
@@ -118,8 +115,7 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
- mDialogFactory.createReenrollDialog(mContextSpy, mDialog,
- BiometricSourceType.FINGERPRINT);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -134,7 +130,7 @@
removalCallbackArgumentCaptor.getValue().onRemovalError(null /* fp */,
0 /* errmsgId */, "Error" /* errString */);
- verify(mContextSpy, never()).startActivity(any());
+ verify(mActivityStarter, never()).startActivity(any());
}
@Test
@@ -142,8 +138,7 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FACE));
- mDialogFactory.createReenrollDialog(mContextSpy, mDialog,
- BiometricSourceType.FACE);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -158,7 +153,7 @@
removalCallbackArgumentCaptor.getValue().onRemovalSucceeded(null /* fp */,
0 /* remaining */);
- verify(mContextSpy).startActivity(mIntentArgumentCaptor.capture());
+ verify(mActivityStarter).startActivity(mIntentArgumentCaptor.capture());
assertThat(mIntentArgumentCaptor.getValue().getAction()).isEqualTo(
"android.settings.FACE_ENROLL");
}
@@ -168,8 +163,7 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FACE));
- mDialogFactory.createReenrollDialog(mContextSpy, mDialog,
- BiometricSourceType.FACE);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -184,6 +178,6 @@
removalCallbackArgumentCaptor.getValue().onRemovalError(null /* face */,
0 /* errmsgId */, "Error" /* errString */);
- verify(mContextSpy, never()).startActivity(any());
+ verify(mActivityStarter, never()).startActivity(any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
index 3c10678..c6771b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
@@ -18,9 +18,7 @@
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG;
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
-
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.never;
@@ -71,6 +69,8 @@
@Mock
NotificationManager mNotificationManager;
@Mock
+ BiometricNotificationDialogFactory mNotificationDialogFactory;
+ @Mock
Optional<FingerprintReEnrollNotification> mFingerprintReEnrollNotificationOptional;
@Mock
FingerprintReEnrollNotification mFingerprintReEnrollNotification;
@@ -103,9 +103,8 @@
mLooper = TestableLooper.get(this);
Handler handler = new Handler(mLooper.getLooper());
- BiometricNotificationDialogFactory dialogFactory = new BiometricNotificationDialogFactory();
BiometricNotificationBroadcastReceiver broadcastReceiver =
- new BiometricNotificationBroadcastReceiver(mContext, dialogFactory);
+ new BiometricNotificationBroadcastReceiver(mContext, mNotificationDialogFactory);
mBiometricNotificationService =
new BiometricNotificationService(mContext,
mKeyguardUpdateMonitor, mKeyguardStateController, handler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
index dfb18b9..f5f1622 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
@@ -17,29 +17,23 @@
package com.android.systemui.biometrics.ui.viewmodel
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.TestMocksModule
-import com.android.systemui.collectLastValue
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.keyguard.ui.viewmodel.deviceEntryIconViewModelTransitionsMock
+import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.user.domain.UserDomainLayerModule
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.statusbar.phone.systemUIDialogManager
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
-import dagger.BindsInstance
-import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -53,35 +47,11 @@
@SmallTest
@RunWith(JUnit4::class)
class DeviceEntryUdfpsTouchOverlayViewModelTest : SysuiTestCase() {
- @Captor
- private lateinit var sysuiDialogListenerCaptor: ArgumentCaptor<SystemUIDialogManager.Listener>
- private var systemUIDialogManager: SystemUIDialogManager = mock()
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- }
-
- @SysUISingleton
- @Component(
- modules =
- [
- SysUITestModule::class,
- UserDomainLayerModule::class,
- ]
- )
- interface TestComponent : SysUITestComponent<DeviceEntryUdfpsTouchOverlayViewModel> {
- val keyguardRepository: FakeKeyguardRepository
- val shadeRepository: FakeShadeRepository
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- featureFlags: FakeFeatureFlagsClassicModule,
- mocks: TestMocksModule,
- ): TestComponent
+ val kosmos =
+ testKosmos().apply {
+ featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }
}
- }
+ val testScope = kosmos.testScope
private val testDeviceEntryIconTransitionAlpha = MutableStateFlow(0f)
private val testDeviceEntryIconTransition: DeviceEntryIconTransition
@@ -90,60 +60,59 @@
override val deviceEntryParentViewAlpha: Flow<Float> =
testDeviceEntryIconTransitionAlpha.asStateFlow()
}
- private val testComponent: TestComponent =
- DaggerDeviceEntryUdfpsTouchOverlayViewModelTest_TestComponent.factory()
- .create(
- test = this,
- featureFlags =
- FakeFeatureFlagsClassicModule { set(Flags.FULL_SCREEN_USER_SWITCHER, true) },
- mocks =
- TestMocksModule(
- systemUIDialogManager = systemUIDialogManager,
- deviceEntryIconTransitions =
- setOf(
- testDeviceEntryIconTransition,
- )
- ),
- )
+
+ init {
+ kosmos.deviceEntryIconViewModelTransitionsMock.add(testDeviceEntryIconTransition)
+ }
+ val systemUIDialogManager = kosmos.systemUIDialogManager
+ private val underTest = kosmos.deviceEntryUdfpsTouchOverlayViewModel
+
+ @Captor
+ private lateinit var sysuiDialogListenerCaptor: ArgumentCaptor<SystemUIDialogManager.Listener>
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
@Test
fun dialogShowing_shouldHandleTouchesFalse() =
- testComponent.runTest {
+ testScope.runTest {
val shouldHandleTouches by collectLastValue(underTest.shouldHandleTouches)
- runCurrent()
testDeviceEntryIconTransitionAlpha.value = 1f
+ runCurrent()
+
verify(systemUIDialogManager).registerListener(sysuiDialogListenerCaptor.capture())
sysuiDialogListenerCaptor.value.shouldHideAffordances(true)
- runCurrent()
assertThat(shouldHandleTouches).isFalse()
}
@Test
fun transitionAlphaIsSmall_shouldHandleTouchesFalse() =
- testComponent.runTest {
+ testScope.runTest {
val shouldHandleTouches by collectLastValue(underTest.shouldHandleTouches)
- runCurrent()
testDeviceEntryIconTransitionAlpha.value = .3f
+ runCurrent()
+
verify(systemUIDialogManager).registerListener(sysuiDialogListenerCaptor.capture())
sysuiDialogListenerCaptor.value.shouldHideAffordances(false)
- runCurrent()
assertThat(shouldHandleTouches).isFalse()
}
@Test
fun alphaFullyShowing_noDialog_shouldHandleTouchesTrue() =
- testComponent.runTest {
+ testScope.runTest {
val shouldHandleTouches by collectLastValue(underTest.shouldHandleTouches)
- runCurrent()
testDeviceEntryIconTransitionAlpha.value = 1f
+ runCurrent()
+
verify(systemUIDialogManager).registerListener(sysuiDialogListenerCaptor.capture())
sysuiDialogListenerCaptor.value.shouldHideAffordances(false)
- runCurrent()
assertThat(shouldHandleTouches).isTrue()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogDelegateTest.java
similarity index 61%
rename from packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogDelegateTest.java
index eee0ed4..4022d43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogDelegateTest.java
@@ -16,8 +16,10 @@
package com.android.systemui.bluetooth;
+import static com.android.systemui.statusbar.phone.SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK;
import static com.google.common.truth.Truth.assertThat;
-
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -26,31 +28,41 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.systemui.res.R;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
+import com.android.systemui.broadcast.BroadcastSender;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.res.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class BroadcastDialogTest extends SysuiTestCase {
+public class BroadcastDialogDelegateTest extends SysuiTestCase {
private static final String CURRENT_BROADCAST_APP = "Music";
private static final String SWITCH_APP = "System UI";
@@ -61,33 +73,64 @@
private final LocalBluetoothLeBroadcast mLocalBluetoothLeBroadcast = mock(
LocalBluetoothLeBroadcast.class);
private final BroadcastSender mBroadcastSender = mock(BroadcastSender.class);
- private BroadcastDialog mBroadcastDialog;
- private View mDialogView;
+ private BroadcastDialogDelegate mBroadcastDialogDelegate;
+ private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
+ @Mock SystemUIDialog.Factory mSystemUIDialogFactory;
+ @Mock SystemUIDialogManager mDialogManager;
+ @Mock SysUiState mSysUiState;
+ @Mock DialogLaunchAnimator mDialogLaunchAnimator;
+ @Mock MediaOutputDialogFactory mMediaOutputDialogFactory;
+ private SystemUIDialog mDialog;
private TextView mTitle;
private TextView mSubTitle;
private Button mSwitchBroadcastAppButton;
private Button mChangeOutputButton;
+ private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
- mBroadcastDialog = new BroadcastDialog(mContext, mock(MediaOutputDialogFactory.class),
- mLocalBluetoothManager, CURRENT_BROADCAST_APP, TEST_PACKAGE,
- mock(UiEventLogger.class), mBroadcastSender);
- mBroadcastDialog.show();
- mDialogView = mBroadcastDialog.mDialogView;
+
+ mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM, true);
+ when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
+ when(mSystemUIDialogFactory.create(any())).thenReturn(mDialog);
+
+ mBroadcastDialogDelegate = new BroadcastDialogDelegate(
+ mContext,
+ mMediaOutputDialogFactory,
+ mLocalBluetoothManager,
+ new UiEventLoggerFake(),
+ mFakeExecutor,
+ mBroadcastSender,
+ mSystemUIDialogFactory,
+ CURRENT_BROADCAST_APP,
+ TEST_PACKAGE);
+
+ mDialog = new SystemUIDialog(
+ mContext,
+ 0,
+ DEFAULT_DISMISS_ON_DEVICE_LOCK,
+ mFeatureFlags,
+ mDialogManager,
+ mSysUiState,
+ getFakeBroadcastDispatcher(),
+ mDialogLaunchAnimator,
+ mBroadcastDialogDelegate
+ );
+
+ mDialog.show();
}
@After
public void tearDown() {
- mBroadcastDialog.dismiss();
+ mDialog.dismiss();
}
@Test
public void onCreate_withCurrentApp_titleIsCurrentAppName() {
- mTitle = mDialogView.requireViewById(R.id.dialog_title);
+ mTitle = mDialog.requireViewById(R.id.dialog_title);
assertThat(mTitle.getText().toString()).isEqualTo(mContext.getString(
R.string.bt_le_audio_broadcast_dialog_title, CURRENT_BROADCAST_APP));
@@ -95,7 +138,7 @@
@Test
public void onCreate_withCurrentApp_subTitleIsSwitchAppName() {
- mSubTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
+ mSubTitle = mDialog.requireViewById(R.id.dialog_subtitle);
assertThat(mSubTitle.getText()).isEqualTo(
mContext.getString(R.string.bt_le_audio_broadcast_dialog_sub_title, SWITCH_APP));
@@ -103,7 +146,7 @@
@Test
public void onCreate_withCurrentApp_switchBtnIsSwitchAppName() {
- mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+ mSwitchBroadcastAppButton = mDialog.requireViewById(R.id.switch_broadcast);
assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo(
mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP));
@@ -111,17 +154,17 @@
@Test
public void onClick_withChangeOutput_dismissBroadcastDialog() {
- mChangeOutputButton = mDialogView.requireViewById(R.id.change_output);
+ mChangeOutputButton = mDialog.requireViewById(R.id.change_output);
mChangeOutputButton.performClick();
- assertThat(mBroadcastDialog.isShowing()).isFalse();
+ assertThat(mDialog.isShowing()).isFalse();
}
@Test
public void onClick_withSwitchBroadcast_stopCurrentBroadcast() {
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
mLocalBluetoothLeBroadcast);
- mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+ mSwitchBroadcastAppButton = mDialog.requireViewById(R.id.switch_broadcast);
mSwitchBroadcastAppButton.performClick();
verify(mLocalBluetoothLeBroadcast).stopLatestBroadcast();
@@ -129,7 +172,7 @@
@Test
public void onClick_withSwitchBroadcast_stopCurrentBroadcastFailed() {
- mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+ mSwitchBroadcastAppButton = mDialog.requireViewById(R.id.switch_broadcast);
mSwitchBroadcastAppButton.performClick();
assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo(
@@ -139,9 +182,9 @@
@Test
public void handleLeBroadcastStopped_withBroadcastProfileNull_doRefreshButton() {
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
- mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+ mSwitchBroadcastAppButton = mDialog.requireViewById(R.id.switch_broadcast);
- mBroadcastDialog.handleLeBroadcastStopped();
+ mBroadcastDialogDelegate.handleLeBroadcastStopped();
assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo(
mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP));
@@ -152,7 +195,7 @@
when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
mLocalBluetoothLeBroadcast);
- mBroadcastDialog.handleLeBroadcastStopped();
+ mBroadcastDialogDelegate.handleLeBroadcastStopped();
verify(mLocalBluetoothLeBroadcast).startBroadcast(eq(SWITCH_APP), any());
}
@@ -160,17 +203,17 @@
@Test
public void handleLeBroadcastMetadataChanged_withNotLaunchFlag_doNotDismissDialog() {
- mBroadcastDialog.handleLeBroadcastMetadataChanged();
+ mBroadcastDialogDelegate.handleLeBroadcastMetadataChanged();
- assertThat(mBroadcastDialog.isShowing()).isTrue();
+ assertThat(mDialog.isShowing()).isTrue();
}
@Test
public void handleLeBroadcastMetadataChanged_withLaunchFlag_dismissDialog() {
- mBroadcastDialog.handleLeBroadcastStarted();
- mBroadcastDialog.handleLeBroadcastMetadataChanged();
+ mBroadcastDialogDelegate.handleLeBroadcastStarted();
+ mBroadcastDialogDelegate.handleLeBroadcastMetadataChanged();
- assertThat(mBroadcastDialog.isShowing()).isFalse();
+ assertThat(mDialog.isShowing()).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index 9671966..c425e82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -444,6 +444,7 @@
verify(mClipboardOverlayView, never()).setMinimized(true);
verify(mClipboardOverlayView).setMinimized(false);
+ verify(mClipboardOverlayView).getEnterAnimation();
verify(mClipboardOverlayView).showTextPreview("Test Item", false);
}
@@ -458,6 +459,7 @@
verify(mClipboardOverlayView).setMinimized(true);
verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_SHOWN_MINIMIZED, 0, "abc");
+ verify(mClipboardOverlayView).getEnterAnimation();
verify(mClipboardOverlayView, never()).setMinimized(false);
verify(mClipboardOverlayView, never()).showTextPreview(any(), anyBoolean());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
new file mode 100644
index 0000000..c5c0208
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.common.ui.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+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.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoAnnotations
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ConfigurationInteractorTest : SysuiTestCase() {
+ private lateinit var testScope: TestScope
+ private lateinit var underTest: ConfigurationInteractor
+ private lateinit var configurationRepository: FakeConfigurationRepository
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ configurationRepository = FakeConfigurationRepository()
+ testScope = TestScope()
+ underTest = ConfigurationInteractor(configurationRepository)
+ }
+
+ @Test
+ fun dimensionPixelSize() =
+ testScope.runTest {
+ val resourceId = 1001
+ val pixelSize = 501
+ configurationRepository.setDimensionPixelSize(resourceId, pixelSize)
+
+ val dimensionPixelSize by collectLastValue(underTest.dimensionPixelSize(resourceId))
+
+ configurationRepository.onAnyConfigurationChange()
+
+ assertThat(dimensionPixelSize).isEqualTo(pixelSize)
+ }
+
+ @Test
+ fun dimensionPixelSizes() =
+ testScope.runTest {
+ val resourceId1 = 1001
+ val pixelSize1 = 501
+ val resourceId2 = 1002
+ val pixelSize2 = 502
+ configurationRepository.setDimensionPixelSize(resourceId1, pixelSize1)
+ configurationRepository.setDimensionPixelSize(resourceId2, pixelSize2)
+
+ val dimensionPixelSizes by
+ collectLastValue(underTest.dimensionPixelSize(setOf(resourceId1, resourceId2)))
+
+ configurationRepository.onAnyConfigurationChange()
+
+ assertThat(dimensionPixelSizes!![resourceId1]).isEqualTo(pixelSize1)
+ assertThat(dimensionPixelSizes!![resourceId2]).isEqualTo(pixelSize2)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt
new file mode 100644
index 0000000..e931384
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.contrast
+
+import android.app.UiModeManager
+import android.app.UiModeManager.ContrastUtils.fromContrastLevel
+import android.os.Looper
+import android.provider.Settings
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.LayoutInflater
+import android.widget.FrameLayout
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.model.SysUiState
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/** Test the behaviour of buttons of the [ContrastDialogDelegate]. */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class ContrastDialogDelegateTest : SysuiTestCase() {
+
+ private val mainExecutor = FakeExecutor(FakeSystemClock())
+ private lateinit var mContrastDialogDelegate: ContrastDialogDelegate
+ @Mock private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
+ @Mock private lateinit var sysuiDialog: SystemUIDialog
+ @Mock private lateinit var mockUiModeManager: UiModeManager
+ @Mock private lateinit var mockUserTracker: UserTracker
+ @Mock private lateinit var mockSecureSettings: SecureSettings
+ @Mock private lateinit var sysuiState: SysUiState
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ mDependency.injectTestDependency(FeatureFlags::class.java, FakeFeatureFlags())
+ mDependency.injectTestDependency(SysUiState::class.java, sysuiState)
+ mDependency.injectMockDependency(DialogLaunchAnimator::class.java)
+ whenever(sysuiState.setFlag(any(), any())).thenReturn(sysuiState)
+ whenever(sysuiDialogFactory.create(any())).thenReturn(sysuiDialog)
+ whenever(sysuiDialog.layoutInflater).thenReturn(LayoutInflater.from(mContext))
+
+ whenever(mockUserTracker.userId).thenReturn(context.userId)
+ if (Looper.myLooper() == null) Looper.prepare()
+
+ mContrastDialogDelegate =
+ ContrastDialogDelegate(
+ sysuiDialogFactory,
+ mainExecutor,
+ mockUiModeManager,
+ mockUserTracker,
+ mockSecureSettings
+ )
+ }
+
+ @Test
+ fun testClickButtons_putsContrastInSettings() {
+ mContrastDialogDelegate.onCreate(sysuiDialog, null)
+
+ mContrastDialogDelegate.contrastButtons.forEach {
+ (contrastLevel: Int, clickedButton: FrameLayout) ->
+ clickedButton.performClick()
+ mainExecutor.runAllReady()
+ verify(mockSecureSettings)
+ .putFloatForUser(
+ eq(Settings.Secure.CONTRAST_LEVEL),
+ eq(fromContrastLevel(contrastLevel)),
+ eq(context.userId)
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogTest.kt
deleted file mode 100644
index 7753197..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogTest.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.contrast
-
-import android.app.UiModeManager
-import android.app.UiModeManager.ContrastUtils.fromContrastLevel
-import android.os.Looper
-import android.provider.Settings
-import android.testing.AndroidTestingRunner
-import android.widget.FrameLayout
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.settings.SecureSettings
-import com.google.common.util.concurrent.MoreExecutors
-import java.util.concurrent.Executor
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.eq
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-/** Test the behaviour of buttons of the [ContrastDialog]. */
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class ContrastDialogTest : SysuiTestCase() {
-
- private lateinit var mainExecutor: Executor
- private lateinit var contrastDialog: ContrastDialog
- @Mock private lateinit var mockUiModeManager: UiModeManager
- @Mock private lateinit var mockUserTracker: UserTracker
- @Mock private lateinit var mockSecureSettings: SecureSettings
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- mainExecutor = MoreExecutors.directExecutor()
- whenever(mockUserTracker.userId).thenReturn(context.userId)
- }
-
- @Test
- fun testClickButtons_putsContrastInSettings() {
- if (Looper.myLooper() == null) Looper.prepare()
- contrastDialog =
- ContrastDialog(
- context,
- mainExecutor,
- mockUiModeManager,
- mockUserTracker,
- mockSecureSettings
- )
- contrastDialog.show()
- try {
- contrastDialog.contrastButtons.forEach {
- (contrastLevel: Int, clickedButton: FrameLayout) ->
- clickedButton.performClick()
- verify(mockSecureSettings)
- .putFloatForUser(
- eq(Settings.Secure.CONTRAST_LEVEL),
- eq(fromContrastLevel(contrastLevel)),
- eq(context.userId)
- )
- }
- } finally {
- contrastDialog.dismiss()
- }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
index bc40c2d..d75cbec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
@@ -18,6 +18,7 @@
import android.provider.Settings
import androidx.test.filters.SmallTest
+import com.android.keyguard.ClockEventController
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.shared.model.SettingsClockSize
@@ -47,6 +48,7 @@
private lateinit var underTest: KeyguardClockRepository
private lateinit var fakeSettings: FakeSettings
@Mock private lateinit var clockRegistry: ClockRegistry
+ @Mock private lateinit var clockEventController: ClockEventController
@Before
fun setup() {
@@ -55,7 +57,14 @@
scheduler = TestCoroutineScheduler()
dispatcher = StandardTestDispatcher(scheduler)
scope = TestScope(dispatcher)
- underTest = KeyguardClockRepository(fakeSettings, clockRegistry, dispatcher)
+ underTest =
+ KeyguardClockRepositoryImpl(
+ fakeSettings,
+ clockRegistry,
+ clockEventController,
+ dispatcher,
+ scope.backgroundScope
+ )
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index b3e8fed..de12b8f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -130,6 +130,7 @@
mContext,
testScope.backgroundScope,
dispatcher,
+ dispatcher,
faceAuthRepository,
{
PrimaryBouncerInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
index a04ea2e..edd781d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
@@ -24,8 +24,10 @@
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.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -35,125 +37,138 @@
@SmallTest
@RunWith(JUnit4::class)
class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
- private lateinit var underTest: KeyguardTransitionAnimationFlow
+ private lateinit var underTest: KeyguardTransitionAnimationFlow.SharedFlowBuilder
private lateinit var repository: FakeKeyguardTransitionRepository
+ private lateinit var testScope: TestScope
@Before
fun setUp() {
+ testScope = TestScope()
repository = FakeKeyguardTransitionRepository()
underTest =
KeyguardTransitionAnimationFlow(
- 1000.milliseconds,
- repository.transitions,
- )
+ testScope.backgroundScope,
+ mock(),
+ )
+ .setup(
+ duration = 1000.milliseconds,
+ stepFlow = repository.transitions,
+ )
}
@Test(expected = IllegalArgumentException::class)
- fun zeroDurationThrowsException() = runTest {
- val flow = underTest.createFlow(duration = 0.milliseconds, onStep = { it })
- }
+ fun zeroDurationThrowsException() =
+ testScope.runTest {
+ val flow = underTest.sharedFlow(duration = 0.milliseconds, onStep = { it })
+ }
@Test(expected = IllegalArgumentException::class)
- fun startTimePlusDurationGreaterThanTransitionDurationThrowsException() = runTest {
- val flow =
- underTest.createFlow(
- startTime = 300.milliseconds,
- duration = 800.milliseconds,
- onStep = { it }
- )
- }
+ fun startTimePlusDurationGreaterThanTransitionDurationThrowsException() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ startTime = 300.milliseconds,
+ duration = 800.milliseconds,
+ onStep = { it }
+ )
+ }
@Test
- fun onFinishRunsWhenSpecified() = runTest {
- val flow =
- underTest.createFlow(
- duration = 100.milliseconds,
- onStep = { it },
- onFinish = { 10f },
- )
- var animationValues = collectLastValue(flow)
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED), validateStep = false)
- assertThat(animationValues()).isEqualTo(10f)
- }
+ fun onFinishRunsWhenSpecified() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ duration = 100.milliseconds,
+ onStep = { it },
+ onFinish = { 10f },
+ )
+ var animationValues = collectLastValue(flow)
+ repository.sendTransitionStep(step(1f, TransitionState.FINISHED), validateStep = false)
+ assertThat(animationValues()).isEqualTo(10f)
+ }
@Test
- fun onCancelRunsWhenSpecified() = runTest {
- val flow =
- underTest.createFlow(
- duration = 100.milliseconds,
- onStep = { it },
- onCancel = { 100f },
- )
- var animationValues = collectLastValue(flow)
- repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
- assertThat(animationValues()).isEqualTo(100f)
- }
+ fun onCancelRunsWhenSpecified() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ duration = 100.milliseconds,
+ onStep = { it },
+ onCancel = { 100f },
+ )
+ var animationValues = collectLastValue(flow)
+ repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
+ assertThat(animationValues()).isEqualTo(100f)
+ }
@Test
- fun usesStartTime() = runTest {
- val flow =
- underTest.createFlow(
- startTime = 500.milliseconds,
- duration = 500.milliseconds,
- onStep = { it },
- )
- var animationValues = collectLastValue(flow)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(animationValues()).isEqualTo(0f)
+ fun usesStartTime() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ startTime = 500.milliseconds,
+ duration = 500.milliseconds,
+ onStep = { it },
+ )
+ var animationValues = collectLastValue(flow)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(animationValues()).isEqualTo(0f)
- // Should not emit a value
- repository.sendTransitionStep(step(0.1f, TransitionState.RUNNING))
+ // Should not emit a value
+ repository.sendTransitionStep(step(0.1f, TransitionState.RUNNING))
- repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
- assertFloat(animationValues(), 0f)
- repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
- assertFloat(animationValues(), 0.2f)
- repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
- assertFloat(animationValues(), 0.6f)
- repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
- assertFloat(animationValues(), 1f)
- }
+ repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 0f)
+ repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 0.2f)
+ repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 0.6f)
+ repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 1f)
+ }
@Test
- fun usesInterpolator() = runTest {
- val flow =
- underTest.createFlow(
- duration = 1000.milliseconds,
- interpolator = EMPHASIZED_ACCELERATE,
- onStep = { it },
- )
- var animationValues = collectLastValue(flow)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0f))
- repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
- assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.5f))
- repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
- assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.6f))
- repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
- assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.8f))
- repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
- assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(1f))
- }
+ fun usesInterpolator() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ duration = 1000.milliseconds,
+ interpolator = EMPHASIZED_ACCELERATE,
+ onStep = { it },
+ )
+ var animationValues = collectLastValue(flow)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0f))
+ repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+ assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.5f))
+ repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+ assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.6f))
+ repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+ assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.8f))
+ repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+ assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(1f))
+ }
@Test
- fun usesOnStepToDoubleValue() = runTest {
- val flow =
- underTest.createFlow(
- duration = 1000.milliseconds,
- onStep = { it * 2 },
- )
- var animationValues = collectLastValue(flow)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertFloat(animationValues(), 0f)
- repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
- assertFloat(animationValues(), 0.6f)
- repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
- assertFloat(animationValues(), 1.2f)
- repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
- assertFloat(animationValues(), 1.6f)
- repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
- assertFloat(animationValues(), 2f)
- }
+ fun usesOnStepToDoubleValue() =
+ testScope.runTest {
+ val flow =
+ underTest.sharedFlow(
+ duration = 1000.milliseconds,
+ onStep = { it * 2 },
+ )
+ var animationValues = collectLastValue(flow)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertFloat(animationValues(), 0f)
+ repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 0.6f)
+ repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 1.2f)
+ repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 1.6f)
+ repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+ assertFloat(animationValues(), 2f)
+ }
private fun assertFloat(actual: Float?, expected: Float) {
assertThat(actual!!).isWithin(0.01f).of(expected)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
new file mode 100644
index 0000000..a4d217f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.binder
+
+import android.view.View
+import androidx.constraintlayout.helper.widget.Layer
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.clocks.ClockConfig
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockFaceLayout
+import com.android.systemui.util.mockito.whenever
+import kotlin.test.Test
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@kotlinx.coroutines.ExperimentalCoroutinesApi
+class KeyguardClockViewBinderTest : SysuiTestCase() {
+ @Mock private lateinit var rootView: ConstraintLayout
+ @Mock private lateinit var burnInLayer: Layer
+ @Mock private lateinit var clock: ClockController
+ @Mock private lateinit var largeClock: ClockFaceController
+ @Mock private lateinit var smallClock: ClockFaceController
+ @Mock private lateinit var largeClockView: View
+ @Mock private lateinit var smallClockView: View
+ @Mock private lateinit var smallClockFaceLayout: ClockFaceLayout
+ @Mock private lateinit var largeClockFaceLayout: ClockFaceLayout
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun addClockViews_nonWeatherClock() {
+ setupNonWeatherClock()
+ KeyguardClockViewBinder.addClockViews(clock, rootView, burnInLayer)
+ verify(rootView).addView(smallClockView)
+ verify(rootView).addView(largeClockView)
+ verify(burnInLayer).addView(smallClockView)
+ verify(burnInLayer, never()).addView(largeClockView)
+ }
+
+ @Test
+ fun addClockViews_WeatherClock() {
+ setupWeatherClock()
+ KeyguardClockViewBinder.addClockViews(clock, rootView, burnInLayer)
+ verify(rootView).addView(smallClockView)
+ verify(rootView).addView(largeClockView)
+ verify(burnInLayer).addView(smallClockView)
+ verify(burnInLayer).addView(largeClockView)
+ }
+
+ private fun setupWeatherClock() {
+ setupClock()
+ val clockConfig =
+ ClockConfig(
+ id = "WEATHER_CLOCK",
+ name = "",
+ description = "",
+ useAlternateSmartspaceAODTransition = true
+ )
+ whenever(clock.config).thenReturn(clockConfig)
+ }
+
+ private fun setupNonWeatherClock() {
+ setupClock()
+ val clockConfig = ClockConfig(id = "NON_WEATHER_CLOCK", name = "", description = "")
+ whenever(clock.config).thenReturn(clockConfig)
+ }
+
+ private fun setupClock() {
+ whenever(largeClockFaceLayout.views).thenReturn(listOf(largeClockView))
+ whenever(smallClockFaceLayout.views).thenReturn(listOf(smallClockView))
+ whenever(clock.largeClock).thenReturn(largeClock)
+ whenever(clock.smallClock).thenReturn(smallClock)
+ whenever(largeClock.layout).thenReturn(largeClockFaceLayout)
+ whenever(smallClock.layout).thenReturn(smallClockFaceLayout)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 740fce9..3109e76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -27,9 +27,9 @@
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.KeyguardRootView
-import com.android.systemui.keyguard.ui.view.layout.items.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
+import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntrySection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultNotificationStackScrollLayoutSection
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 6b85cf7..64a07fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -22,9 +22,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags.MIGRATE_CLOCKS_TO_BLUEPRINT
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.ui.view.layout.items.ClockSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.res.R
@@ -32,7 +30,6 @@
import com.android.systemui.util.Utils
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -47,7 +44,6 @@
@Mock private lateinit var keyguardClockViewModel: KeyguardClockViewModel
@Mock private lateinit var smartspaceViewModel: KeyguardSmartspaceViewModel
@Mock private lateinit var splitShadeStateController: SplitShadeStateController
- @Mock private lateinit var keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>
private var featureFlags: FakeFeatureFlagsClassic = FakeFeatureFlagsClassic()
private lateinit var underTest: ClockSection
@@ -94,7 +90,6 @@
smartspaceViewModel,
mContext,
splitShadeStateController,
- keyguardBlueprintInteractor,
featureFlags
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
index fc9f54ec..d959872 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
@@ -21,66 +21,45 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+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.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager
+import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
@ExperimentalCoroutinesApi
@RunWith(JUnit4::class)
@SmallTest
class AlternateBouncerViewModelTest : SysuiTestCase() {
-
- private lateinit var testScope: TestScope
-
- @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
-
- private lateinit var transitionRepository: FakeKeyguardTransitionRepository
- private lateinit var transitionInteractor: KeyguardTransitionInteractor
- private lateinit var underTest: AlternateBouncerViewModel
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- testScope = TestScope()
-
- val transitionInteractorWithDependencies =
- KeyguardTransitionInteractorFactory.create(testScope.backgroundScope)
- transitionInteractor = transitionInteractorWithDependencies.keyguardTransitionInteractor
- transitionRepository = transitionInteractorWithDependencies.repository
- underTest =
- AlternateBouncerViewModel(
- statusBarKeyguardViewManager,
- transitionInteractor,
- )
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val transitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val statusBarKeyguardViewManager = kosmos.statusBarKeyguardViewManager
+ private val underTest = kosmos.alternateBouncerViewModel
@Test
fun transitionToAlternateBouncer_scrimAlphaUpdate() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val scrimAlphas by collectValues(underTest.scrimAlpha)
- transitionRepository.sendTransitionStep(
- stepToAlternateBouncer(0f, TransitionState.STARTED)
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepToAlternateBouncer(0f, TransitionState.STARTED),
+ stepToAlternateBouncer(.4f),
+ stepToAlternateBouncer(.6f),
+ stepToAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.4f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
assertThat(scrimAlphas.size).isEqualTo(4)
scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
@@ -88,15 +67,18 @@
@Test
fun transitionFromAlternateBouncer_scrimAlphaUpdate() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val scrimAlphas by collectValues(underTest.scrimAlpha)
- transitionRepository.sendTransitionStep(
- stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepToAlternateBouncer(0f, TransitionState.STARTED),
+ stepToAlternateBouncer(.4f),
+ stepToAlternateBouncer(.6f),
+ stepToAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.4f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
assertThat(scrimAlphas.size).isEqualTo(4)
scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
@@ -104,43 +86,57 @@
@Test
fun forcePluginOpen() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val forcePluginOpen by collectLastValue(underTest.forcePluginOpen)
- transitionRepository.sendTransitionStep(
- stepToAlternateBouncer(0f, TransitionState.STARTED)
+
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepToAlternateBouncer(0f, TransitionState.STARTED),
+ stepToAlternateBouncer(.4f),
+ stepToAlternateBouncer(.6f),
+ stepToAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.3f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
assertThat(forcePluginOpen).isTrue()
- transitionRepository.sendTransitionStep(
- stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepFromAlternateBouncer(0f, TransitionState.STARTED),
+ stepFromAlternateBouncer(.3f),
+ stepFromAlternateBouncer(.6f),
+ stepFromAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.3f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
assertThat(forcePluginOpen).isFalse()
}
@Test
fun registerForDismissGestures() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val registerForDismissGestures by collectLastValue(underTest.registerForDismissGestures)
- transitionRepository.sendTransitionStep(
- stepToAlternateBouncer(0f, TransitionState.STARTED)
+
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepToAlternateBouncer(0f, TransitionState.STARTED),
+ stepToAlternateBouncer(.4f),
+ stepToAlternateBouncer(.6f),
+ stepToAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.3f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
assertThat(registerForDismissGestures).isTrue()
- transitionRepository.sendTransitionStep(
- stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ stepFromAlternateBouncer(0f, TransitionState.STARTED),
+ stepFromAlternateBouncer(.3f),
+ stepFromAlternateBouncer(.6f),
+ stepFromAlternateBouncer(1f),
+ ),
+ testScope,
)
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.3f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
- transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
assertThat(registerForDismissGestures).isFalse()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelTest.kt
index f282481..4c972e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelTest.kt
@@ -20,16 +20,15 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,34 +36,25 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class AodToGoneTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: AodToGoneTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest = AodToGoneTransitionViewModel(interactor)
- }
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val repository = kosmos.fakeKeyguardTransitionRepository
+ val underTest = kosmos.aodToGoneTransitionViewModel
@Test
- fun deviceEntryParentViewHides() = runTest {
- val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
- deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(0f) }
- }
+ fun deviceEntryParentViewHides() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.4f))
+ repository.sendTransitionStep(step(0.5f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(0.8f))
+ repository.sendTransitionStep(step(1f))
+ deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(0f) }
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
index 517149c..af8d8a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
@@ -19,22 +19,18 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -42,83 +38,67 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class AodToLockscreenTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: AodToLockscreenTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- underTest =
- AodToLockscreenTransitionViewModel(
- interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor,
- deviceEntryUdfpsInteractor =
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = FakeBiometricSettingsRepository(),
- ),
- )
- }
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val repository = kosmos.fakeKeyguardTransitionRepository
+ val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ val underTest = kosmos.aodToLockscreenTransitionViewModel
@Test
- fun deviceEntryParentViewShows() = runTest {
- val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
- deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(1f) }
- }
+ fun deviceEntryParentViewShows() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.5f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(1f))
+ deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(1f) }
+ }
@Test
- fun deviceEntryBackgroundView_udfps_alphaFadeIn() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- val deviceEntryBackgroundViewAlpha by
- collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ fun deviceEntryBackgroundView_udfps_alphaFadeIn() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- // fade in
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ // fade in
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(0.1f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(.2f)
+ repository.sendTransitionStep(step(0.1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(.2f)
- repository.sendTransitionStep(step(0.3f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(.6f)
+ repository.sendTransitionStep(step(0.3f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(.6f)
- repository.sendTransitionStep(step(0.6f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
+ repository.sendTransitionStep(step(0.6f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
- }
+ repository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(1f)
+ }
@Test
- fun deviceEntryBackgroundView_rearFp_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsRearFps()
- val deviceEntryBackgroundViewAlpha by
- collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- // no updates
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryBackgroundViewAlpha).isNull()
- repository.sendTransitionStep(step(0.1f))
- assertThat(deviceEntryBackgroundViewAlpha).isNull()
- repository.sendTransitionStep(step(0.3f))
- assertThat(deviceEntryBackgroundViewAlpha).isNull()
- repository.sendTransitionStep(step(0.6f))
- assertThat(deviceEntryBackgroundViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryBackgroundViewAlpha).isNull()
- }
+ fun deviceEntryBackgroundView_rearFp_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsRearFps()
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ // no updates
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryBackgroundViewAlpha).isNull()
+ repository.sendTransitionStep(step(0.1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isNull()
+ repository.sendTransitionStep(step(0.3f))
+ assertThat(deviceEntryBackgroundViewAlpha).isNull()
+ repository.sendTransitionStep(step(0.6f))
+ assertThat(deviceEntryBackgroundViewAlpha).isNull()
+ repository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isNull()
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelTest.kt
index 96f69462..db8fbf6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelTest.kt
@@ -20,16 +20,15 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+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.testKosmos
import com.google.common.truth.Truth
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,34 +36,25 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class AodToOccludedTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: AodToOccludedTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest = AodToOccludedTransitionViewModel(interactor)
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest = kosmos.aodToOccludedTransitionViewModel
@Test
- fun deviceEntryParentViewHides() = runTest {
- val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
- deviceEntryParentViewAlpha.forEach { Truth.assertThat(it).isEqualTo(0f) }
- }
+ fun deviceEntryParentViewHides() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.4f))
+ repository.sendTransitionStep(step(0.5f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(0.8f))
+ repository.sendTransitionStep(step(1f))
+ deviceEntryParentViewAlpha.forEach { Truth.assertThat(it).isEqualTo(0f) }
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
index 1ff46db..c9b14a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
@@ -19,28 +19,26 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.shared.model.ScrimAlpha
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.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.sysuiStatusBarStateController
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -51,56 +49,47 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class BouncerToGoneFlowsTest : SysuiTestCase() {
- private lateinit var underTest: BouncerToGoneFlows
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var featureFlags: FakeFeatureFlags
- @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
- @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
- @Mock
- private lateinit var keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>
@Mock private lateinit var shadeInteractor: ShadeInteractor
private val shadeExpansionStateFlow = MutableStateFlow(0.1f)
+ private val kosmos =
+ testKosmos().apply {
+ featureFlagsClassic.apply {
+ set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ }
+ }
+ private val testScope = kosmos.testScope
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val shadeRepository = kosmos.shadeRepository
+ private val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController
+ private val primaryBouncerInteractor = kosmos.primaryBouncerInteractor
+ private val underTest = kosmos.bouncerToGoneFlows
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- whenever(shadeInteractor.shadeExpansion).thenReturn(shadeExpansionStateFlow)
-
- repository = FakeKeyguardTransitionRepository()
- val featureFlags =
- FakeFeatureFlags().apply { set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) }
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest =
- BouncerToGoneFlows(
- interactor,
- statusBarStateController,
- primaryBouncerInteractor,
- keyguardDismissActionInteractor,
- featureFlags,
- shadeInteractor,
- )
-
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
- whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
}
@Test
fun scrimAlpha_runDimissFromKeyguard_shadeExpanded() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.scrimAlpha(500.milliseconds, PRIMARY_BOUNCER))
- shadeExpansionStateFlow.value = 1f
+ shadeRepository.setLockscreenShadeExpansion(1f)
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it.frontAlpha).isEqualTo(0f) }
@@ -110,16 +99,21 @@
@Test
fun scrimAlpha_runDimissFromKeyguard_shadeNotExpanded() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.scrimAlpha(500.milliseconds, PRIMARY_BOUNCER))
- shadeExpansionStateFlow.value = 0f
+ shadeRepository.setLockscreenShadeExpansion(0f)
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it).isEqualTo(ScrimAlpha()) }
@@ -127,15 +121,20 @@
@Test
fun scrimBehindAlpha_leaveShadeOpen() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.scrimAlpha(500.milliseconds, PRIMARY_BOUNCER))
- whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(true)
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach {
@@ -145,15 +144,17 @@
@Test
fun scrimBehindAlpha_doNotLeaveShadeOpen() =
- runTest(UnconfinedTestDispatcher()) {
+ testScope.runTest {
val values by collectValues(underTest.scrimAlpha(500.milliseconds, PRIMARY_BOUNCER))
-
- whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
-
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ step(1f),
+ ),
+ testScope,
+ )
assertThat(values.size).isEqualTo(4)
values.forEach { assertThat(it.notificationsAlpha).isEqualTo(0f) }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelTest.kt
index 5dccc3b..dd542d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelTest.kt
@@ -25,6 +25,8 @@
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.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -43,29 +45,36 @@
@Before
fun setUp() {
+ testScope = TestScope()
repository = FakeKeyguardTransitionRepository()
underTest =
DozingToLockscreenTransitionViewModel(
interactor =
KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
+ scope = testScope.backgroundScope,
repository = repository,
)
.keyguardTransitionInteractor,
+ animationFlow =
+ KeyguardTransitionAnimationFlow(
+ scope = testScope.backgroundScope,
+ logger = mock()
+ ),
)
}
@Test
- fun deviceEntryParentViewShows() = runTest {
- val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(1f))
- deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(1f) }
- }
+ fun deviceEntryParentViewShows() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.5f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(1f))
+ deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(1f) }
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
index c1444a5..a105008 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
@@ -19,23 +19,19 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+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.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -43,37 +39,12 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class GoneToAodTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: GoneToAodTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
- private lateinit var testScope: TestScope
-
- @Before
- fun setUp() {
- val testDispatcher = StandardTestDispatcher()
- testScope = TestScope(testDispatcher)
-
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- biometricSettingsRepository = FakeBiometricSettingsRepository()
-
- underTest =
- GoneToAodTransitionViewModel(
- interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = testScope.backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor,
- deviceEntryUdfpsInteractor =
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = biometricSettingsRepository,
- ),
- )
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest = kosmos.goneToAodTransitionViewModel
+ private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ private val biometricSettingsRepository = kosmos.biometricSettingsRepository
@Test
fun enterFromTopTranslationY() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
index 46a7735..d421004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
@@ -25,11 +25,16 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.KeyguardClockRepositoryImpl
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockFaceConfig
+import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.shared.clocks.ClockRegistry
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -50,7 +55,6 @@
private lateinit var scheduler: TestCoroutineScheduler
private lateinit var dispatcher: CoroutineDispatcher
private lateinit var scope: TestScope
-
private lateinit var underTest: KeyguardClockViewModel
private lateinit var keyguardInteractor: KeyguardInteractor
private lateinit var keyguardRepository: KeyguardRepository
@@ -58,6 +62,9 @@
private lateinit var keyguardClockRepository: KeyguardClockRepository
private lateinit var fakeSettings: FakeSettings
@Mock private lateinit var clockRegistry: ClockRegistry
+ @Mock private lateinit var clock: ClockController
+ @Mock private lateinit var largeClock: ClockFaceController
+ @Mock private lateinit var clockFaceConfig: ClockFaceConfig
@Mock private lateinit var eventController: ClockEventController
@Before
fun setup() {
@@ -70,13 +77,21 @@
scheduler = TestCoroutineScheduler()
dispatcher = StandardTestDispatcher(scheduler)
scope = TestScope(dispatcher)
- keyguardClockRepository = KeyguardClockRepository(fakeSettings, clockRegistry, dispatcher)
- keyguardClockInteractor = KeyguardClockInteractor(eventController, keyguardClockRepository)
+ setupMockClock()
+ keyguardClockRepository =
+ KeyguardClockRepositoryImpl(
+ fakeSettings,
+ clockRegistry,
+ eventController,
+ dispatcher,
+ scope.backgroundScope
+ )
+ keyguardClockInteractor = KeyguardClockInteractor(keyguardClockRepository)
underTest =
KeyguardClockViewModel(
keyguardInteractor,
keyguardClockInteractor,
- scope.backgroundScope
+ scope.backgroundScope,
)
}
@@ -86,7 +101,7 @@
// When use double line clock is disabled,
// should always return small
fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 0)
- keyguardRepository.setClockSize(LARGE)
+ keyguardClockRepository.setClockSize(LARGE)
val value = collectLastValue(underTest.clockSize)
assertThat(value()).isEqualTo(SMALL)
}
@@ -95,12 +110,19 @@
fun testClockSize_dynamicClockSize() =
scope.runTest {
fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)
- keyguardRepository.setClockSize(SMALL)
+ keyguardClockRepository.setClockSize(SMALL)
var value = collectLastValue(underTest.clockSize)
assertThat(value()).isEqualTo(SMALL)
- keyguardRepository.setClockSize(LARGE)
+ keyguardClockRepository.setClockSize(LARGE)
value = collectLastValue(underTest.clockSize)
assertThat(value()).isEqualTo(LARGE)
}
+
+ private fun setupMockClock() {
+ whenever(clock.largeClock).thenReturn(largeClock)
+ whenever(largeClock.config).thenReturn(clockFaceConfig)
+ whenever(clockFaceConfig.hasCustomWeatherDataDisplay).thenReturn(false)
+ whenever(clockRegistry.createCurrentClock()).thenReturn(clock)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
index 88a4aa5..864acfb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
@@ -17,7 +17,10 @@
package com.android.systemui.keyguard.ui.viewmodel
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -65,6 +68,9 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+
+ mSetFlagsRule.disableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
+
whenever(burnInHelperWrapper.burnInOffset(anyInt(), any()))
.thenReturn(RETURNED_BURN_IN_OFFSET)
@@ -83,6 +89,7 @@
keyguardBottomAreaViewModel = bottomAreaViewModel,
burnInHelperWrapper = burnInHelperWrapper,
shortcutsCombinedViewModel = shortcutsCombinedViewModel,
+ configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index a57feda..23a2709 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -23,46 +23,41 @@
import androidx.test.filters.SmallTest
import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.TestMocksModule
import com.android.systemui.collectLastValue
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
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.plugins.ClockController
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.statusbar.notification.data.repository.FakeNotificationsKeyguardViewStateRepository
-import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.statusbar.notification.data.repository.fakeNotificationsKeyguardViewStateRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
+import com.android.systemui.statusbar.phone.dozeParameters
+import com.android.systemui.statusbar.phone.screenOffAnimationController
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.ui.isAnimating
import com.android.systemui.util.ui.stopAnimating
import com.android.systemui.util.ui.value
import com.google.common.truth.Truth.assertThat
-import dagger.BindsInstance
-import dagger.Component
import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -72,45 +67,49 @@
import org.mockito.Mock
import org.mockito.Mockito.RETURNS_DEEP_STUBS
import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.withSettings
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(JUnit4::class)
class KeyguardRootViewModelTest : SysuiTestCase() {
-
+ private val kosmos =
+ testKosmos().apply {
+ featureFlagsClassic.apply { set(Flags.MIGRATE_CLOCKS_TO_BLUEPRINT, false) }
+ }
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardRepository
+ private val configurationRepository = kosmos.fakeConfigurationRepository
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val screenOffAnimationController = kosmos.screenOffAnimationController
+ private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository
+ private val notificationsKeyguardInteractor = kosmos.notificationsKeyguardInteractor
+ private val fakeNotificationsKeyguardViewStateRepository =
+ kosmos.fakeNotificationsKeyguardViewStateRepository
+ private val dozeParameters = kosmos.dozeParameters
private lateinit var underTest: KeyguardRootViewModel
- private lateinit var testScope: TestScope
- private lateinit var repository: FakeKeyguardRepository
- private lateinit var keyguardInteractor: KeyguardInteractor
- private lateinit var configurationRepository: FakeConfigurationRepository
+
@Mock private lateinit var burnInInteractor: BurnInInteractor
- @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ private val burnInFlow = MutableStateFlow(BurnInModel())
+
@Mock private lateinit var goneToAodTransitionViewModel: GoneToAodTransitionViewModel
+ private val enterFromTopAnimationAlpha = MutableStateFlow(0f)
+
@Mock
private lateinit var aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel
- @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var clockController: ClockController
+ @Mock
+ private lateinit var occludedToLockscreenTransitionViewModel:
+ OccludedToLockscreenTransitionViewModel
+ private val occludedToLockscreenTranslationY = MutableStateFlow(0f)
+ private val occludedToLockscreenAlpha = MutableStateFlow(0f)
- private val burnInFlow = MutableStateFlow(BurnInModel())
- private val goneToAodTransitionViewModelVisibility = MutableStateFlow(0)
- private val enterFromTopAnimationAlpha = MutableStateFlow(0f)
- private val goneToAodTransitionStep = MutableSharedFlow<TransitionStep>(replay = 1)
- private val dozeAmountTransitionStep = MutableSharedFlow<TransitionStep>(replay = 1)
- private val startedKeyguardState = MutableStateFlow(KeyguardState.GONE)
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var clockController: ClockController
@Before
fun setUp() {
- val testDispatcher = StandardTestDispatcher()
- testScope = TestScope(testDispatcher)
MockitoAnnotations.initMocks(this)
mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
-
- val withDeps = KeyguardInteractorFactory.create()
- keyguardInteractor = withDeps.keyguardInteractor
- repository = withDeps.repository
- configurationRepository = withDeps.configurationRepository
+ mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
whenever(goneToAodTransitionViewModel.enterFromTopTranslationY(anyInt()))
.thenReturn(emptyFlow<Float>())
@@ -119,30 +118,29 @@
whenever(burnInInteractor.keyguardBurnIn).thenReturn(burnInFlow)
- whenever(keyguardTransitionInteractor.goneToAodTransition)
- .thenReturn(goneToAodTransitionStep)
- whenever(keyguardTransitionInteractor.dozeAmountTransition)
- .thenReturn(dozeAmountTransitionStep)
- whenever(keyguardTransitionInteractor.startedKeyguardState).thenReturn(startedKeyguardState)
+ whenever(occludedToLockscreenTransitionViewModel.lockscreenTranslationY)
+ .thenReturn(occludedToLockscreenTranslationY)
+ whenever(occludedToLockscreenTransitionViewModel.lockscreenAlpha)
+ .thenReturn(occludedToLockscreenAlpha)
underTest =
KeyguardRootViewModel(
- context,
- deviceEntryInteractor =
- mock { whenever(isBypassEnabled).thenReturn(MutableStateFlow(false)) },
- dozeParameters = mock(),
- keyguardInteractor,
- keyguardTransitionInteractor,
- notificationsKeyguardInteractor =
- mock {
- whenever(areNotificationsFullyHidden).thenReturn(emptyFlow())
- whenever(isPulseExpanding).thenReturn(emptyFlow())
- },
- burnInInteractor,
- goneToAodTransitionViewModel,
- aodToLockscreenTransitionViewModel,
- screenOffAnimationController = mock(),
+ configurationInteractor = kosmos.configurationInteractor,
+ deviceEntryInteractor = kosmos.deviceEntryInteractor,
+ dozeParameters = kosmos.dozeParameters,
+ keyguardInteractor = kosmos.keyguardInteractor,
+ keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
+ notificationsKeyguardInteractor = kosmos.notificationsKeyguardInteractor,
+ burnInInteractor = burnInInteractor,
+ keyguardClockViewModel = kosmos.keyguardClockViewModel,
+ goneToAodTransitionViewModel = goneToAodTransitionViewModel,
+ aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
+ occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
+ screenOffAnimationController = screenOffAnimationController,
+ // TODO(b/310989341): remove after change to aconfig
+ featureFlags = kosmos.featureFlagsClassic
)
+
underTest.clockControllerProvider = Provider { clockController }
}
@@ -150,8 +148,8 @@
fun alpha() =
testScope.runTest {
val value = collectLastValue(underTest.alpha)
+ assertThat(value()).isEqualTo(0f)
- assertThat(value()).isEqualTo(1f)
repository.setKeyguardAlpha(0.1f)
assertThat(value()).isEqualTo(0.1f)
repository.setKeyguardAlpha(0.5f)
@@ -160,6 +158,8 @@
assertThat(value()).isEqualTo(0.2f)
repository.setKeyguardAlpha(0f)
assertThat(value()).isEqualTo(0f)
+ occludedToLockscreenAlpha.value = 0.8f
+ assertThat(value()).isEqualTo(0.8f)
}
@Test
@@ -170,7 +170,15 @@
val scale by collectLastValue(underTest.scale)
// Set to not dozing (on lockscreen)
- dozeAmountTransitionStep.emit(TransitionStep(value = 0f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ ),
+ validateStep = false,
+ )
// Trigger a change to the burn-in model
burnInFlow.value =
@@ -195,7 +203,15 @@
underTest.statusViewTop = 100
// Set to dozing (on AOD)
- dozeAmountTransitionStep.emit(TransitionStep(value = 1f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ ),
+ validateStep = false,
+ )
// Trigger a change to the burn-in model
burnInFlow.value =
BurnInModel(
@@ -203,12 +219,21 @@
translationY = 30,
scale = 0.5f,
)
+
assertThat(translationX).isEqualTo(20)
assertThat(translationY).isEqualTo(30)
assertThat(scale).isEqualTo(Pair(0.5f, true /* scaleClockOnly */))
// Set to the beginning of GONE->AOD transition
- goneToAodTransitionStep.emit(TransitionStep(value = 0f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = 0f,
+ transitionState = TransitionState.STARTED
+ ),
+ validateStep = false,
+ )
assertThat(translationX).isEqualTo(0)
assertThat(translationY).isEqualTo(0)
assertThat(scale).isEqualTo(Pair(1f, true /* scaleClockOnly */))
@@ -225,7 +250,16 @@
underTest.topInset = 80
// Set to dozing (on AOD)
- dozeAmountTransitionStep.emit(TransitionStep(value = 1f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ ),
+ validateStep = false,
+ )
+
// Trigger a change to the burn-in model
burnInFlow.value =
BurnInModel(
@@ -239,7 +273,15 @@
assertThat(scale).isEqualTo(Pair(0.5f, true /* scaleClockOnly */))
// Set to the beginning of GONE->AOD transition
- goneToAodTransitionStep.emit(TransitionStep(value = 0f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = 0f,
+ transitionState = TransitionState.STARTED
+ ),
+ validateStep = false,
+ )
assertThat(translationX).isEqualTo(0)
assertThat(translationY).isEqualTo(0)
assertThat(scale).isEqualTo(Pair(1f, true /* scaleClockOnly */))
@@ -255,7 +297,15 @@
val scale by collectLastValue(underTest.scale)
// Set to dozing (on AOD)
- dozeAmountTransitionStep.emit(TransitionStep(value = 1f))
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = 1f,
+ transitionState = TransitionState.FINISHED
+ ),
+ validateStep = false,
+ )
// Trigger a change to the burn-in model
burnInFlow.value =
@@ -275,10 +325,15 @@
testScope.runTest {
val burnInLayerVisibility by collectLastValue(underTest.burnInLayerVisibility)
- startedKeyguardState.value = KeyguardState.OCCLUDED
- assertThat(burnInLayerVisibility).isNull()
-
- startedKeyguardState.value = KeyguardState.AOD
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ value = 0f,
+ transitionState = TransitionState.STARTED
+ ),
+ validateStep = false,
+ )
assertThat(burnInLayerVisibility).isEqualTo(View.VISIBLE)
}
@@ -293,165 +348,124 @@
enterFromTopAnimationAlpha.value = 1f
assertThat(burnInLayerAlpha).isEqualTo(1f)
}
-}
-@SmallTest
-class KeyguardRootViewModelTestWithFakes : SysuiTestCase() {
-
- @Component(modules = [SysUITestModule::class])
- @SysUISingleton
- interface TestComponent : SysUITestComponent<KeyguardRootViewModel> {
- val deviceEntryRepository: FakeDeviceEntryRepository
- val notifsKeyguardRepository: FakeNotificationsKeyguardViewStateRepository
- val repository: FakeKeyguardRepository
- val transitionRepository: FakeKeyguardTransitionRepository
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- featureFlags: FakeFeatureFlagsClassicModule,
- mocks: TestMocksModule,
- ): TestComponent
- }
- }
-
- private val clockController: ClockController =
- mock(withSettings().defaultAnswer(RETURNS_DEEP_STUBS))
- private val dozeParams: DozeParameters = mock()
- private val screenOffAnimController: ScreenOffAnimationController = mock()
-
- private fun runTest(block: suspend TestComponent.() -> Unit): Unit =
- DaggerKeyguardRootViewModelTestWithFakes_TestComponent.factory()
- .create(
- test = this,
- featureFlags = FakeFeatureFlagsClassicModule(),
- mocks =
- TestMocksModule(
- dozeParameters = dozeParams,
- screenOffAnimationController = screenOffAnimController,
- ),
+ @Test
+ fun iconContainer_isNotVisible_notOnKeyguard_dontShowAodIconsWhenShade() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.OFF,
+ to = KeyguardState.GONE,
+ testScope,
)
- .runTest {
- reset(clockController)
- underTest.clockControllerProvider = Provider { clockController }
- block()
- }
+ whenever(screenOffAnimationController.shouldShowAodIconsWhenShade()).thenReturn(false)
+ runCurrent()
- @Before
- fun before() {
- mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
- }
+ assertThat(isVisible?.value).isFalse()
+ assertThat(isVisible?.isAnimating).isFalse()
+ }
@Test
- fun iconContainer_isNotVisible_notOnKeyguard_dontShowAodIconsWhenShade() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.OFF,
- to = KeyguardState.GONE,
- testScope,
- )
- whenever(screenOffAnimController.shouldShowAodIconsWhenShade()).thenReturn(false)
- runCurrent()
+ fun iconContainer_isVisible_bypassEnabled() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ deviceEntryRepository.setBypassEnabled(true)
+ runCurrent()
- assertThat(isVisible?.value).isFalse()
- assertThat(isVisible?.isAnimating).isFalse()
- }
+ assertThat(isVisible?.value).isTrue()
+ }
@Test
- fun iconContainer_isVisible_bypassEnabled() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- deviceEntryRepository.setBypassEnabled(true)
- runCurrent()
+ fun iconContainer_isNotVisible_pulseExpanding_notBypassing() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(true)
+ deviceEntryRepository.setBypassEnabled(false)
+ runCurrent()
- assertThat(isVisible?.value).isTrue()
- }
+ assertThat(isVisible?.value).isEqualTo(false)
+ }
@Test
- fun iconContainer_isNotVisible_pulseExpanding_notBypassing() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(true)
- deviceEntryRepository.setBypassEnabled(false)
- runCurrent()
+ fun iconContainer_isVisible_notifsFullyHidden_bypassEnabled() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(true)
+ fakeNotificationsKeyguardViewStateRepository.setNotificationsFullyHidden(true)
+ runCurrent()
- assertThat(isVisible?.value).isEqualTo(false)
- }
+ assertThat(isVisible?.value).isTrue()
+ assertThat(isVisible?.isAnimating).isTrue()
+ }
@Test
- fun iconContainer_isVisible_notifsFullyHidden_bypassEnabled() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(true)
- notifsKeyguardRepository.setNotificationsFullyHidden(true)
- runCurrent()
+ fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_aodDisabled() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ whenever(dozeParameters.alwaysOn).thenReturn(false)
+ fakeNotificationsKeyguardViewStateRepository.setNotificationsFullyHidden(true)
+ runCurrent()
- assertThat(isVisible?.value).isTrue()
- assertThat(isVisible?.isAnimating).isTrue()
- }
+ assertThat(isVisible?.value).isTrue()
+ assertThat(isVisible?.isAnimating).isFalse()
+ }
@Test
- fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_aodDisabled() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(false)
- whenever(dozeParams.alwaysOn).thenReturn(false)
- notifsKeyguardRepository.setNotificationsFullyHidden(true)
- runCurrent()
+ fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_displayNeedsBlanking() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ whenever(dozeParameters.alwaysOn).thenReturn(true)
+ whenever(dozeParameters.displayNeedsBlanking).thenReturn(true)
+ fakeNotificationsKeyguardViewStateRepository.setNotificationsFullyHidden(true)
+ runCurrent()
- assertThat(isVisible?.value).isTrue()
- assertThat(isVisible?.isAnimating).isFalse()
- }
+ assertThat(isVisible?.value).isTrue()
+ assertThat(isVisible?.isAnimating).isFalse()
+ }
@Test
- fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_displayNeedsBlanking() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(false)
- whenever(dozeParams.alwaysOn).thenReturn(true)
- whenever(dozeParams.displayNeedsBlanking).thenReturn(true)
- notifsKeyguardRepository.setNotificationsFullyHidden(true)
- runCurrent()
+ fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ whenever(dozeParameters.alwaysOn).thenReturn(true)
+ whenever(dozeParameters.displayNeedsBlanking).thenReturn(false)
+ fakeNotificationsKeyguardViewStateRepository.setNotificationsFullyHidden(true)
+ runCurrent()
- assertThat(isVisible?.value).isTrue()
- assertThat(isVisible?.isAnimating).isFalse()
- }
+ assertThat(isVisible?.value).isTrue()
+ assertThat(isVisible?.isAnimating).isTrue()
+ }
@Test
- fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(false)
- whenever(dozeParams.alwaysOn).thenReturn(true)
- whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
- notifsKeyguardRepository.setNotificationsFullyHidden(true)
- runCurrent()
+ fun isIconContainerVisible_stopAnimation() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
+ runCurrent()
+ fakeNotificationsKeyguardViewStateRepository.setPulseExpanding(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ whenever(dozeParameters.alwaysOn).thenReturn(true)
+ whenever(dozeParameters.displayNeedsBlanking).thenReturn(false)
+ fakeNotificationsKeyguardViewStateRepository.setNotificationsFullyHidden(true)
+ runCurrent()
- assertThat(isVisible?.value).isTrue()
- assertThat(isVisible?.isAnimating).isTrue()
- }
+ assertThat(isVisible?.isAnimating).isEqualTo(true)
+ isVisible?.stopAnimating()
+ runCurrent()
- @Test
- fun isIconContainerVisible_stopAnimation() = runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- notifsKeyguardRepository.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(false)
- whenever(dozeParams.alwaysOn).thenReturn(true)
- whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
- notifsKeyguardRepository.setNotificationsFullyHidden(true)
- runCurrent()
-
- assertThat(isVisible?.isAnimating).isEqualTo(true)
- isVisible?.stopAnimating()
- runCurrent()
-
- assertThat(isVisible?.isAnimating).isEqualTo(false)
- }
+ assertThat(isVisible?.isAnimating).isEqualTo(false)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
index 2314c83..c15a2c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
@@ -18,88 +18,47 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.TestMocksModule
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.collectLastValue
-import com.android.systemui.collectValues
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.Flags.FULL_SCREEN_USER_SWITCHER
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import dagger.BindsInstance
-import dagger.Component
import kotlin.test.Test
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.runner.RunWith
@ExperimentalCoroutinesApi
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockscreenToAodTransitionViewModelTest : SysuiTestCase() {
- @SysUISingleton
- @Component(
- modules =
- [
- SysUITestModule::class,
- UserDomainLayerModule::class,
- ]
- )
- interface TestComponent : SysUITestComponent<LockscreenToAodTransitionViewModel> {
- val repository: FakeKeyguardTransitionRepository
- val deviceEntryRepository: FakeDeviceEntryRepository
- val keyguardRepository: FakeKeyguardRepository
- val shadeRepository: FakeShadeRepository
- val fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- val biometricSettingsRepository: FakeBiometricSettingsRepository
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- featureFlags: FakeFeatureFlagsClassicModule,
- mocks: TestMocksModule,
- ): TestComponent
- }
- }
-
- private fun TestComponent.shadeExpanded(expanded: Boolean) {
- if (expanded) {
- shadeRepository.setQsExpansion(1f)
- } else {
- keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
- }
- }
-
- private val testComponent: TestComponent =
- DaggerLockscreenToAodTransitionViewModelTest_TestComponent.factory()
- .create(
- test = this,
- featureFlags =
- FakeFeatureFlagsClassicModule { set(FULL_SCREEN_USER_SWITCHER, true) },
- mocks = TestMocksModule(),
- )
+ private val kosmos =
+ testKosmos().apply { featureFlagsClassic.apply { set(FULL_SCREEN_USER_SWITCHER, false) } }
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val shadeRepository = kosmos.shadeRepository
+ private val keyguardRepository = kosmos.fakeKeyguardRepository
+ private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ private val biometricSettingsRepository = kosmos.biometricSettingsRepository
+ private val underTest = kosmos.lockscreenToAodTransitionViewModel
@Test
fun backgroundViewAlpha_shadeNotExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
shadeExpanded(false)
runCurrent()
@@ -121,7 +80,7 @@
@Test
fun backgroundViewAlpha_shadeExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
shadeExpanded(true)
runCurrent()
@@ -142,7 +101,7 @@
@Test
fun deviceEntryParentViewAlpha_udfpsEnrolled_shadeNotExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val values by collectValues(underTest.deviceEntryParentViewAlpha)
fingerprintPropertyRepository.supportsUdfps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
@@ -165,7 +124,7 @@
@Test
fun deviceEntryParentViewAlpha_udfpsEnrolled_shadeExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryParentViewAlpha)
fingerprintPropertyRepository.supportsUdfps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
@@ -189,7 +148,7 @@
@Test
fun deviceEntryParentViewAlpha_rearFp_shadeNotExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryParentViewAlpha)
fingerprintPropertyRepository.supportsRearFps()
shadeExpanded(false)
@@ -212,7 +171,7 @@
@Test
fun deviceEntryParentViewAlpha_rearFp_shadeExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val values by collectValues(underTest.deviceEntryParentViewAlpha)
fingerprintPropertyRepository.supportsRearFps()
shadeExpanded(true)
@@ -232,6 +191,16 @@
values.forEach { assertThat(it).isEqualTo(0f) }
}
+ private fun shadeExpanded(expanded: Boolean) {
+ if (expanded) {
+ shadeRepository.setQsExpansion(1f)
+ } else {
+ keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ shadeRepository.setQsExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
+ }
+ }
+
private fun step(
value: Float,
state: TransitionState = TransitionState.RUNNING
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt
index 1494c92..8b05a54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt
@@ -20,16 +20,15 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,37 +36,25 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockscreenToGoneTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: LockscreenToGoneTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
-
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest =
- LockscreenToGoneTransitionViewModel(
- interactor,
- )
- }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest = kosmos.lockscreenToGoneTransitionViewModel
@Test
- fun deviceEntryParentViewHides() = runTest {
- val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.1f))
- repository.sendTransitionStep(step(0.3f))
- repository.sendTransitionStep(step(0.4f))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(0.6f))
- repository.sendTransitionStep(step(0.8f))
- repository.sendTransitionStep(step(1f))
- deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(0f) }
- }
+ fun deviceEntryParentViewHides() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectValues(underTest.deviceEntryParentViewAlpha)
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.4f))
+ repository.sendTransitionStep(step(0.5f))
+ repository.sendTransitionStep(step(0.6f))
+ repository.sendTransitionStep(step(0.8f))
+ repository.sendTransitionStep(step(1f))
+ deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(0f) }
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
index 049e4e2..b31968c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
@@ -18,81 +18,44 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.TestMocksModule
-import com.android.systemui.collectLastValue
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth
-import dagger.BindsInstance
-import dagger.Component
import kotlin.test.Test
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.runner.RunWith
@ExperimentalCoroutinesApi
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockscreenToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
- @SysUISingleton
- @Component(
- modules =
- [
- SysUITestModule::class,
- UserDomainLayerModule::class,
- ]
- )
- interface TestComponent : SysUITestComponent<LockscreenToPrimaryBouncerTransitionViewModel> {
- val repository: FakeKeyguardTransitionRepository
- val keyguardRepository: FakeKeyguardRepository
- val shadeRepository: FakeShadeRepository
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- featureFlags: FakeFeatureFlagsClassicModule,
- mocks: TestMocksModule,
- ): TestComponent
+ private val kosmos =
+ testKosmos().apply {
+ featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
}
- }
-
- private fun TestComponent.shadeExpanded(expanded: Boolean) {
- if (expanded) {
- shadeRepository.setQsExpansion(1f)
- } else {
- keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
- }
- }
-
- private val testComponent: TestComponent =
- DaggerLockscreenToPrimaryBouncerTransitionViewModelTest_TestComponent.factory()
- .create(
- test = this,
- featureFlags =
- FakeFeatureFlagsClassicModule { set(Flags.FULL_SCREEN_USER_SWITCHER, true) },
- mocks = TestMocksModule(),
- )
+ private val testScope = kosmos.testScope
+ private val repository = kosmos.fakeKeyguardTransitionRepository
+ private val shadeRepository = kosmos.shadeRepository
+ private val keyguardRepository = kosmos.fakeKeyguardRepository
+ private val underTest = kosmos.lockscreenToPrimaryBouncerTransitionViewModel
@Test
fun deviceEntryParentViewAlpha_shadeExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryParentViewAlpha)
shadeExpanded(true)
runCurrent()
@@ -117,7 +80,7 @@
@Test
fun deviceEntryParentViewAlpha_shadeNotExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val actual by collectLastValue(underTest.deviceEntryParentViewAlpha)
shadeExpanded(false)
runCurrent()
@@ -153,4 +116,14 @@
ownerName = "LockscreenToPrimaryBouncerTransitionViewModelTest"
)
}
+
+ private fun shadeExpanded(expanded: Boolean) {
+ if (expanded) {
+ shadeRepository.setQsExpansion(1f)
+ } else {
+ keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ shadeRepository.setQsExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelTest.kt
index 0eb8ff6..5e62317 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelTest.kt
@@ -19,21 +19,18 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,119 +38,105 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class OccludedToAodTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: OccludedToAodTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- biometricSettingsRepository = FakeBiometricSettingsRepository()
-
- underTest =
- OccludedToAodTransitionViewModel(
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor,
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = biometricSettingsRepository,
- ),
- )
- }
+ val biometricSettingsRepository = kosmos.biometricSettingsRepository
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ val underTest = kosmos.occludedToAodTransitionViewModel
@Test
- fun deviceEntryBackgroundViewAlpha() = runTest {
- val deviceEntryBackgroundViewAlpha by
- collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ fun deviceEntryBackgroundViewAlpha() =
+ testScope.runTest {
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- // immediately 0f
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ // immediately 0f
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(0.4f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ keyguardTransitionRepository.sendTransitionStep(step(0.4f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(.85f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ keyguardTransitionRepository.sendTransitionStep(step(.85f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ }
@Test
- fun deviceEntryParentViewAlpha_udfpsEnrolled() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_udfpsEnrolled() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- // immediately 1f
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ // immediately 1f
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(0.5f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(.95f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(.95f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ }
@Test
- fun deviceEntryParentViewAlpha_rearFpEnrolled_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsRearFps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_rearFpEnrolled_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsRearFps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- // no updates
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ // no updates
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(0.5f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(.95f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(.95f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isNull()
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
+ }
@Test
- fun deviceEntryParentViewAlpha_udfpsNotEnrolled_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_udfpsNotEnrolled_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- // no updates
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ // no updates
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(0.5f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(.95f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(.95f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isNull()
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
index 350b310..9729022 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
@@ -19,21 +19,18 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,113 +38,100 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerToAodTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: PrimaryBouncerToAodTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- biometricSettingsRepository = FakeBiometricSettingsRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor
- underTest =
- PrimaryBouncerToAodTransitionViewModel(
- interactor,
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = biometricSettingsRepository,
- ),
- )
- }
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ val biometricSettingsRepository = kosmos.biometricSettingsRepository
+
+ val underTest = kosmos.primaryBouncerToAodTransitionViewModel
@Test
- fun deviceEntryBackgroundViewAlpha() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- val deviceEntryBackgroundViewAlpha by
- collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ fun deviceEntryBackgroundViewAlpha() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ val deviceEntryBackgroundViewAlpha by
+ collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- // immediately 0f
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ // immediately 0f
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(0.4f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ keyguardTransitionRepository.sendTransitionStep(step(0.4f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(.85f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ keyguardTransitionRepository.sendTransitionStep(step(.85f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryBackgroundViewAlpha).isEqualTo(0f)
+ }
@Test
- fun deviceEntryParentViewAlpha_udfpsEnrolled_fadeIn() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_udfpsEnrolled_fadeIn() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
- repository.sendTransitionStep(step(0.5f))
- repository.sendTransitionStep(step(.75f))
- repository.sendTransitionStep(step(1f))
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ keyguardTransitionRepository.sendTransitionStep(step(.75f))
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ }
@Test
- fun deviceEntryParentViewAlpha_rearFpEnrolled_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsRearFps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_rearFpEnrolled_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsRearFps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- // animation doesn't start until the end
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ // animation doesn't start until the end
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(0.5f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(.95f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(.95f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isNull()
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
+ }
@Test
- fun deviceEntryParentViewAlpha_udfpsNotEnrolled_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha_udfpsNotEnrolled_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(0.5f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(.75f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(.75f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isNull()
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(deviceEntryParentViewAlpha).isNull()
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(deviceEntryParentViewAlpha).isNull()
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
index 24e4920..2c6436e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
@@ -19,21 +19,18 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,91 +38,77 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
- private lateinit var underTest: PrimaryBouncerToLockscreenTransitionViewModel
- private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
- @Before
- fun setUp() {
- repository = FakeKeyguardTransitionRepository()
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- biometricSettingsRepository = FakeBiometricSettingsRepository()
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+ val biometricSettingsRepository = kosmos.biometricSettingsRepository
- underTest =
- PrimaryBouncerToLockscreenTransitionViewModel(
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = repository,
- )
- .keyguardTransitionInteractor,
- DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository(),
- biometricSettingsRepository = biometricSettingsRepository,
- ),
- )
- }
+ val underTest = kosmos.primaryBouncerToLockscreenTransitionViewModel
@Test
- fun deviceEntryParentViewAlpha() = runTest {
- val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
+ fun deviceEntryParentViewAlpha() =
+ testScope.runTest {
+ val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
- // immediately 1f
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ // immediately 1f
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(0.4f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(0.4f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(.85f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(.85f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(1f))
- assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(deviceEntryParentViewAlpha).isEqualTo(1f)
+ }
@Test
- fun deviceEntryBackgroundViewAlpha_udfpsEnrolled_show() = runTest {
- fingerprintPropertyRepository.supportsUdfps()
- val bgViewAlpha by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ fun deviceEntryBackgroundViewAlpha_udfpsEnrolled_show() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsUdfps()
+ val bgViewAlpha by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- // immediately 1f
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(bgViewAlpha).isEqualTo(1f)
+ // immediately 1f
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(bgViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(0.1f))
- assertThat(bgViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(0.1f))
+ assertThat(bgViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(.3f))
- assertThat(bgViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(.3f))
+ assertThat(bgViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(.5f))
- assertThat(bgViewAlpha).isEqualTo(1f)
+ keyguardTransitionRepository.sendTransitionStep(step(.5f))
+ assertThat(bgViewAlpha).isEqualTo(1f)
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(bgViewAlpha).isEqualTo(1f)
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(bgViewAlpha).isEqualTo(1f)
+ }
@Test
- fun deviceEntryBackgroundViewAlpha_rearFpEnrolled_noUpdates() = runTest {
- fingerprintPropertyRepository.supportsRearFps()
- val bgViewAlpha by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
- repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(bgViewAlpha).isNull()
+ fun deviceEntryBackgroundViewAlpha_rearFpEnrolled_noUpdates() =
+ testScope.runTest {
+ fingerprintPropertyRepository.supportsRearFps()
+ val bgViewAlpha by collectLastValue(underTest.deviceEntryBackgroundViewAlpha)
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(bgViewAlpha).isNull()
- repository.sendTransitionStep(step(0.5f))
- assertThat(bgViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(bgViewAlpha).isNull()
- repository.sendTransitionStep(step(.75f))
- assertThat(bgViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(.75f))
+ assertThat(bgViewAlpha).isNull()
- repository.sendTransitionStep(step(1f))
- assertThat(bgViewAlpha).isNull()
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(bgViewAlpha).isNull()
- repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(bgViewAlpha).isNull()
- }
+ keyguardTransitionRepository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+ assertThat(bgViewAlpha).isNull()
+ }
private fun step(
value: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
new file mode 100644
index 0000000..02d40da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.base.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
+import com.android.systemui.qs.tiles.base.interactor.FakeDisabledByPolicyInteractor
+import com.android.systemui.qs.tiles.base.interactor.FakeQSTileDataInteractor
+import com.android.systemui.qs.tiles.base.interactor.FakeQSTileUserActionInteractor
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.base.logging.QSTileLogger
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfigTestBuilder
+import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.user.data.repository.FakeUserRepository
+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.flow.launchIn
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+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
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class QSTileViewModelImplTest : SysuiTestCase() {
+
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+ @Mock private lateinit var qsTileLogger: QSTileLogger
+ @Mock private lateinit var qsTileAnalytics: QSTileAnalytics
+
+ private val userRepository = FakeUserRepository()
+ private val tileDataInteractor = FakeQSTileDataInteractor<Any>()
+ private val tileUserActionInteractor = FakeQSTileUserActionInteractor<Any>()
+ private val disabledByPolicyInteractor = FakeDisabledByPolicyInteractor()
+ private val falsingManager = FalsingManagerFake()
+
+ private val testCoroutineDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testCoroutineDispatcher)
+
+ private lateinit var underTest: QSTileViewModelImpl<Any>
+
+ @Before
+ fun setup() {
+ underTest =
+ QSTileViewModelImpl(
+ QSTileConfigTestBuilder.build {
+ policy = QSTilePolicy.Restricted("test_restriction")
+ },
+ { tileUserActionInteractor },
+ { tileDataInteractor },
+ {
+ object : QSTileDataToStateMapper<Any> {
+ override fun map(config: QSTileConfig, data: Any): QSTileState =
+ QSTileState.build(
+ { Icon.Resource(0, ContentDescription.Resource(0)) },
+ data.toString()
+ ) {}
+ }
+ },
+ disabledByPolicyInteractor,
+ userRepository,
+ falsingManager,
+ qsTileAnalytics,
+ qsTileLogger,
+ FakeSystemClock(),
+ testCoroutineDispatcher,
+ testScope.backgroundScope,
+ )
+ }
+
+ @Test
+ fun dumpWritesState() =
+ testScope.runTest {
+ tileDataInteractor.emitData("test_data")
+ underTest.state.launchIn(backgroundScope)
+ runCurrent()
+
+ val sw = StringWriter()
+ PrintWriter(sw).use { underTest.dump(it, emptyArray()) }
+
+ assertThat(sw.buffer.toString())
+ .isEqualTo(
+ "test_spec:\n" +
+ " QSTileState(" +
+ "icon=() -> com.android.systemui.common.shared.model.Icon, " +
+ "label=test_data, " +
+ "activationState=INACTIVE, " +
+ "secondaryLabel=null, " +
+ "supportedActions=[CLICK], " +
+ "contentDescription=null, " +
+ "stateDescription=null, " +
+ "sideViewIcon=None, " +
+ "enabledState=ENABLED, " +
+ "expandedAccessibilityClassName=android.widget.Switch)\n"
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
index 1b4ba64..cb90cc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
@@ -328,7 +328,7 @@
}
@Override
- public SystemUIDialog create(DialogDelegate<SystemUIDialog> delegate) {
+ public SystemUIDialog create(SystemUIDialog.Delegate delegate) {
SystemUIDialog dialog = super.create(delegate);
mLastDelegate = delegate;
mLastCreatedDialog = dialog;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
index c848287..8f696e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
@@ -89,8 +89,9 @@
userContextProvider,
onStartRecordingClicked,
mediaProjectionMetricsLogger,
+ systemUIDialogFactory
)
- dialog = systemUIDialogFactory.create(delegate)
+ dialog = delegate.createDialog()
delegate.onCreate(dialog, savedInstanceState = null)
whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 03878b7..b0b29e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -96,6 +96,7 @@
import com.android.systemui.keyguard.KeyguardViewConfigurator;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
@@ -343,6 +344,7 @@
protected final int mMaxUdfpsBurnInOffsetY = 5;
protected FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+ protected KeyguardClockInteractor mKeyguardClockInteractor;
protected FakeKeyguardRepository mFakeKeyguardRepository;
protected KeyguardInteractor mKeyguardInteractor;
protected SceneTestUtils mUtils = new SceneTestUtils(this);
@@ -527,7 +529,7 @@
.thenReturn(emptyFlow());
when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
.thenReturn(emptyFlow());
- when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+ when(mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY())
.thenReturn(emptyFlow());
// Lockscreen->Dreaming
@@ -565,7 +567,7 @@
.thenReturn(emptyFlow());
when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
.thenReturn(emptyFlow());
- when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
+ when(mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY())
.thenReturn(emptyFlow());
// Primary Bouncer->Gone
@@ -696,6 +698,7 @@
systemClock,
mKeyguardBottomAreaViewModel,
mKeyguardBottomAreaInteractor,
+ mKeyguardClockInteractor,
mAlternateBouncerInteractor,
mDreamingToLockscreenTransitionViewModel,
mOccludedToLockscreenTransitionViewModel,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 36b4435..28fe8e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -362,6 +362,28 @@
}
@Test
+ public void onInterceptTouchEvent_nsslMigrationOff_userActivity() {
+ mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_KEYGUARD_SHADE_MIGRATION_NSSL);
+
+ mTouchHandler.onInterceptTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
+ 0 /* metaState */));
+
+ verify(mCentralSurfaces).userActivity();
+ }
+
+ @Test
+ public void onInterceptTouchEvent_nsslMigrationOn_userActivity_not_called() {
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_KEYGUARD_SHADE_MIGRATION_NSSL);
+
+ mTouchHandler.onInterceptTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
+ 0 /* metaState */));
+
+ verify(mCentralSurfaces, times(0)).userActivity();
+ }
+
+ @Test
public void testOnTouchEvent_expansionResumesAfterBriefTouch() {
mFalsingManager.setIsClassifierEnabled(true);
mFalsingManager.setIsFalseTouch(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 39b306b..39739e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -190,7 +191,7 @@
powerInteractor,
sceneContainerFlags,
new FakeKeyguardBouncerRepository(),
- configurationRepository,
+ new ConfigurationInteractor(configurationRepository),
shadeRepository,
() -> sceneInteractor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 0587633..6ff7966 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -98,7 +98,6 @@
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
@@ -113,8 +112,9 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
+import java.util.Optional
+import org.mockito.Mockito.`when` as whenever
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -446,6 +446,26 @@
}
@Test
+ fun handleDispatchTouchEvent_nsslMigrationOff_userActivity_not_called() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_SHADE_MIGRATION_NSSL)
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+
+ interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
+
+ verify(centralSurfaces, times(0)).userActivity()
+ }
+
+ @Test
+ fun handleDispatchTouchEvent_nsslMigrationOn_userActivity() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_KEYGUARD_SHADE_MIGRATION_NSSL)
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+
+ interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
+
+ verify(centralSurfaces).userActivity()
+ }
+
+ @Test
fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() {
// down event should be intercepted by keyguardViewManager
whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index 62c0ebe..e723d7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -40,6 +40,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.flags.FeatureFlags;
@@ -228,7 +229,7 @@
powerInteractor,
sceneContainerFlags,
new FakeKeyguardBouncerRepository(),
- configurationRepository,
+ new ConfigurationInteractor(configurationRepository),
mShadeRepository,
() -> sceneInteractor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index 5f8777d..f8aa359 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -225,4 +225,13 @@
underTest.setLegacyQsFullscreen(true)
assertThat(underTest.legacyQsFullscreen.value).isEqualTo(true)
}
+
+ @Test
+ fun updateLegacyIsClosing() =
+ testScope.runTest {
+ assertThat(underTest.legacyIsClosing.value).isEqualTo(false)
+
+ underTest.setLegacyIsClosing(true)
+ assertThat(underTest.legacyIsClosing.value).isEqualTo(true)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
new file mode 100644
index 0000000..40006ba
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysUITestComponent
+import com.android.systemui.SysUITestModule
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.TestMocksModule
+import com.android.systemui.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.flags.Flags
+import com.android.systemui.runCurrent
+import com.android.systemui.runTest
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.ObservableTransitionState
+import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth
+import dagger.BindsInstance
+import dagger.Component
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import org.junit.Test
+
+@SmallTest
+class ShadeAnimationInteractorSceneContainerImplTest : SysuiTestCase() {
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent : SysUITestComponent<ShadeAnimationInteractorSceneContainerImpl> {
+ val sceneInteractor: SceneInteractor
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
+ }
+
+ private val dozeParameters: DozeParameters = mock()
+
+ private val testComponent: TestComponent =
+ DaggerShadeAnimationInteractorSceneContainerImplTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule { set(Flags.FULL_SCREEN_USER_SWITCHER, true) },
+ mocks =
+ TestMocksModule(
+ dozeParameters = dozeParameters,
+ ),
+ )
+
+ @Test
+ fun isAnyCloseAnimationRunning_qsToShade() =
+ testComponent.runTest() {
+ val actual by collectLastValue(underTest.isAnyCloseAnimationRunning)
+
+ // WHEN transitioning from QS to Shade
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.QuickSettings,
+ toScene = SceneKey.Shade,
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is animating closed
+ Truth.assertThat(actual).isFalse()
+ }
+
+ @Test
+ fun isAnyCloseAnimationRunning_qsToGone_userInputNotOngoing() =
+ testComponent.runTest() {
+ val actual by collectLastValue(underTest.isAnyCloseAnimationRunning)
+
+ // WHEN transitioning from QS to Gone with no ongoing user input
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.QuickSettings,
+ toScene = SceneKey.Gone,
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is animating closed
+ Truth.assertThat(actual).isTrue()
+ }
+
+ @Test
+ fun isAnyCloseAnimationRunning_qsToGone_userInputOngoing() =
+ testComponent.runTest() {
+ val actual by collectLastValue(underTest.isAnyCloseAnimationRunning)
+
+ // WHEN transitioning from QS to Gone with user input ongoing
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.QuickSettings,
+ toScene = SceneKey.Gone,
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(true),
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is not animating closed
+ Truth.assertThat(actual).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
index 565e20a..310b86f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
@@ -127,22 +127,22 @@
val actual by collectLastValue(underTest.qsExpansion)
// WHEN split shade is enabled and QS is expanded
- keyguardRepository.setStatusBarState(StatusBarState.SHADE)
overrideResource(R.bool.config_use_split_notification_shade, true)
configurationRepository.onAnyConfigurationChange()
- val progress = MutableStateFlow(.3f)
+ runCurrent()
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
fromScene = SceneKey.QuickSettings,
toScene = SceneKey.Shade,
- progress = progress,
+ progress = MutableStateFlow(.3f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
runCurrent()
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
// THEN legacy shade expansion is passed through
Truth.assertThat(actual).isEqualTo(.3f)
@@ -157,6 +157,8 @@
// WHEN split shade is not enabled and QS is expanded
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
overrideResource(R.bool.config_use_split_notification_shade, false)
+ configurationRepository.onAnyConfigurationChange()
+ runCurrent()
val progress = MutableStateFlow(.3f)
val transitionState =
MutableStateFlow<ObservableTransitionState>(
@@ -182,13 +184,12 @@
// WHEN scene transition active
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- val progress = MutableStateFlow(.3f)
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
fromScene = SceneKey.QuickSettings,
toScene = SceneKey.Shade,
- progress = progress,
+ progress = MutableStateFlow(.3f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
)
@@ -347,6 +348,52 @@
Truth.assertThat(expansionAmount).isEqualTo(0f)
}
+ fun isQsBypassingShade_goneToQs() =
+ testComponent.runTest() {
+ val actual by collectLastValue(underTest.isQsBypassingShade)
+
+ // WHEN transitioning from QS directly to Gone
+ configurationRepository.onAnyConfigurationChange()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.QuickSettings,
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is bypassing shade
+ Truth.assertThat(actual).isTrue()
+ }
+
+ fun isQsBypassingShade_shadeToQs() =
+ testComponent.runTest() {
+ val actual by collectLastValue(underTest.isQsBypassingShade)
+
+ // WHEN transitioning from QS to Shade
+ configurationRepository.onAnyConfigurationChange()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.QuickSettings,
+ progress = MutableStateFlow(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+
+ // THEN qs is not bypassing shade
+ Truth.assertThat(actual).isFalse()
+ }
+
@Test
fun lockscreenShadeExpansion_transitioning_toAndFromDifferentScenes() =
testComponent.runTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index ae659f4..186ae6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -24,11 +24,11 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.TRANSIT_CLOCK
-import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.ClockId
-import com.android.systemui.plugins.ClockMetadata
-import com.android.systemui.plugins.ClockProviderPlugin
-import com.android.systemui.plugins.ClockSettings
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMetadata
+import com.android.systemui.plugins.clocks.ClockProviderPlugin
+import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.plugins.PluginLifecycleManager
import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index bd3dae4..fef262f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -24,9 +24,9 @@
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
-import com.android.systemui.customization.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.ClockSettings
+import com.android.systemui.customization.R
+import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index 7546dfa..dff91dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -121,7 +122,7 @@
powerInteractor,
sceneContainerFlags,
FakeKeyguardBouncerRepository(),
- configurationRepository,
+ ConfigurationInteractor(configurationRepository),
shadeRepository,
utils::sceneInteractor
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 8440e00..a5f3f57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -44,7 +44,7 @@
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.WeatherData
+import com.android.systemui.plugins.clocks.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
import com.android.systemui.settings.UserTracker
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index e488f39..bd46474 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -34,12 +34,14 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.TestScopeProvider;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeStateEvents;
import com.android.systemui.shade.ShadeStateEvents.ShadeStateEventsListener;
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
@@ -51,6 +53,7 @@
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -62,6 +65,10 @@
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;
+import kotlinx.coroutines.flow.MutableStateFlow;
+import kotlinx.coroutines.flow.StateFlowKt;
+import kotlinx.coroutines.test.TestScope;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -78,6 +85,7 @@
@Mock private ShadeStateEvents mShadeStateEvents;
@Mock private VisibilityLocationProvider mVisibilityLocationProvider;
@Mock private VisualStabilityProvider mVisualStabilityProvider;
+ @Mock private ShadeAnimationInteractor mShadeAnimationInteractor;
@Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
@@ -86,6 +94,9 @@
private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
+ private final TestScope mTestScope = TestScopeProvider.getTestScope();
+ private final JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope());
+ private final MutableStateFlow<Boolean> mShadeClosing = StateFlowKt.MutableStateFlow(false);
private WakefulnessLifecycle.Observer mWakefulnessObserver;
private StatusBarStateController.StateListener mStatusBarStateListener;
@@ -103,11 +114,13 @@
mDumpManager,
mHeadsUpManager,
mShadeStateEvents,
+ mShadeAnimationInteractor,
+ mJavaAdapter,
mStatusBarStateController,
mVisibilityLocationProvider,
mVisualStabilityProvider,
mWakefulnessLifecycle);
-
+ when(mShadeAnimationInteractor.isAnyCloseAnimationRunning()).thenReturn(mShadeClosing);
mCoordinator.attach(mNotifPipeline);
// capture arguments:
@@ -549,7 +562,8 @@
}
private void setPanelCollapsing(boolean collapsing) {
- mNotifPanelEventsCallback.onPanelCollapsingChanged(collapsing);
+ mShadeClosing.setValue(collapsing);
+ mTestScope.getTestScheduler().runCurrent();
}
private void setPulsing(boolean pulsing) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
index 7415645..349a35eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -285,28 +285,13 @@
assertThat(iconColors.tint).isEqualTo(0xAABBCC)
- val staticDrawableColor = iconColors.staticDrawableColor(Rect(), isColorized = true)
+ val staticDrawableColor = iconColors.staticDrawableColor(Rect())
assertThat(staticDrawableColor).isEqualTo(0xAABBCC)
}
@Test
- fun iconColors_staticDrawableColor_nonColorized() =
- testComponent.runTest {
- darkIconRepository.darkState.value =
- SysuiDarkIconDispatcher.DarkChange(
- emptyList(),
- 0f,
- 0xAABBCC,
- )
- val iconColorsLookup by collectLastValue(underTest.iconColors)
- val iconColors = iconColorsLookup?.iconColors(Rect())
- val staticDrawableColor = iconColors?.staticDrawableColor(Rect(), isColorized = false)
- assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
- }
-
- @Test
- fun iconColors_staticDrawableColor_isColorized_notInDarkTintArea() =
+ fun iconColors_staticDrawableColor_notInDarkTintArea() =
testComponent.runTest {
darkIconRepository.darkState.value =
SysuiDarkIconDispatcher.DarkChange(
@@ -316,8 +301,7 @@
)
val iconColorsLookup by collectLastValue(underTest.iconColors)
val iconColors = iconColorsLookup?.iconColors(Rect(1, 1, 4, 4))
- val staticDrawableColor =
- iconColors?.staticDrawableColor(Rect(6, 6, 7, 7), isColorized = true)
+ val staticDrawableColor = iconColors?.staticDrawableColor(Rect(6, 6, 7, 7))
assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 62a2bc5..5102b4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -55,6 +55,7 @@
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
@@ -167,7 +168,7 @@
PowerInteractorFactory.create().getPowerInteractor(),
mSceneTestUtils.getSceneContainerFlags(),
new FakeKeyguardBouncerRepository(),
- new FakeConfigurationRepository(),
+ new ConfigurationInteractor(new FakeConfigurationRepository()),
new FakeShadeRepository(),
() -> mSceneTestUtils.sceneInteractor());
mViewModel =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
index 59bf9f3..9419d63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
@@ -20,6 +20,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -56,7 +57,7 @@
PowerInteractorFactory.create().powerInteractor,
sceneTestUtils.sceneContainerFlags,
FakeKeyguardBouncerRepository(),
- FakeConfigurationRepository(),
+ ConfigurationInteractor(FakeConfigurationRepository()),
FakeShadeRepository(),
) {
sceneTestUtils.sceneInteractor()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 52c25f7..8585d46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -96,6 +96,7 @@
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.FakeFeatureFlagsClassic;
@@ -415,7 +416,7 @@
powerInteractor,
sceneContainerFlags,
new FakeKeyguardBouncerRepository(),
- configurationRepository,
+ new ConfigurationInteractor(configurationRepository),
shadeRepository,
() -> sceneInteractor);
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/keyguard/logging/BiometricUnlockLoggerKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/keyguard/logging/BiometricUnlockLoggerKosmos.kt
index 4098987..f55ae2f 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/keyguard/logging/BiometricUnlockLoggerKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.keyguard.logging
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.biometricUnlockLogger by Kosmos.Fixture { mock<BiometricUnlockLogger>() }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/keyguard/logging/KeyguardTransitionAnimationLoggerKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/keyguard/logging/KeyguardTransitionAnimationLoggerKosmos.kt
index 4098987..db2a87e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/keyguard/logging/KeyguardTransitionAnimationLoggerKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.keyguard.logging
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.keyguardTransitionAnimationLogger by
+ Kosmos.Fixture { mock<KeyguardTransitionAnimationLogger>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt
new file mode 100644
index 0000000..5475659
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.viewmodel.deviceEntryIconViewModel
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.phone.systemUIDialogManager
+
+val Kosmos.deviceEntryUdfpsTouchOverlayViewModel by Fixture {
+ DeviceEntryUdfpsTouchOverlayViewModel(
+ deviceEntryIconViewModel = deviceEntryIconViewModel,
+ systemUIDialogManager = systemUIDialogManager,
+ )
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt
index 4098987..06b6cda6 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.bouncer.domain.interactor
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.primaryBouncerInteractor by Kosmos.Fixture { mock<PrimaryBouncerInteractor>() }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorKosmos.kt
similarity index 66%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorKosmos.kt
index 4098987..7e0e5f3 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.common.ui.domain.interactor
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.configurationInteractor: ConfigurationInteractor by
+ Kosmos.Fixture { ConfigurationInteractor(configurationRepository) }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
similarity index 64%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
index 4098987..8bb07d9 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.deviceentry.data.repository
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
+ Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
+val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
new file mode 100644
index 0000000..de6cacb
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.keyguard.logging.biometricUnlockLogger
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryHapticsRepository
+import com.android.systemui.keyevent.domain.interactor.keyEventInteractor
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.util.time.fakeSystemClock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.deviceEntryHapticsInteractor by
+ Kosmos.Fixture {
+ DeviceEntryHapticsInteractor(
+ repository = fakeDeviceEntryHapticsRepository,
+ fingerprintPropertyRepository = fingerprintPropertyRepository,
+ biometricSettingsRepository = biometricSettingsRepository,
+ keyEventInteractor = keyEventInteractor,
+ powerInteractor = powerInteractor,
+ systemClock = fakeSystemClock,
+ logger = biometricUnlockLogger,
+ )
+ }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/data/repository/KeyEventRepositoryKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/data/repository/KeyEventRepositoryKosmos.kt
index 4098987..1238a7a 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/data/repository/KeyEventRepositoryKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.keyevent.data.repository
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.keyEventRepository: KeyEventRepository by Kosmos.Fixture { fakeKeyEventRepository }
+val Kosmos.fakeKeyEventRepository by Kosmos.Fixture { FakeKeyEventRepository() }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorKosmos.kt
index 4098987..53a1b03 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyevent/domain/interactor/KeyEventInteractorKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.keyevent.domain.interactor
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.keyevent.data.repository.keyEventRepository
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.keyEventInteractor by
+ Kosmos.Fixture { KeyEventInteractor(repository = keyEventRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/FakeKeyguardDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/FakeKeyguardDataLayerModule.kt
index 6838e76..abbd9be 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/FakeKeyguardDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/FakeKeyguardDataLayerModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.data
import com.android.systemui.keyguard.data.repository.FakeCommandQueueModule
+import com.android.systemui.keyguard.data.repository.FakeKeyguardClockRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeKeyguardSurfaceBehindRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepositoryModule
@@ -28,6 +29,7 @@
FakeKeyguardRepositoryModule::class,
FakeKeyguardTransitionRepositoryModule::class,
FakeKeyguardSurfaceBehindRepositoryModule::class,
+ FakeKeyguardClockRepositoryModule::class,
]
)
object FakeKeyguardDataLayerModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
new file mode 100644
index 0000000..85a233fd
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import com.android.keyguard.ClockEventController
+import com.android.keyguard.KeyguardClockSwitch.ClockSize
+import com.android.keyguard.KeyguardClockSwitch.LARGE
+import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.shared.clocks.DEFAULT_CLOCK_ID
+import com.android.systemui.util.mockito.mock
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeKeyguardClockRepository @Inject constructor() : KeyguardClockRepository {
+ private val _clockSize = MutableStateFlow(LARGE)
+ override val clockSize: StateFlow<Int> = _clockSize
+
+ private val _selectedClockSize = MutableStateFlow(SettingsClockSize.DYNAMIC)
+ override val selectedClockSize = _selectedClockSize
+
+ private val _currentClockId = MutableStateFlow(DEFAULT_CLOCK_ID)
+ override val currentClockId: Flow<ClockId> = _currentClockId
+
+ private val _currentClock = MutableStateFlow(null)
+ override val currentClock = _currentClock
+ override val clockEventController: ClockEventController
+ get() = mock()
+
+ override fun setClockSize(@ClockSize size: Int) {
+ _clockSize.value = size
+ }
+}
+
+@Module
+interface FakeKeyguardClockRepositoryModule {
+ @Binds fun bindFake(fake: FakeKeyguardClockRepository): KeyguardClockRepository
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 4068e40..81a7bec 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
-import com.android.keyguard.KeyguardClockSwitch.LARGE
import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
@@ -26,7 +25,6 @@
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
import com.android.systemui.keyguard.shared.model.StatusBarState
import dagger.Binds
import dagger.Module
@@ -42,8 +40,6 @@
class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
private val _deferKeyguardDone: MutableSharedFlow<KeyguardDone> = MutableSharedFlow()
override val keyguardDone: Flow<KeyguardDone> = _deferKeyguardDone
- private val _clockSize = MutableStateFlow<Int>(LARGE)
- override val clockSize: Flow<Int> = _clockSize
private val _clockShouldBeCentered = MutableStateFlow<Boolean>(true)
override val clockShouldBeCentered: Flow<Boolean> = _clockShouldBeCentered
@@ -123,17 +119,6 @@
private val _keyguardAlpha = MutableStateFlow(1f)
override val keyguardAlpha: StateFlow<Float> = _keyguardAlpha
- private val _keyguardRootViewVisibility =
- MutableStateFlow(
- KeyguardRootViewVisibilityState(
- 0,
- goingToFullShade = false,
- occlusionTransitionRunning = false
- )
- )
- override val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState> =
- _keyguardRootViewVisibility.asStateFlow()
-
override fun setQuickSettingsVisible(isVisible: Boolean) {
_isQuickSettingsVisible.value = isVisible
}
@@ -187,10 +172,6 @@
_deferKeyguardDone.emit(timing)
}
- override fun setClockSize(size: Int) {
- _clockSize.value = size
- }
-
override fun setClockShouldBeCentered(shouldBeCentered: Boolean) {
_clockShouldBeCentered.value = shouldBeCentered
}
@@ -254,19 +235,6 @@
override fun setKeyguardAlpha(alpha: Float) {
_keyguardAlpha.value = alpha
}
-
- override fun setKeyguardVisibility(
- statusBarState: Int,
- goingToFullShade: Boolean,
- occlusionTransitionRunning: Boolean
- ) {
- _keyguardRootViewVisibility.value =
- KeyguardRootViewVisibilityState(
- statusBarState,
- goingToFullShade,
- occlusionTransitionRunning
- )
- }
}
@Module
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryKosmos.kt
similarity index 66%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryKosmos.kt
index 4098987..e6716ba3 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.keyguard.data.repository
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+val Kosmos.keyguardClockRepository: KeyguardClockRepository by
+ Kosmos.Fixture { fakeKeyguardClockRepository }
+val Kosmos.fakeKeyguardClockRepository by Kosmos.Fixture { FakeKeyguardClockRepository() }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
similarity index 66%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
index 4098987..d791e94 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.keyguard.domain.interactor
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+val Kosmos.keyguardClockInteractor by
+ Kosmos.Fixture { KeyguardClockInteractor(keyguardClockRepository = keyguardClockRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index c575bb3..0bba36b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -19,6 +19,7 @@
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -63,7 +64,7 @@
commandQueue = commandQueue,
sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
- configurationRepository = configurationRepository,
+ configurationInteractor = ConfigurationInteractor(configurationRepository),
shadeRepository = shadeRepository,
sceneInteractorProvider = { sceneInteractor },
powerInteractor = powerInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
index bb84036..58d99b5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.power.domain.interactor.powerInteractor
@@ -34,7 +34,7 @@
powerInteractor = powerInteractor,
sceneContainerFlags = sceneContainerFlags,
bouncerRepository = keyguardBouncerRepository,
- configurationRepository = configurationRepository,
+ configurationInteractor = configurationInteractor,
shadeRepository = shadeRepository,
sceneInteractorProvider = { sceneInteractor },
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt
new file mode 100644
index 0000000..8d6529a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui
+
+import com.android.keyguard.logging.keyguardTransitionAnimationLogger
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.keyguardTransitionAnimationFlow by Fixture {
+ KeyguardTransitionAnimationFlow(
+ scope = applicationCoroutineScope,
+ logger = keyguardTransitionAnimationLogger,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt
new file mode 100644
index 0000000..9f0466d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.alternateBouncerViewModel by Fixture {
+ AlternateBouncerViewModel(
+ statusBarKeyguardViewManager = statusBarKeyguardViewManager,
+ transitionInteractor = keyguardTransitionInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..44e5426
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModelKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.aodToGoneTransitionViewModel by Fixture {
+ AodToGoneTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelKosmos.kt
index a31ab3e..b5a5f03 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelKosmos.kt
@@ -20,6 +20,7 @@
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -28,5 +29,6 @@
AodToLockscreenTransitionViewModel(
interactor = keyguardTransitionInteractor,
deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..27ad0f0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToOccludedTransitionViewModelKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.aodToOccludedTransitionViewModel by Fixture {
+ AodToOccludedTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt
new file mode 100644
index 0000000..6ffcc9a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.sysuiStatusBarStateController
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.bouncerToGoneFlows by Fixture {
+ BouncerToGoneFlows(
+ interactor = keyguardTransitionInteractor,
+ statusBarStateController = sysuiStatusBarStateController,
+ primaryBouncerInteractor = primaryBouncerInteractor,
+ keyguardDismissActionInteractor = mock(),
+ featureFlags = featureFlagsClassic,
+ shadeInteractor = shadeInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
new file mode 100644
index 0000000..299262b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.burnInInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.shared.flag.sceneContainerFlags
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager
+
+val Kosmos.deviceEntryIconViewModelTransitionsMock by Fixture {
+ mutableSetOf<DeviceEntryIconTransition>()
+}
+
+val Kosmos.deviceEntryIconViewModel by Fixture {
+ DeviceEntryIconViewModel(
+ transitions = deviceEntryIconViewModelTransitionsMock,
+ burnInInteractor = burnInInteractor,
+ shadeInteractor = shadeInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ transitionInteractor = keyguardTransitionInteractor,
+ keyguardInteractor = keyguardInteractor,
+ viewModel = aodToLockscreenTransitionViewModel,
+ shadeDependentFlows = shadeDependentFlows,
+ sceneContainerFlags = sceneContainerFlags,
+ keyguardViewController = { statusBarKeyguardViewManager },
+ deviceEntryHapticsInteractor = deviceEntryHapticsInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..8b5407c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.dreamingToLockscreenTransitionViewModel by Fixture {
+ DreamingToLockscreenTransitionViewModel(
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
+ fromDreamingTransitionInteractor = mock(),
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
index 5db95cf..14e2cff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
@@ -20,6 +20,7 @@
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -27,6 +28,7 @@
val Kosmos.goneToAodTransitionViewModel by Fixture {
GoneToAodTransitionViewModel(
interactor = keyguardTransitionInteractor,
- deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..073b34b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.goneToDreamingTransitionViewModel by Fixture {
+ GoneToDreamingTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
new file mode 100644
index 0000000..d878683
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+
+val Kosmos.keyguardClockViewModel by
+ Kosmos.Fixture {
+ KeyguardClockViewModel(
+ keyguardInteractor = keyguardInteractor,
+ keyguardClockInteractor = keyguardClockInteractor,
+ applicationScope = applicationCoroutineScope,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
index 663b845..13ee747 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
@@ -18,8 +18,9 @@
package com.android.systemui.keyguard.ui.viewmodel
-import android.content.applicationContext
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.keyguard.domain.interactor.burnInInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -32,7 +33,7 @@
val Kosmos.keyguardRootViewModel by Fixture {
KeyguardRootViewModel(
- context = applicationContext,
+ configurationInteractor = configurationInteractor,
deviceEntryInteractor = deviceEntryInteractor,
dozeParameters = dozeParameters,
keyguardInteractor = keyguardInteractor,
@@ -41,6 +42,9 @@
burnInInteractor = burnInInteractor,
goneToAodTransitionViewModel = goneToAodTransitionViewModel,
aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
+ occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
screenOffAnimationController = screenOffAnimationController,
+ keyguardClockViewModel = keyguardClockViewModel,
+ featureFlags = FakeFeatureFlagsClassic(),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..7865f71
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.lockscreenToAodTransitionViewModel by Fixture {
+ LockscreenToAodTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ shadeDependentFlows = shadeDependentFlows,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..b9f4b71
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.lockscreenToDreamingTransitionViewModel by Fixture {
+ LockscreenToDreamingTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ shadeDependentFlows = shadeDependentFlows,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..475aa2d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.lockscreenToGoneTransitionViewModel by Fixture {
+ LockscreenToGoneTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..8541a4f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.lockscreenToOccludedTransitionViewModel by Fixture {
+ LockscreenToOccludedTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ shadeDependentFlows = shadeDependentFlows,
+ configurationInteractor = configurationInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..65c47fc
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.lockscreenToPrimaryBouncerTransitionViewModel by Fixture {
+ LockscreenToPrimaryBouncerTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ shadeDependentFlows = shadeDependentFlows,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..ddde549
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.occludedToAodTransitionViewModel by Fixture {
+ OccludedToAodTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..5bbde2b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.occludedToLockscreenTransitionViewModel by Fixture {
+ OccludedToLockscreenTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ configurationInteractor = configurationInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..a7f29d6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.primaryBouncerToAodTransitionViewModel by Fixture {
+ PrimaryBouncerToAodTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..ace6ae3
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.sysuiStatusBarStateController
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.primaryBouncerToGoneTransitionViewModel by Fixture {
+ PrimaryBouncerToGoneTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ statusBarStateController = sysuiStatusBarStateController,
+ primaryBouncerInteractor = primaryBouncerInteractor,
+ keyguardDismissActionInteractor = mock(),
+ featureFlags = featureFlagsClassic,
+ bouncerToGoneFlows = bouncerToGoneFlows,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..3bbabf7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.primaryBouncerToLockscreenTransitionViewModel by Fixture {
+ PrimaryBouncerToLockscreenTransitionViewModel(
+ interactor = keyguardTransitionInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/alarm/AlarmTileKosmos.kt
similarity index 66%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/alarm/AlarmTileKosmos.kt
index 4098987..2fa92c7 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/alarm/AlarmTileKosmos.kt
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.qs.tiles.impl.alarm
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
+import com.android.systemui.statusbar.policy.PolicyModule
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+val Kosmos.qsAlarmTileConfig by
+ Kosmos.Fixture { PolicyModule.provideAlarmTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt
new file mode 100644
index 0000000..9d0faca
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom
+
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject.Companion.assertThat
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject.Companion.states
+import com.android.systemui.qs.tiles.impl.custom.TileSubject.Companion.assertThat
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Subject.Factory
+import com.google.common.truth.Truth
+
+/**
+ * [QSTileState]-specific extension for [Truth]. Use [assertThat] or [states] to get an instance of
+ * this subject.
+ */
+class QSTileStateSubject
+private constructor(failureMetadata: FailureMetadata, subject: QSTileState?) :
+ Subject(failureMetadata, subject) {
+
+ private val actual: QSTileState? = subject
+
+ /** Asserts if the [QSTileState] fields are the same. */
+ fun isEqualTo(other: QSTileState?) {
+ if (actual == null) {
+ check("other").that(other).isNull()
+ return
+ } else {
+ check("other").that(other).isNotNull()
+ other ?: return
+ }
+ check("icon").that(actual.icon()).isEqualTo(other.icon())
+ check("label").that(actual.label).isEqualTo(other.label)
+ check("activationState").that(actual.activationState).isEqualTo(other.activationState)
+ check("secondaryLabel").that(actual.secondaryLabel).isEqualTo(other.secondaryLabel)
+ check("label").that(actual.supportedActions).isEqualTo(other.supportedActions)
+ check("contentDescription")
+ .that(actual.contentDescription)
+ .isEqualTo(other.contentDescription)
+ check("stateDescription").that(actual.stateDescription).isEqualTo(other.stateDescription)
+ check("sideViewIcon").that(actual.sideViewIcon).isEqualTo(other.sideViewIcon)
+ check("enabledState").that(actual.enabledState).isEqualTo(other.enabledState)
+ check("expandedAccessibilityClassName")
+ .that(actual.expandedAccessibilityClassName)
+ .isEqualTo(other.expandedAccessibilityClassName)
+ }
+
+ companion object {
+
+ /** Returns a factory to be used with [Truth.assertAbout]. */
+ fun states(): Factory<QSTileStateSubject, QSTileState?> {
+ return Factory { failureMetadata: FailureMetadata, subject: QSTileState? ->
+ QSTileStateSubject(failureMetadata, subject)
+ }
+ }
+
+ /** Shortcut for `Truth.assertAbout(states()).that(state)`. */
+ fun assertThat(state: QSTileState?): QSTileStateSubject =
+ Truth.assertAbout(states()).that(state)
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 3c96051..d78bcb9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -47,6 +47,7 @@
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory
@@ -133,6 +134,9 @@
val configurationRepository: FakeConfigurationRepository by lazy {
FakeConfigurationRepository()
}
+ val configurationInteractor: ConfigurationInteractor by lazy {
+ ConfigurationInteractor(configurationRepository)
+ }
private val emergencyServicesRepository: EmergencyServicesRepository by lazy {
EmergencyServicesRepository(
applicationScope = applicationScope(),
@@ -246,7 +250,7 @@
commandQueue = FakeCommandQueue(),
sceneContainerFlags = sceneContainerFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
- configurationRepository = configurationRepository,
+ configurationInteractor = configurationInteractor,
shadeRepository = FakeShadeRepository(),
sceneInteractorProvider = { sceneInteractor() },
powerInteractor = PowerInteractorFactory.create().powerInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index 92ec4f2..9c10848 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -24,6 +24,7 @@
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
/** Fake implementation of [ShadeRepository] */
@SysUISingleton
@@ -105,6 +106,14 @@
_legacyQsFullscreen.value = legacyQsFullscreen
}
+ private val _legacyIsClosing = MutableStateFlow(false)
+ @Deprecated("Use ShadeInteractor instead") override val legacyIsClosing = _legacyIsClosing
+
+ @Deprecated("Use ShadeInteractor instead")
+ override fun setLegacyIsClosing(isClosing: Boolean) {
+ _legacyIsClosing.value = isClosing
+ }
+
fun setShadeModel(model: ShadeModel) {
_shadeModel.value = model
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SysuiStatusBarStateControllerKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SysuiStatusBarStateControllerKosmos.kt
index 4098987..fead581 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SysuiStatusBarStateControllerKosmos.kt
@@ -14,10 +14,8 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.statusbar
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.sysuiStatusBarStateController by Kosmos.Fixture { FakeStatusBarStateController() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
index c17083c..e2479fe 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
@@ -18,6 +18,7 @@
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.viewmodel.occludedToLockscreenTransitionViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -31,5 +32,6 @@
keyguardInteractor = keyguardInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
shadeInteractor = shadeInteractor,
+ occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
)
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerKosmos.kt
index 4098987..4e15ea2 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.statusbar.phone
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.statusBarKeyguardViewManager by Kosmos.Fixture { mock<StatusBarKeyguardViewManager>() }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/SystemUIDialogManagerKosmos.kt
similarity index 68%
copy from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/SystemUIDialogManagerKosmos.kt
index 4098987..7dfbf2a 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/SystemUIDialogManagerKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spaprivileged.settingsprovider
+package com.android.systemui.statusbar.phone
-import android.content.Context
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
- settingsGlobalFlow(name, sendInitialValue) { }
+var Kosmos.systemUIDialogManager by Kosmos.Fixture { mock<SystemUIDialogManager>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt
index 50d3f0a..282e2e8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt
@@ -24,7 +24,7 @@
@SysUISingleton
class FakeDarkIconRepository @Inject constructor() : DarkIconRepository {
- override val darkState = MutableStateFlow(DarkChange(emptyList(), 0f, 0))
+ override val darkState = MutableStateFlow(DarkChange.EMPTY)
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
index 5ae8e22..377e97c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
@@ -14,15 +14,44 @@
package com.android.systemui.utils.leaks;
+import android.app.AlarmManager;
import android.testing.LeakCheck;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+import java.util.ArrayList;
+import java.util.List;
+
public class FakeNextAlarmController extends BaseLeakChecker<NextAlarmChangeCallback>
implements NextAlarmController {
+ private AlarmManager.AlarmClockInfo mNextAlarm = null;
+ private List<NextAlarmChangeCallback> mCallbacks = new ArrayList<>();
+
public FakeNextAlarmController(LeakCheck test) {
super(test, "alarm");
}
+
+ /**
+ * Helper method for setting the next alarm
+ */
+ public void setNextAlarm(AlarmManager.AlarmClockInfo nextAlarm) {
+ this.mNextAlarm = nextAlarm;
+ for (var callback: mCallbacks) {
+ callback.onNextAlarmChanged(nextAlarm);
+ }
+ }
+
+ @Override
+ public void addCallback(NextAlarmChangeCallback listener) {
+ mCallbacks.add(listener);
+ listener.onNextAlarmChanged(mNextAlarm);
+ }
+
+ @Override
+ public void removeCallback(NextAlarmChangeCallback listener) {
+ mCallbacks.remove(listener);
+ }
+
}
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index 72eb665..0319848 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -1,7 +1,21 @@
{
- "presubmit": [
- // Let's only run this one as a smoke test.
- // TODO: Enable it once the infra knows how to run it.
- // { "name": "CtsUtilTestCasesRavenwood" }
- ]
+ "presubmit": [
+ {
+ "name": "RavenwoodMockitoTest_device"
+ }
+ ],
+ "ravenwood-presubmit": [
+ {
+ "name": "RavenwoodMinimumTest",
+ "host": true
+ },
+ {
+ "name": "RavenwoodMockitoTest",
+ "host": true
+ },
+ {
+ "name": "CtsUtilTestCasesRavenwood",
+ "host": true
+ }
+ ]
}
diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/framework-minus-apex-ravenwood-policies.txt
index 96cfa48..6a6ae38 100644
--- a/ravenwood/framework-minus-apex-ravenwood-policies.txt
+++ b/ravenwood/framework-minus-apex-ravenwood-policies.txt
@@ -85,18 +85,13 @@
class com.android.internal.util.FastPrintWriter stubclass
class com.android.internal.util.GrowingArrayUtils stubclass
class com.android.internal.util.LineBreakBufferedWriter stubclass
+class com.android.internal.util.Parcelling stubclass
class com.android.internal.util.Preconditions stubclass
class com.android.internal.util.StringPool stubclass
class com.android.internal.os.SomeArgs stubclass
# Parcel
-class android.os.Parcel stubclass
- method writeException (Ljava/lang/Exception;)V @writeException$ravenwood
- method writeNoException ()V @writeNoException$ravenwood
-class android.os.Parcel !com.android.hoststubgen.nativesubstitution.Parcel_host
-
-class android.os.Parcelable stubclass
class android.os.ParcelFormatException stubclass
class android.os.BadParcelableException stubclass
class android.os.BadTypeParcelableException stubclass
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 be0c09e..eacdc2f 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -32,6 +32,8 @@
android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
android.os.Binder.init$ravenwood();
+ com.android.server.LocalServices.removeAllServicesForTest();
+
if (rule.mProvideMainThread) {
final HandlerThread main = new HandlerThread(MAIN_THREAD_NAME);
main.start();
@@ -45,6 +47,8 @@
Looper.clearMainLooperForTest();
}
+ com.android.server.LocalServices.removeAllServicesForTest();
+
android.os.Process.reset$ravenwood();
android.os.Binder.reset$ravenwood();
}
diff --git a/ravenwood/minimum-test/Android.bp b/ravenwood/minimum-test/Android.bp
new file mode 100644
index 0000000..bf3583c
--- /dev/null
+++ b/ravenwood/minimum-test/Android.bp
@@ -0,0 +1,24 @@
+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"],
+}
+
+// Minimum ravenwood test according to test-authors.md.
+android_ravenwood_test {
+ name: "RavenwoodMinimumTest",
+
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.test.rules",
+ ],
+
+ srcs: [
+ "test/**/*.java",
+ ],
+ sdk_version: "test_current",
+ auto_gen_config: true,
+}
diff --git a/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java b/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
new file mode 100644
index 0000000..085c186
--- /dev/null
+++ b/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ravenwood;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodMinimumTest {
+ @Rule
+ public RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+ .setProcessApp()
+ .build();
+
+ @Test
+ public void testSimple() {
+ Assert.assertTrue(android.os.Process.isApplicationUid(android.os.Process.myUid()));
+ }
+
+ @Test
+ @IgnoreUnderRavenwood
+ public void testIgnored() {
+ throw new RuntimeException("Shouldn't be executed under ravenwood");
+ }
+}
diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/ravenwood-annotation-allowed-classes.txt
index eba6e0b..2902932 100644
--- a/ravenwood/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/ravenwood-annotation-allowed-classes.txt
@@ -23,6 +23,8 @@
android.os.Looper
android.os.Message
android.os.MessageQueue
+android.os.Parcel
+android.os.Parcelable
android.os.Process
android.os.SystemClock
android.os.ThreadLocalWorkSource
@@ -64,3 +66,5 @@
android.graphics.PointF
android.graphics.Rect
android.graphics.RectF
+
+com.android.server.LocalServices
diff --git a/ravenwood/test-authors.md b/ravenwood/test-authors.md
index 2b5bd908..5adef53 100644
--- a/ravenwood/test-authors.md
+++ b/ravenwood/test-authors.md
@@ -31,6 +31,14 @@
* Write your unit test just like you would for an Android device:
```
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@RunWith(AndroidJUnit4.class)
public class MyCodeTest {
@Test
@@ -43,6 +51,14 @@
* APIs available under Ravenwood are stateless by default. If your test requires explicit states (such as defining the UID you’re running under, or requiring a main `Looper` thread), add a `RavenwoodRule` to declare that:
```
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@RunWith(AndroidJUnit4.class)
public class MyCodeTest {
@Rule
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 2032a50..b4deeb0 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -29,12 +29,14 @@
import android.content.ComponentName;
import android.content.Context;
import android.hardware.display.DisplayManager;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -66,8 +68,8 @@
* TODO(241117292): Remove or cut down during simultaneous user refactoring.
*/
public class ProxyManager {
- private static final boolean DEBUG = false;
private static final String LOG_TAG = "ProxyManager";
+ private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG) && Build.IS_DEBUGGABLE;
// Names used to populate ComponentName and ResolveInfo in connection.mA11yServiceInfo and in
// the infos of connection.setInstalledAndEnabledServices
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index e3797c9..f55ecb0 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -916,18 +916,27 @@
&& event.getPointerCount() == 2;
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
- if (isActivated() && event.getPointerCount() == 2) {
- storePointerDownLocation(mSecondPointerDownLocation, event);
- mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
- ViewConfiguration.getTapTimeout());
- } else if (mIsTwoFingerCountReached) {
- // Placing two-finger triple-taps behind isActivated to avoid
- // blocking panning scaling state
+ if (event.getPointerCount() == 2) {
if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)) {
// 3tap and hold
afterLongTapTimeoutTransitionToDraggingState(event);
} else {
- afterMultiTapTimeoutTransitionToDelegatingState();
+ if (mDetectTwoFingerTripleTap) {
+ // If mDetectTwoFingerTripleTap, delay transition to the delegating
+ // state for mMultiTapMaxDelay to ensure reachability of
+ // multi finger multi tap
+ afterMultiTapTimeoutTransitionToDelegatingState();
+ }
+
+ if (isActivated()) {
+ // If activated, delay transition to the panning scaling
+ // state for tap timeout to ensure reachability of
+ // multi finger multi tap
+ storePointerDownLocation(mSecondPointerDownLocation, event);
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+ ViewConfiguration.getTapTimeout());
+ }
}
} else {
transitionToDelegatingStateAndClear();
@@ -953,6 +962,9 @@
// (which is a rare combo to be used aside from magnification)
if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
transitionToViewportDraggingStateAndClear(event);
+ } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)
+ && event.getPointerCount() == 2) {
+ transitionToViewportDraggingStateAndClear(event);
} else if (isActivated() && event.getPointerCount() == 2) {
if (mIsSinglePanningEnabled
&& overscrollState(event, mFirstPointerDownLocation)
@@ -961,11 +973,6 @@
}
//Primary pointer is swiping, so transit to PanningScalingState
transitToPanningScalingStateAndClear();
- } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)
- && event.getPointerCount() == 2) {
- // Placing two-finger triple-taps behind isActivated to avoid
- // blocking panning scaling state
- transitionToViewportDraggingStateAndClear(event);
} else if (mIsSinglePanningEnabled
&& isActivated()
&& event.getPointerCount() == 1) {
@@ -979,8 +986,11 @@
}
} else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
&& distanceClosestPointerToPoint(
- mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
- //Second pointer is swiping, so transit to PanningScalingState
+ mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance
+ // If mCompleteTapCount is not zero, it means that it is a multi tap
+ // gesture. So, we should not transit to the PanningScalingState.
+ && mCompletedTapCount == 0) {
+ // Second pointer is swiping, so transit to PanningScalingState
transitToPanningScalingStateAndClear();
}
}
@@ -988,6 +998,7 @@
case ACTION_UP: {
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
+ mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
if (!mFullScreenMagnificationController.magnificationRegionContains(
mDisplayId, event.getX(), event.getY())) {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 3323d0b..659112e 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -136,7 +136,6 @@
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V2-java",
"android.hardware.vibrator-V2-java",
- "android.nfc.flags-aconfig-java",
"app-compat-annotations",
"framework-tethering.stubs.module_lib",
"service-art.stubs.system_server",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 898b693..31c9348 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -45,7 +45,6 @@
import com.android.internal.pm.pkg.component.ParsedMainComponent;
import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.permission.persistence.RuntimePermissionsState;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.KnownPackages;
import com.android.server.pm.PackageArchiver;
@@ -1104,7 +1103,9 @@
* Read legacy permission states for permissions migration to new permission subsystem.
* Note that this api is supposed to be used for permissions state migration only.
*/
- public abstract RuntimePermissionsState getLegacyPermissionsState(@UserIdInt int userId);
+ // TODO: restore to com.android.permission.persistence.RuntimePermissionsState
+ // once Ravenwood includes Mainline stubs
+ public abstract Object getLegacyPermissionsState(@UserIdInt int userId);
/**
* @return permissions file version for the given user.
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f2d9759..f8f3d82 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -886,9 +886,7 @@
syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
}
- synchronized (mStats) {
- return mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, queries);
- }
+ return mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, queries);
}
/** Register callbacks for statsd pulled atoms. */
@@ -2730,13 +2728,13 @@
BatteryUsageStatsQuery query = builder.build();
synchronized (mStats) {
mStats.prepareForDumpLocked();
- BatteryUsageStats batteryUsageStats =
- mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
- if (proto) {
- batteryUsageStats.dumpToProto(fd);
- } else {
- batteryUsageStats.dump(pw, "");
- }
+ }
+ BatteryUsageStats batteryUsageStats =
+ mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
+ if (proto) {
+ batteryUsageStats.dumpToProto(fd);
+ } else {
+ batteryUsageStats.dump(pw, "");
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index b500ff1..3e1edf2 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -120,6 +120,7 @@
static final String[] sDeviceConfigAconfigScopes = new String[] {
"accessibility",
"android_core_networking",
+ "aoc",
"app_widgets",
"arc_next",
"avic",
@@ -179,6 +180,7 @@
"tv_system_ui",
"vibrator",
"virtual_devices",
+ "wallet_integration",
"wear_calling_messaging",
"wear_connectivity",
"wear_esim_carriers",
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index a770b66..2ed079a 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -29,3 +29,10 @@
description: "Disable BOOT_COMPLETED broadcast FGS start for certain types"
bug: "296558535"
}
+
+flag {
+ name: "bfgs_managed_network_access"
+ namespace: "backstage_power"
+ description: "Restrict network access for certain applications in BFGS process state"
+ bug: "304347838"
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 3446737..7780b39 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1180,6 +1180,8 @@
uidState.pkgOps.put(packageName,
new Ops(packageName, uidState));
}
+
+ createSandboxUidStateIfNotExistsForAppLocked(uid);
}
}
}
@@ -1261,6 +1263,8 @@
ops.put(code, new Op(uidState, packageName, code, uid));
}
}
+
+ createSandboxUidStateIfNotExistsForAppLocked(uid);
}
/**
@@ -4011,6 +4015,11 @@
return uidState;
}
+ private void createSandboxUidStateIfNotExistsForAppLocked(int uid) {
+ final int sandboxUid = Process.toSdkSandboxUid(uid);
+ getUidStateLocked(sandboxUid, true);
+ }
+
private void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible) {
synchronized (this) {
getUidStateTracker().updateAppWidgetVisibility(uidPackageNames, visible);
diff --git a/services/core/java/com/android/server/appop/AudioRestrictionManager.java b/services/core/java/com/android/server/appop/AudioRestrictionManager.java
index be87037..b9ccc53 100644
--- a/services/core/java/com/android/server/appop/AudioRestrictionManager.java
+++ b/services/core/java/com/android/server/appop/AudioRestrictionManager.java
@@ -43,7 +43,7 @@
static {
SparseBooleanArray audioMutedUsages = new SparseBooleanArray();
SparseBooleanArray vibrationMutedUsages = new SparseBooleanArray();
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.SDK_USAGES.toArray()) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION ||
suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL ||
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b1706ed..2f7d99f 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1595,8 +1595,8 @@
sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
- /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) {
- sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs);
+ /*package*/ void setLeAudioTimeout(String address, int device, int codec, int delayMs) {
+ sendIILMsg(MSG_IIL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, codec, address, delayMs);
}
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
@@ -1794,8 +1794,9 @@
return;
}
@AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
- mBtHelper.getA2dpCodecWithFallbackToSBC(
- btInfo.mDevice, "MSG_L_SET_BT_ACTIVE_DEVICE");
+ mBtHelper.getCodecWithFallback(btInfo.mDevice,
+ btInfo.mProfile, btInfo.mIsLeOutput,
+ "MSG_L_SET_BT_ACTIVE_DEVICE");
mDeviceInventory.onSetBtActiveDevice(btInfo, codec,
(btInfo.mProfile
!= BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
@@ -1819,22 +1820,24 @@
case MSG_IL_BTA2DP_TIMEOUT:
// msg.obj == address of BTA2DP device
synchronized (mDeviceStateLock) {
- mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
+ mDeviceInventory.onMakeA2dpDeviceUnavailableNow(
+ (String) msg.obj, msg.arg1);
}
break;
- case MSG_IL_BTLEAUDIO_TIMEOUT:
+ case MSG_IIL_BTLEAUDIO_TIMEOUT:
// msg.obj == address of LE Audio device
synchronized (mDeviceStateLock) {
mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
- (String) msg.obj, msg.arg1);
+ (String) msg.obj, msg.arg1, msg.arg2);
}
break;
case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: {
final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
synchronized (mDeviceStateLock) {
@AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
- mBtHelper.getA2dpCodecWithFallbackToSBC(
- btInfo.mDevice, "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
+ mBtHelper.getCodecWithFallback(btInfo.mDevice,
+ btInfo.mProfile, btInfo.mIsLeOutput,
+ "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
mDeviceInventory.onBluetoothDeviceConfigChange(
btInfo, codec, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
}
@@ -2084,7 +2087,7 @@
private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
- private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
+ private static final int MSG_IIL_BTLEAUDIO_TIMEOUT = 49;
private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53;
@@ -2104,7 +2107,7 @@
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_IL_BTA2DP_TIMEOUT:
- case MSG_IL_BTLEAUDIO_TIMEOUT:
+ case MSG_IIL_BTLEAUDIO_TIMEOUT:
case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
@@ -2196,7 +2199,7 @@
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_TIMEOUT:
- case MSG_IL_BTLEAUDIO_TIMEOUT:
+ case MSG_IIL_BTLEAUDIO_TIMEOUT:
case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e9b102b..e503f1f 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -689,9 +689,11 @@
case BluetoothProfile.LE_AUDIO:
case BluetoothProfile.LE_AUDIO_BROADCAST:
if (switchToUnavailable) {
- makeLeAudioDeviceUnavailableNow(address, btInfo.mAudioSystemDevice);
+ makeLeAudioDeviceUnavailableNow(address,
+ btInfo.mAudioSystemDevice, di.mDeviceCodecFormat);
} else if (switchToAvailable) {
- makeLeAudioDeviceAvailable(btInfo, streamType, "onSetBtActiveDevice");
+ makeLeAudioDeviceAvailable(
+ btInfo, streamType, codec, "onSetBtActiveDevice");
}
break;
default: throw new IllegalArgumentException("Invalid profile "
@@ -752,12 +754,13 @@
if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
- boolean a2dpCodecChange = false;
- if (btInfo.mProfile == BluetoothProfile.A2DP) {
+ boolean codecChange = false;
+ if (btInfo.mProfile == BluetoothProfile.A2DP
+ || btInfo.mProfile == BluetoothProfile.LE_AUDIO) {
if (di.mDeviceCodecFormat != codec) {
di.mDeviceCodecFormat = codec;
mConnectedDevices.replace(key, di);
- a2dpCodecChange = true;
+ codecChange = true;
}
final int res = mAudioSystem.handleDeviceConfigChange(
btInfo.mAudioSystemDevice, address, BtHelper.getName(btDevice), codec);
@@ -782,7 +785,7 @@
}
}
- if (!a2dpCodecChange) {
+ if (!codecChange) {
updateBluetoothPreferredModes_l(btDevice /*connectedDevice*/);
}
}
@@ -796,9 +799,9 @@
}
}
- /*package*/ void onMakeLeAudioDeviceUnavailableNow(String address, int device) {
+ /*package*/ void onMakeLeAudioDeviceUnavailableNow(String address, int device, int codec) {
synchronized (mDevicesLock) {
- makeLeAudioDeviceUnavailableNow(address, device);
+ makeLeAudioDeviceUnavailableNow(address, device, codec);
}
}
@@ -1335,6 +1338,27 @@
}
}
+ private static boolean devicesListEqual(@NonNull List<AudioDeviceAttributes> list1,
+ @NonNull List<AudioDeviceAttributes> list2) {
+ if (list1.size() != list2.size()) {
+ return false;
+ }
+ // This assumes a given device is only present once in a list
+ for (AudioDeviceAttributes d1 : list1) {
+ boolean found = false;
+ for (AudioDeviceAttributes d2 : list2) {
+ if (d1.equalTypeAddress(d2)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private int setDevicesRole(
ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
AudioSystemInterface addOp,
@@ -1342,31 +1366,26 @@
int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
synchronized (rolesMap) {
Pair<Integer, Integer> key = new Pair<>(useCase, role);
- List<AudioDeviceAttributes> roleDevices = new ArrayList<>();
- List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
-
if (rolesMap.containsKey(key)) {
- roleDevices = rolesMap.get(key);
- boolean equal = false;
- if (roleDevices.size() == devices.size()) {
- roleDevices.retainAll(devices);
- equal = roleDevices.size() == devices.size();
+ if (devicesListEqual(devices, rolesMap.get(key))) {
+ // NO OP: no change in preference
+ return AudioSystem.SUCCESS;
}
- if (!equal) {
- clearOp.deviceRoleAction(useCase, role, null);
- roleDevices.clear();
- appliedDevices.addAll(devices);
- }
- } else {
- appliedDevices.addAll(devices);
- }
- if (appliedDevices.isEmpty()) {
+ } else if (devices.isEmpty()) {
+ // NO OP: no preference to no preference
return AudioSystem.SUCCESS;
}
- final int status = addOp.deviceRoleAction(useCase, role, appliedDevices);
- if (status == AudioSystem.SUCCESS) {
- roleDevices.addAll(appliedDevices);
- rolesMap.put(key, roleDevices);
+ int status;
+ if (devices.isEmpty()) {
+ status = clearOp.deviceRoleAction(useCase, role, null);
+ if (status == AudioSystem.SUCCESS) {
+ rolesMap.remove(key);
+ }
+ } else {
+ status = addOp.deviceRoleAction(useCase, role, devices);
+ if (status == AudioSystem.SUCCESS) {
+ rolesMap.put(key, devices);
+ }
}
return status;
}
@@ -1641,11 +1660,12 @@
}
synchronized (mDevicesLock) {
- final ArraySet<String> toRemove = new ArraySet<>();
+ final ArraySet<Pair<String, Integer>> toRemove = new ArraySet<>();
// Disconnect ALL DEVICE_OUT_BLE_HEADSET or DEVICE_OUT_BLE_BROADCAST devices
mConnectedDevices.values().forEach(deviceInfo -> {
if (deviceInfo.mDeviceType == device) {
- toRemove.add(deviceInfo.mDeviceAddress);
+ toRemove.add(
+ new Pair<>(deviceInfo.mDeviceAddress, deviceInfo.mDeviceCodecFormat));
}
});
new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
@@ -1655,8 +1675,8 @@
final int delay = checkSendBecomingNoisyIntentInt(device,
AudioService.CONNECTION_STATE_DISCONNECTED,
AudioSystem.DEVICE_NONE);
- toRemove.stream().forEach(deviceAddress ->
- makeLeAudioDeviceUnavailableLater(deviceAddress, device, delay)
+ toRemove.stream().forEach(entry ->
+ makeLeAudioDeviceUnavailableLater(entry.first, device, entry.second, delay)
);
}
}
@@ -2200,7 +2220,8 @@
@GuardedBy("mDevicesLock")
private void makeLeAudioDeviceAvailable(
- AudioDeviceBroker.BtDeviceInfo btInfo, int streamType, String eventSource) {
+ AudioDeviceBroker.BtDeviceInfo btInfo, int streamType,
+ @AudioSystem.AudioFormatNativeEnumForBtCodec int codec, String eventSource) {
final int volumeIndex = btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10;
final int device = btInfo.mAudioSystemDevice;
@@ -2234,7 +2255,7 @@
AudioDeviceAttributes ada = new AudioDeviceAttributes(device, address, name);
final int res = AudioSystem.setDeviceConnectionState(ada,
- AudioSystem.DEVICE_STATE_AVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
+ AudioSystem.DEVICE_STATE_AVAILABLE, codec);
if (res != AudioSystem.AUDIO_STATUS_OK) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"APM failed to make available LE Audio device addr=" + address
@@ -2249,7 +2270,7 @@
// Reset LEA suspend state each time a new sink is connected
mDeviceBroker.clearLeAudioSuspended(true /* internalOnly */);
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
- new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT,
+ new DeviceInfo(device, name, address, codec,
peerAddress, groupId));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
@@ -2272,13 +2293,14 @@
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceUnavailableNow(String address, int device) {
+ private void makeLeAudioDeviceUnavailableNow(String address, int device,
+ @AudioSystem.AudioFormatNativeEnumForBtCodec int codec) {
AudioDeviceAttributes ada = null;
if (device != AudioSystem.DEVICE_NONE) {
ada = new AudioDeviceAttributes(device, address);
final int res = AudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
- AudioSystem.AUDIO_FORMAT_DEFAULT);
+ codec);
if (res != AudioSystem.AUDIO_STATUS_OK) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
@@ -2303,7 +2325,8 @@
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
+ private void makeLeAudioDeviceUnavailableLater(
+ String address, int device, int codec, int delayMs) {
// prevent any activity on the LEA output to avoid unwanted
// reconnection of the sink.
mDeviceBroker.setLeAudioSuspended(
@@ -2311,7 +2334,7 @@
// the device will be made unavailable later, so consider it disconnected right away
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
// send the delayed message to make the device unavailable later
- mDeviceBroker.setLeAudioTimeout(address, device, delayMs);
+ mDeviceBroker.setLeAudioTimeout(address, device, codec, delayMs);
}
@GuardedBy("mDevicesLock")
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 7b96215..a078d08 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -26,6 +26,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
import android.bluetooth.BluetoothLeAudioCodecStatus;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -250,35 +251,73 @@
}
}
- /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getA2dpCodec(
- @NonNull BluetoothDevice device) {
- if (mA2dp == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec(
+ @NonNull BluetoothDevice device, @AudioService.BtProfile int profile) {
+ switch (profile) {
+ case BluetoothProfile.A2DP: {
+ if (mA2dp == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ BluetoothCodecStatus btCodecStatus = null;
+ try {
+ btCodecStatus = mA2dp.getCodecStatus(device);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while getting status of " + device, e);
+ }
+ if (btCodecStatus == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ final BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
+ if (btCodecConfig == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ return AudioSystem.bluetoothA2dpCodecToAudioFormat(btCodecConfig.getCodecType());
+ }
+ case BluetoothProfile.LE_AUDIO: {
+ if (mLeAudio == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ BluetoothLeAudioCodecStatus btLeCodecStatus = null;
+ int groupId = mLeAudio.getGroupId(device);
+ try {
+ btLeCodecStatus = mLeAudio.getCodecStatus(groupId);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while getting status of " + device, e);
+ }
+ if (btLeCodecStatus == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ BluetoothLeAudioCodecConfig btLeCodecConfig =
+ btLeCodecStatus.getOutputCodecConfig();
+ if (btLeCodecConfig == null) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ return AudioSystem.bluetoothLeCodecToAudioFormat(btLeCodecConfig.getCodecType());
+ }
+ default:
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
- BluetoothCodecStatus btCodecStatus = null;
- try {
- btCodecStatus = mA2dp.getCodecStatus(device);
- } catch (Exception e) {
- Log.e(TAG, "Exception while getting status of " + device, e);
- }
- if (btCodecStatus == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
- }
- final BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
- if (btCodecConfig == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
- }
- return AudioSystem.bluetoothCodecToAudioFormat(btCodecConfig.getCodecType());
}
/*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec
- int getA2dpCodecWithFallbackToSBC(
- @NonNull BluetoothDevice device, @NonNull String source) {
- @AudioSystem.AudioFormatNativeEnumForBtCodec int codec = getA2dpCodec(device);
+ int getCodecWithFallback(
+ @NonNull BluetoothDevice device, @AudioService.BtProfile int profile,
+ boolean isLeOutput, @NonNull String source) {
+ // For profiles other than A2DP and LE Audio output, the audio codec format must be
+ // AUDIO_FORMAT_DEFAULT as native audio policy manager expects a specific audio format
+ // only if audio HW module selection based on format is supported for the device type.
+ if (!(profile == BluetoothProfile.A2DP
+ || (profile == BluetoothProfile.LE_AUDIO && isLeOutput))) {
+ return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ }
+ @AudioSystem.AudioFormatNativeEnumForBtCodec int codec =
+ getCodec(device, profile);
if (codec == AudioSystem.AUDIO_FORMAT_DEFAULT) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
- "getA2dpCodec DEFAULT from " + source + " fallback to SBC"));
- return AudioSystem.AUDIO_FORMAT_SBC;
+ "getCodec DEFAULT from " + source + " fallback to "
+ + (profile == BluetoothProfile.A2DP ? "SBC" : "LC3")));
+ return profile == BluetoothProfile.A2DP
+ ? AudioSystem.AUDIO_FORMAT_SBC : AudioSystem.AUDIO_FORMAT_LC3;
}
return codec;
}
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 61e4f36..4f7f31d 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -1016,6 +1016,11 @@
if (mSpat == null) {
mSpatCallback = new SpatializerCallback();
mSpat = AudioSystem.getSpatializer(mSpatCallback);
+ if (mSpat == null) {
+ Log.e(TAG, "createSpat(): No Spatializer found");
+ postReset();
+ return;
+ }
try {
//TODO: register heatracking callback only when sensors are registered
if (mIsHeadTrackingSupported) {
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
index 7452228..95a047f 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -116,8 +116,10 @@
service.setBiometicContextListener(new IBiometricContextListener.Stub() {
@Override
public void onFoldChanged(int foldState) {
- mFoldState = foldState;
- // no need to notify, not sent to HAL
+ if (mFoldState != foldState) {
+ mFoldState = foldState;
+ notifyChanged();
+ }
}
@Override
@@ -254,6 +256,7 @@
+ "isAwake: " + isAwake() + ", "
+ "isDisplayOn: " + isDisplayOn() + ", "
+ "dock: " + getDockedState() + ", "
- + "rotation: " + getCurrentRotation() + "]";
+ + "rotation: " + getCurrentRotation() + ", "
+ + "foldState: " + mFoldState + "]";
}
}
diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
index f78ca43..b4e0dff 100644
--- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
+++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
@@ -23,6 +23,7 @@
import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.common.AuthenticateReason;
import android.hardware.biometrics.common.DisplayState;
+import android.hardware.biometrics.common.FoldState;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
import android.hardware.biometrics.common.WakeReason;
@@ -250,6 +251,7 @@
OperationContextExt update(@NonNull BiometricContext biometricContext, boolean isCrypto) {
mAidlContext.isAod = biometricContext.isAod();
mAidlContext.displayState = toAidlDisplayState(biometricContext.getDisplayState());
+ mAidlContext.foldState = toAidlFoldState(biometricContext.getFoldState());
mAidlContext.isCrypto = isCrypto;
setFirstSessionId(biometricContext);
@@ -276,6 +278,19 @@
return DisplayState.UNKNOWN;
}
+ @FoldState
+ private static int toAidlFoldState(@IBiometricContextListener.FoldState int state) {
+ switch (state) {
+ case IBiometricContextListener.FoldState.FULLY_CLOSED:
+ return FoldState.FULLY_CLOSED;
+ case IBiometricContextListener.FoldState.FULLY_OPENED:
+ return FoldState.FULLY_OPENED;
+ case IBiometricContextListener.FoldState.HALF_OPENED:
+ return FoldState.HALF_OPENED;
+ }
+ return FoldState.UNKNOWN;
+ }
+
private void setFirstSessionId(@NonNull BiometricContext biometricContext) {
if (mIsBP) {
mSessionInfo = biometricContext.getBiometricPromptSessionInfo();
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 5bb5c53..a796544 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -52,7 +52,6 @@
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
-import android.nfc.INfcAdapter;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.os.Binder;
@@ -1281,45 +1280,19 @@
}
}
- // TODO(b/303286040): Remove the raw INfcAdapter usage once |ENABLE_NFC_MAINLINE_FLAG| is
- // rolled out.
- private static final String NFC_SERVICE_BINDER_NAME = "nfc";
- // Flags arguments to NFC adapter to enable/disable NFC
- public static final int DISABLE_POLLING_FLAGS = 0x1000;
- public static final int ENABLE_POLLING_FLAGS = 0x0000;
- private void setNfcReaderModeUsingINfcAdapter(boolean enablePolling) {
- IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME);
- if (nfcServiceBinder == null) {
+ private void notifyNfcService(boolean enablePolling) {
+ NfcManager nfcManager = mContext.getSystemService(NfcManager.class);
+ if (nfcManager == null) {
Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
return;
}
- INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder);
- int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
- if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags);
- try {
- nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null);
- } catch (RemoteException e) {
- Slog.w(TAG, "Could not notify NFC service, remote exception: " + e);
+ NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter();
+ if (nfcAdapter == null) {
+ Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
+ return;
}
- }
-
- private void notifyNfcService(boolean enablePolling) {
- if (android.nfc.Flags.enableNfcMainline()) {
- NfcManager nfcManager = mContext.getSystemService(NfcManager.class);
- if (nfcManager == null) {
- Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
- return;
- }
- NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter();
- if (nfcAdapter == null) {
- Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
- return;
- }
- if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling);
- nfcAdapter.setReaderMode(enablePolling);
- } else {
- setNfcReaderModeUsingINfcAdapter(enablePolling);
- }
+ if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling);
+ nfcAdapter.setReaderMode(enablePolling);
}
private static int[] toArray(Collection<Integer> c) {
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index b394fb5..56a94ec0 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -56,6 +56,7 @@
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -67,7 +68,6 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -116,8 +116,6 @@
public class ClipboardService extends SystemService {
private static final String TAG = "ClipboardService";
- private static final boolean IS_EMULATOR =
- SystemProperties.getBoolean("ro.boot.qemu", false);
@VisibleForTesting
public static final long DEFAULT_CLIPBOARD_TIMEOUT_MILLIS = 3600000;
@@ -193,7 +191,7 @@
mAutofillInternal = LocalServices.getService(AutofillManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
- if (IS_EMULATOR) {
+ if (Build.IS_EMULATOR) {
mEmulatorClipboardMonitor = new EmulatorClipboardMonitor((clip) -> {
synchronized (mLock) {
Clipboard clipboard = getClipboardLocked(0, DEVICE_ID_DEFAULT);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index aef2248..c517058 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -56,7 +56,6 @@
import android.content.pm.UserInfo;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
-import android.net.DnsResolver;
import android.net.INetd;
import android.net.INetworkManagementEventObserver;
import android.net.Ikev2VpnProfile;
@@ -67,8 +66,6 @@
import android.net.IpSecTransform;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
@@ -109,7 +106,6 @@
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -120,7 +116,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemService;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -160,11 +155,8 @@
import libcore.io.IoUtils;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -190,8 +182,6 @@
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
@@ -451,10 +441,6 @@
// The user id of initiating VPN.
private final int mUserId;
- interface RetryScheduler {
- void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException;
- }
-
private static class CarrierConfigInfo {
public final String mccMnc;
public final int keepaliveDelaySec;
@@ -483,26 +469,6 @@
return Binder.getCallingUid() == Process.SYSTEM_UID;
}
- public void startService(final String serviceName) {
- SystemService.start(serviceName);
- }
-
- public void stopService(final String serviceName) {
- SystemService.stop(serviceName);
- }
-
- public boolean isServiceRunning(final String serviceName) {
- return SystemService.isRunning(serviceName);
- }
-
- public boolean isServiceStopped(final String serviceName) {
- return SystemService.isStopped(serviceName);
- }
-
- public File getStateFile() {
- return new File("/data/misc/vpn/state");
- }
-
public DeviceIdleInternal getDeviceIdleInternal() {
return LocalServices.getService(DeviceIdleInternal.class);
}
@@ -511,104 +477,6 @@
return VpnConfig.getIntentForStatusPanel(context);
}
- public void sendArgumentsToDaemon(
- final String daemon, final LocalSocket socket, final String[] arguments,
- final RetryScheduler retryScheduler) throws IOException, InterruptedException {
- final LocalSocketAddress address = new LocalSocketAddress(
- daemon, LocalSocketAddress.Namespace.RESERVED);
-
- // Wait for the socket to connect.
- while (true) {
- try {
- socket.connect(address);
- break;
- } catch (Exception e) {
- // ignore
- }
- retryScheduler.checkInterruptAndDelay(true /* sleepLonger */);
- }
- socket.setSoTimeout(500);
-
- final OutputStream out = socket.getOutputStream();
- for (String argument : arguments) {
- byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
- if (bytes.length >= 0xFFFF) {
- throw new IllegalArgumentException("Argument is too large");
- }
- out.write(bytes.length >> 8);
- out.write(bytes.length);
- out.write(bytes);
- retryScheduler.checkInterruptAndDelay(false /* sleepLonger */);
- }
- out.write(0xFF);
- out.write(0xFF);
-
- // Wait for End-of-File.
- final InputStream in = socket.getInputStream();
- while (true) {
- try {
- if (in.read() == -1) {
- break;
- }
- } catch (Exception e) {
- // ignore
- }
- retryScheduler.checkInterruptAndDelay(true /* sleepLonger */);
- }
- }
-
- @NonNull
- public InetAddress resolve(final String endpoint)
- throws ExecutionException, InterruptedException {
- try {
- return InetAddresses.parseNumericAddress(endpoint);
- } catch (IllegalArgumentException e) {
- // Endpoint is not numeric : fall through and resolve
- }
-
- final CancellationSignal cancellationSignal = new CancellationSignal();
- try {
- final DnsResolver resolver = DnsResolver.getInstance();
- final CompletableFuture<InetAddress> result = new CompletableFuture();
- final DnsResolver.Callback<List<InetAddress>> cb =
- new DnsResolver.Callback<List<InetAddress>>() {
- @Override
- public void onAnswer(@NonNull final List<InetAddress> answer,
- final int rcode) {
- if (answer.size() > 0) {
- result.complete(answer.get(0));
- } else {
- result.completeExceptionally(
- new UnknownHostException(endpoint));
- }
- }
-
- @Override
- public void onError(@Nullable final DnsResolver.DnsException error) {
- // Unfortunately UnknownHostException doesn't accept a cause, so
- // print a message here instead. Only show the summary, not the
- // full stack trace.
- Log.e(TAG, "Async dns resolver error : " + error);
- result.completeExceptionally(new UnknownHostException(endpoint));
- }
- };
- resolver.query(null /* network, null for default */, endpoint,
- DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb);
- return result.get();
- } catch (final ExecutionException e) {
- Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e);
- throw e;
- } catch (final InterruptedException e) {
- Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e);
- cancellationSignal.cancel();
- throw e;
- }
- }
-
- public boolean isInterfacePresent(final Vpn vpn, final String iface) {
- return vpn.jniCheck(iface) != 0;
- }
-
/**
* @see ParcelFileDescriptor#adoptFd(int)
*/
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f09fcea..2cca72e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1978,8 +1978,9 @@
|| sdrAnimateValue != currentSdrBrightness)) {
boolean skipAnimation = initialRampSkip || hasBrightnessBuckets
|| !isDisplayContentVisible || brightnessIsTemporary;
- if (!skipAnimation && BrightnessSynchronizer.floatEquals(
- sdrAnimateValue, currentSdrBrightness)) {
+ final boolean isHdrOnlyChange = BrightnessSynchronizer.floatEquals(
+ sdrAnimateValue, currentSdrBrightness);
+ if (mFlags.isFastHdrTransitionsEnabled() && !skipAnimation && isHdrOnlyChange) {
// SDR brightness is unchanged, so animate quickly as this is only impacting
// a likely minority amount of display content
// ie, the highlights of an HDR video or UltraHDR image
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 5310e43..810ac08 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1602,8 +1602,9 @@
|| sdrAnimateValue != currentSdrBrightness)) {
boolean skipAnimation = initialRampSkip || hasBrightnessBuckets
|| !isDisplayContentVisible || brightnessIsTemporary;
- if (!skipAnimation && BrightnessSynchronizer.floatEquals(
- sdrAnimateValue, currentSdrBrightness)) {
+ final boolean isHdrOnlyChange = BrightnessSynchronizer.floatEquals(
+ sdrAnimateValue, currentSdrBrightness);
+ if (mFlags.isFastHdrTransitionsEnabled() && !skipAnimation && isHdrOnlyChange) {
// SDR brightness is unchanged, so animate quickly as this is only impacting
// a likely minority amount of display content
// ie, the highlights of an HDR video or UltraHDR image
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index f579dbd..bd5e189 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -101,6 +101,10 @@
Flags.FLAG_AUTO_BRIGHTNESS_MODES,
Flags::autoBrightnessModes);
+ private final FlagState mFastHdrTransitions = new FlagState(
+ Flags.FLAG_FAST_HDR_TRANSITIONS,
+ Flags::fastHdrTransitions);
+
/** Returns whether connected display management is enabled or not. */
public boolean isConnectedDisplayManagementEnabled() {
return mConnectedDisplayManagementFlagState.isEnabled();
@@ -205,6 +209,10 @@
return mAutoBrightnessModesFlagState.isEnabled();
}
+ public boolean isFastHdrTransitionsEnabled() {
+ return mFastHdrTransitions.isEnabled();
+ }
+
/**
* dumps all flagstates
* @param pw printWriter
@@ -226,6 +234,7 @@
pw.println(" " + mVsyncProximityVote);
pw.println(" " + mBrightnessWearBedtimeModeClamperFlagState);
pw.println(" " + mAutoBrightnessModesFlagState);
+ pw.println(" " + mFastHdrTransitions);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 1b4d74c..7a723a3 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -144,3 +144,12 @@
bug: "293613040"
is_fixed_read_only: true
}
+
+flag {
+ name: "fast_hdr_transitions"
+ namespace: "display_manager"
+ description: "Feature flag for fast transitions into/out of HDR"
+ bug: "292124102"
+ is_fixed_read_only: true
+}
+
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index 6147c10..f3532e5 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -182,7 +182,7 @@
.setVendorId(mVendorId)
.setDisplayName(mDisplayName)
.build();
- localDevice().mService.getHdmiCecNetwork().addCecDevice(deviceInfo);
+ localDevice().mService.getHdmiCecNetwork().updateCecDevice(deviceInfo);
// Consume CEC messages we already got for this newly found device.
tv().processDelayedMessages(mDeviceLogicalAddress);
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 35c6120..d359280 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -467,8 +467,7 @@
}
public byte[] getUuid() throws RemoteException {
- //TODO(b/247124878): return the UUID defined in this file when the API is put in use
- throw new RemoteException("This API is not implemented yet.");
+ return UUID;
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 4bac872..17f2fcc 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -155,43 +155,45 @@
try (final PrintWriter pw = getOutPrintWriter();) {
pw.println("lockSettings service commands:");
pw.println("");
- pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>"
- + " argument.");
+ pw.println("NOTE: when a secure lock screen is set, most commands require the");
+ pw.println("--old <CREDENTIAL> option.");
pw.println("");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
- pw.println(" get-disabled [--old <CREDENTIAL>] [--user USER_ID]");
- pw.println(" Checks whether lock screen is disabled.");
+ pw.println(" get-disabled [--user USER_ID]");
+ pw.println(" Prints true if the lock screen is completely disabled, i.e. set to None.");
+ pw.println(" Otherwise prints false.");
pw.println("");
- pw.println(" set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>");
- pw.println(" When true, disables lock screen.");
+ pw.println(" set-disabled [--user USER_ID] <true|false>");
+ pw.println(" Sets whether the lock screen is disabled. If the lock screen is secure, this");
+ pw.println(" has no immediate effect. I.e. this can only change between Swipe and None.");
pw.println("");
pw.println(" set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>");
- pw.println(" Sets the lock screen as pattern, using the given PATTERN to unlock.");
+ pw.println(" Sets a secure lock screen that uses the given PATTERN. PATTERN is a series");
+ pw.println(" of digits 1-9 that identify the cells of the pattern.");
pw.println("");
pw.println(" set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>");
- pw.println(" Sets the lock screen as PIN, using the given PIN to unlock.");
+ pw.println(" Sets a secure lock screen that uses the given PIN.");
pw.println("");
pw.println(" set-password [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>");
- pw.println(" Sets the lock screen as password, using the given PASSWORD to unlock.");
+ pw.println(" Sets a secure lock screen that uses the given PASSWORD.");
pw.println("");
pw.println(" clear [--old <CREDENTIAL>] [--user USER_ID]");
- pw.println(" Clears the lock credentials.");
+ pw.println(" Clears the lock credential.");
pw.println("");
pw.println(" verify [--old <CREDENTIAL>] [--user USER_ID]");
- pw.println(" Verifies the lock credentials.");
+ pw.println(" Verifies the lock credential.");
pw.println("");
pw.println(" remove-cache [--user USER_ID]");
pw.println(" Removes cached unified challenge for the managed profile.");
pw.println("");
pw.println(" set-resume-on-reboot-provider-package <package_name>");
- pw.println(" Sets the package name for server based resume on reboot service "
- + "provider.");
+ pw.println(" Sets the package name for server based resume on reboot service provider.");
pw.println("");
pw.println(" require-strong-auth [--user USER_ID] <reason>");
- pw.println(" Requires the strong authentication. The current supported reasons: "
- + "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN.");
+ pw.println(" Requires strong authentication. The current supported reasons:");
+ pw.println(" STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN.");
pw.println("");
}
}
diff --git a/services/core/java/com/android/server/notification/ZenModeEventLogger.java b/services/core/java/com/android/server/notification/ZenModeEventLogger.java
index 1641d4a..87158cd 100644
--- a/services/core/java/com/android/server/notification/ZenModeEventLogger.java
+++ b/services/core/java/com/android/server/notification/ZenModeEventLogger.java
@@ -23,6 +23,7 @@
import static android.service.notification.NotificationServiceProto.RULE_TYPE_UNKNOWN;
import android.annotation.NonNull;
+import android.app.Flags;
import android.app.NotificationManager;
import android.content.pm.PackageManager;
import android.os.Process;
@@ -502,6 +503,13 @@
ZenModeConfig.getZenPolicySenders(mNewPolicy.allowMessagesFrom()));
proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM,
mNewPolicy.allowConversationsFrom());
+
+ if (Flags.modesApi()) {
+ proto.write(DNDPolicyProto.ALLOW_CHANNELS,
+ mNewPolicy.allowPriorityChannels()
+ ? ZenPolicy.CHANNEL_TYPE_PRIORITY
+ : ZenPolicy.CHANNEL_TYPE_NONE);
+ }
} else {
Log.wtf(TAG, "attempted to write zen mode log event with null policy");
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 89d8200..d0ded63 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1519,7 +1519,7 @@
final boolean muteEverything = zenSilence || (zenPriorityOnly
&& ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.SDK_USAGES.toArray()) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
diff --git a/services/core/java/com/android/server/pdb/TEST_MAPPING b/services/core/java/com/android/server/pdb/TEST_MAPPING
deleted file mode 100644
index e5f154a..0000000
--- a/services/core/java/com/android/server/pdb/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "postsubmit": [
- {
- "name": " PersistentDataBlockServiceTest"
- }
- ]
-}
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index af6a002..b23ccb8 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -397,6 +397,9 @@
@Nullable Certificate[] trustedInstallers,
Map<Integer, ApkChecksum> checksums,
@NonNull Injector injector) {
+ if (!file.exists()) {
+ return;
+ }
final String filePath = file.getAbsolutePath();
// Always available: FSI or IncFs.
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index ba2cf1d..1a65297 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -690,6 +690,9 @@
pkgSetting.setInstallReason(installReason, userId);
pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
+ // Clear any existing archive state.
+ pkgSetting.setArchiveTimeMillis(0, userId);
+ pkgSetting.setArchiveState(null, userId);
mPm.mSettings.writePackageRestrictionsLPr(userId);
mPm.mSettings.writeKernelMappingLPr(pkgSetting);
installed = true;
@@ -2263,6 +2266,9 @@
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId,
installerPackageName);
}
+ // Clear any existing archive state.
+ ps.setArchiveState(null, userId);
+ ps.setArchiveTimeMillis(0, userId);
} else if (allUsers != null) {
// The caller explicitly specified INSTALL_ALL_USERS flag.
// Thus, updating the settings to install the app for all users.
@@ -2285,6 +2291,9 @@
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId,
installerPackageName);
}
+ // Clear any existing archive state.
+ ps.setArchiveState(null, currentUserId);
+ ps.setArchiveTimeMillis(0, currentUserId);
} else {
ps.setInstalled(false, currentUserId);
}
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index fb311da..e3bab3f 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -24,6 +24,8 @@
import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
import static android.content.pm.ArchivedActivityInfo.bytesFromBitmap;
import static android.content.pm.ArchivedActivityInfo.drawableToBitmap;
+import static android.content.pm.PackageInstaller.EXTRA_UNARCHIVE_STATUS;
+import static android.content.pm.PackageInstaller.UNARCHIVAL_OK;
import static android.content.pm.PackageManager.DELETE_ARCHIVE;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT;
@@ -38,6 +40,7 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -51,6 +54,7 @@
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.DeleteFlags;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.VersionedPackage;
@@ -118,6 +122,15 @@
private static final String ACTION_UNARCHIVE_DIALOG =
"com.android.intent.action.UNARCHIVE_DIALOG";
+ private static final String ACTION_UNARCHIVE_ERROR_DIALOG =
+ "com.android.intent.action.UNARCHIVE_ERROR_DIALOG";
+
+ private static final String EXTRA_REQUIRED_BYTES =
+ "com.android.content.pm.extra.UNARCHIVE_EXTRA_REQUIRED_BYTES";
+ private static final String EXTRA_INSTALLER_PACKAGE_NAME =
+ "com.android.content.pm.extra.UNARCHIVE_INSTALLER_PACKAGE_NAME";
+ private static final String EXTRA_INSTALLER_TITLE =
+ "com.android.content.pm.extra.UNARCHIVE_INSTALLER_TITLE";
private final Context mContext;
private final PackageManagerService mPm;
@@ -142,7 +155,8 @@
@NonNull String packageName,
@NonNull String callerPackageName,
@NonNull IntentSender intentSender,
- @NonNull UserHandle userHandle) {
+ @NonNull UserHandle userHandle,
+ @DeleteFlags int flags) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(callerPackageName);
Objects.requireNonNull(intentSender);
@@ -183,7 +197,7 @@
new VersionedPackage(packageName,
PackageManager.VERSION_CODE_HIGHEST),
callerPackageName,
- DELETE_ARCHIVE | DELETE_KEEP_DATA,
+ DELETE_ARCHIVE | DELETE_KEEP_DATA | flags,
intentSender,
userId,
binderUid);
@@ -305,11 +319,14 @@
/** Creates archived state for the package and user. */
private CompletableFuture<ArchiveState> createArchiveState(String packageName, int userId)
throws PackageManager.NameNotFoundException {
- PackageStateInternal ps = getPackageState(packageName, mPm.snapshotComputer(),
+ Computer snapshot = mPm.snapshotComputer();
+ PackageStateInternal ps = getPackageState(packageName, snapshot,
Binder.getCallingUid(), userId);
verifyNotSystemApp(ps.getFlags());
String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
verifyInstaller(responsibleInstallerPackage, userId);
+ ApplicationInfo installerInfo = snapshot.getApplicationInfo(
+ responsibleInstallerPackage, /* flags= */ 0, userId);
verifyOptOutStatus(packageName,
UserHandle.getUid(userId, UserHandle.getUid(userId, ps.getAppId())));
@@ -320,7 +337,7 @@
try {
archiveState.complete(
createArchiveStateInternal(packageName, userId, mainActivities,
- responsibleInstallerPackage));
+ installerInfo.loadLabel(mContext.getPackageManager()).toString()));
} catch (IOException e) {
archiveState.completeExceptionally(e);
}
@@ -328,8 +345,17 @@
return archiveState;
}
- static ArchiveState createArchiveState(@NonNull ArchivedPackageParcel archivedPackage,
+ @Nullable
+ ArchiveState createArchiveState(@NonNull ArchivedPackageParcel archivedPackage,
int userId, String installerPackage) {
+ ApplicationInfo installerInfo = mPm.snapshotComputer().getApplicationInfo(
+ installerPackage, /* flags= */ 0, userId);
+ if (installerInfo == null) {
+ // Should never happen because we just fetched the installerInfo.
+ Slog.e(TAG, "Couldnt find installer " + installerPackage);
+ return null;
+ }
+
try {
var packageName = archivedPackage.packageName;
var mainActivities = archivedPackage.archivedActivities;
@@ -346,7 +372,8 @@
archiveActivityInfos.add(activityInfo);
}
- return new ArchiveState(archiveActivityInfos, installerPackage);
+ return new ArchiveState(archiveActivityInfos,
+ installerInfo.loadLabel(mContext.getPackageManager()).toString());
} catch (IOException e) {
Slog.e(TAG, "Failed to create archive state", e);
return null;
@@ -354,7 +381,7 @@
}
ArchiveState createArchiveStateInternal(String packageName, int userId,
- List<LauncherActivityInfo> mainActivities, String installerPackage)
+ List<LauncherActivityInfo> mainActivities, String installerTitle)
throws IOException {
final int iconSize = mContext.getSystemService(
ActivityManager.class).getLauncherLargeIconSize();
@@ -372,7 +399,7 @@
archiveActivityInfos.add(activityInfo);
}
- return new ArchiveState(archiveActivityInfos, installerPackage);
+ return new ArchiveState(archiveActivityInfos, installerTitle);
}
// TODO(b/298452477) Handle monochrome icons.
@@ -412,14 +439,14 @@
return iconFile.toPath();
}
- private void verifyInstaller(String installerPackage, int userId)
+ private void verifyInstaller(String installerPackageName, int userId)
throws PackageManager.NameNotFoundException {
- if (TextUtils.isEmpty(installerPackage)) {
+ if (TextUtils.isEmpty(installerPackageName)) {
throw new PackageManager.NameNotFoundException("No installer found");
}
// Allow shell for easier development.
if ((Binder.getCallingUid() != Process.SHELL_UID)
- && !verifySupportsUnarchival(installerPackage, userId)) {
+ && !verifySupportsUnarchival(installerPackageName, userId)) {
throw new PackageManager.NameNotFoundException("Installer does not support unarchival");
}
}
@@ -588,7 +615,7 @@
final Intent broadcastIntent = new Intent();
broadcastIntent.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName);
- broadcastIntent.putExtra(PackageInstaller.EXTRA_UNARCHIVE_STATUS,
+ broadcastIntent.putExtra(EXTRA_UNARCHIVE_STATUS,
PackageInstaller.STATUS_PENDING_USER_ACTION);
broadcastIntent.putExtra(Intent.EXTRA_INTENT, dialogIntent);
sendIntent(statusReceiver, packageName, /* message= */ "", broadcastIntent);
@@ -782,6 +809,83 @@
: ps.getInstallSource().mUpdateOwnerPackageName;
}
+ void notifyUnarchivalListener(int status, String installerPackageName, String appPackageName,
+ long requiredStorageBytes, @Nullable PendingIntent userActionIntent,
+ IntentSender unarchiveIntentSender, int userId) {
+ final Intent broadcastIntent = new Intent();
+ broadcastIntent.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, appPackageName);
+ broadcastIntent.putExtra(EXTRA_UNARCHIVE_STATUS, status);
+
+ if (status != UNARCHIVAL_OK) {
+ final Intent dialogIntent = createErrorDialogIntent(status, installerPackageName,
+ appPackageName,
+ requiredStorageBytes, userActionIntent, userId);
+ if (dialogIntent == null) {
+ // Error already logged.
+ return;
+ }
+ broadcastIntent.putExtra(Intent.EXTRA_INTENT, dialogIntent);
+ }
+
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_DENIED);
+ try {
+ unarchiveIntentSender.sendIntent(mContext, 0, broadcastIntent, /* onFinished= */ null,
+ /* handler= */ null, /* requiredPermission= */ null,
+ options.toBundle());
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, TextUtils.formatSimple("Failed to send unarchive intent"), e);
+ }
+ }
+
+ @Nullable
+ private Intent createErrorDialogIntent(int status, String installerPackageName,
+ String appPackageName,
+ long requiredStorageBytes, PendingIntent userActionIntent, int userId) {
+ final Intent dialogIntent = new Intent(ACTION_UNARCHIVE_ERROR_DIALOG);
+ dialogIntent.putExtra(EXTRA_UNARCHIVE_STATUS, status);
+ if (requiredStorageBytes > 0) {
+ dialogIntent.putExtra(EXTRA_REQUIRED_BYTES, requiredStorageBytes);
+ }
+ // Note that the userActionIntent is provided by the installer and is used only by the
+ // system package installer as a follow-up action after the user confirms the dialog.
+ if (userActionIntent != null) {
+ dialogIntent.putExtra(Intent.EXTRA_INTENT, userActionIntent);
+ }
+ dialogIntent.putExtra(EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
+ // We fetch this label from the archive state because the installer might not be installed
+ // anymore in an edge case.
+ String installerTitle = getInstallerTitle(appPackageName, userId);
+ if (installerTitle == null) {
+ // Error already logged.
+ return null;
+ }
+ dialogIntent.putExtra(EXTRA_INSTALLER_TITLE, installerTitle);
+ return dialogIntent;
+ }
+
+ private String getInstallerTitle(String appPackageName, int userId) {
+ PackageStateInternal packageState;
+ try {
+ packageState = getPackageState(appPackageName,
+ mPm.snapshotComputer(),
+ Process.SYSTEM_UID, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, TextUtils.formatSimple(
+ "notifyUnarchivalListener: Couldn't fetch package state for %s.",
+ appPackageName), e);
+ return null;
+ }
+ ArchiveState archiveState = packageState.getUserStateOrDefault(userId).getArchiveState();
+ if (archiveState == null) {
+ Slog.e(TAG, TextUtils.formatSimple("notifyUnarchivalListener: App not archived %s.",
+ appPackageName));
+ return null;
+ }
+ return archiveState.getInstallerTitle();
+ }
+
@NonNull
private static PackageStateInternal getPackageState(String packageName,
Computer snapshot, int callingUid, int userId)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 882e05d..7d6dd62 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -16,9 +16,10 @@
package com.android.server.pm;
-import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
import static android.app.admin.DevicePolicyResources.Strings.Core.PACKAGE_DELETED_BY_DO;
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
+import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED;
+import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED;
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY;
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED;
@@ -66,6 +67,7 @@
import android.content.pm.PackageInstaller.UnarchivalStatus;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.DeleteFlags;
import android.content.pm.ParceledListSlice;
import android.content.pm.VersionedPackage;
import android.content.pm.parsing.FrameworkParsingPackageUtils;
@@ -1389,11 +1391,14 @@
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, versionedPackage.getPackageName(),
canSilentlyInstallPackage, userId);
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES)
+ final boolean shouldShowConfirmationDialog =
+ (flags & PackageManager.DELETE_SHOW_DIALOG) != 0;
+ if (!shouldShowConfirmationDialog
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES)
== PackageManager.PERMISSION_GRANTED) {
// Sweet, call straight through!
mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
- } else if (canSilentlyInstallPackage) {
+ } else if (!shouldShowConfirmationDialog && canSilentlyInstallPackage) {
// Allow the device owner and affiliated profile owner to silently delete packages
// Need to clear the calling identity to get DELETE_PACKAGES permission
final long ident = Binder.clearCallingIdentity();
@@ -1418,6 +1423,11 @@
intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null));
intent.putExtra(PackageInstaller.EXTRA_CALLBACK,
new PackageManager.UninstallCompleteCallback(adapter.getBinder().asBinder()));
+ if ((flags & PackageManager.DELETE_ARCHIVE) != 0) {
+ // Delete flags are passed to the uninstaller activity so it can be preserved
+ // in the follow-up uninstall operation after the user confirmation
+ intent.putExtra(PackageInstaller.EXTRA_DELETE_FLAGS, flags);
+ }
adapter.onUserActionRequired(intent);
}
}
@@ -1630,9 +1640,10 @@
@NonNull String packageName,
@NonNull String callerPackageName,
@NonNull IntentSender intentSender,
- @NonNull UserHandle userHandle) {
+ @NonNull UserHandle userHandle,
+ @DeleteFlags int flags) {
mPackageArchiver.requestArchive(packageName, callerPackageName, intentSender,
- userHandle);
+ userHandle, flags);
}
@Override
@@ -1703,7 +1714,6 @@
});
}
- // TODO(b/307299702) Implement error dialog and propagate userActionIntent.
@Override
public void reportUnarchivalStatus(
int unarchiveId,
@@ -1746,8 +1756,10 @@
// Execute expensive calls outside the sync block.
mPm.mHandler.post(
- () -> notifyUnarchivalListener(status, session.params.appPackageName,
- unarchiveIntentSender));
+ () -> mPackageArchiver.notifyUnarchivalListener(status,
+ session.getInstallerPackageName(),
+ session.params.appPackageName, requiredStorageBytes, userActionIntent,
+ unarchiveIntentSender, userId));
session.params.unarchiveIntentSender = null;
if (status != UNARCHIVAL_OK) {
Binder.withCleanCallingIdentity(session::abandon);
@@ -1776,29 +1788,13 @@
UNARCHIVAL_ERROR_USER_ACTION_NEEDED,
UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE,
UNARCHIVAL_ERROR_NO_CONNECTIVITY,
+ UNARCHIVAL_ERROR_INSTALLER_DISABLED,
+ UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED,
UNARCHIVAL_GENERIC_ERROR).contains(status)) {
throw new IllegalStateException("Invalid status code passed " + status);
}
}
- private void notifyUnarchivalListener(int status, String packageName,
- IntentSender unarchiveIntentSender) {
- final Intent fillIn = new Intent();
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName);
- fillIn.putExtra(PackageInstaller.EXTRA_UNARCHIVE_STATUS, status);
- // TODO(b/307299702) Attach failure dialog with EXTRA_INTENT and requiredStorageBytes here.
- final BroadcastOptions options = BroadcastOptions.makeBasic();
- options.setPendingIntentBackgroundActivityStartMode(
- MODE_BACKGROUND_ACTIVITY_START_DENIED);
- try {
- unarchiveIntentSender.sendIntent(mContext, 0, fillIn, /* onFinished= */ null,
- /* handler= */ null, /* requiredPermission= */ null,
- options.toBundle());
- } catch (SendIntentException e) {
- Slog.e(TAG, TextUtils.formatSimple("Failed to send unarchive intent"), e);
- }
- }
-
private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
int installerUid) {
int count = 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index adb6906..5daada9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1534,8 +1534,8 @@
return;
}
for (int userId : userIds) {
- var archiveState = PackageArchiver.createArchiveState(archivePackage, userId,
- responsibleInstallerPackage);
+ var archiveState = mInstallerService.mPackageArchiver.createArchiveState(
+ archivePackage, userId, responsibleInstallerPackage);
if (archiveState == null) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fc66203..215e952 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -4639,7 +4639,7 @@
try {
mInterface.getPackageInstaller().requestArchive(packageName,
/* callerPackageName= */ "", receiver.getIntentSender(),
- new UserHandle(translatedUserId));
+ new UserHandle(translatedUserId), 0);
} catch (Exception e) {
pw.println("Failure [" + e.getMessage() + "]");
return 1;
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 293b873..26dc576 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -770,6 +770,11 @@
onChanged();
}
+ void setArchiveState(ArchiveState archiveState, int userId) {
+ modifyUserState(userId).setArchiveState(archiveState);
+ onChanged();
+ }
+
void setArchiveTimeMillis(long value, int userId) {
modifyUserState(userId).setArchiveTimeMillis(value);
onChanged();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
index dbf4047..28818f7 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
@@ -93,7 +93,7 @@
Map<Integer, Map<String, LegacyPermissionState>> appIdPermissionStates = new ArrayMap<>();
RuntimePermissionsState legacyState =
- mPackageManagerInternal.getLegacyPermissionsState(userId);
+ (RuntimePermissionsState) mPackageManagerInternal.getLegacyPermissionsState(userId);
PackageManagerLocal packageManagerLocal =
LocalManagerRegistry.getManager(PackageManagerLocal.class);
diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING
index 05a0e85..e64704a 100644
--- a/services/core/java/com/android/server/power/TEST_MAPPING
+++ b/services/core/java/com/android/server/power/TEST_MAPPING
@@ -45,6 +45,17 @@
{"include-filter": "com.android.server.power"},
{"exclude-annotation": "org.junit.Ignore"}
]
+ },
+ {
+ "name": "CtsStatsdAtomHostTestCases",
+ "options": [
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {"exclude-annotation": "org.junit.Ignore"},
+ {"include-filter": "android.cts.statsdatom.powermanager"}
+ ],
+ "file_patterns": [
+ "(/|^)ThermalManagerService.java"
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index d17207b..99653ae 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -16,8 +16,17 @@
package com.android.server.power;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__NO_TEMPERATURE_THRESHOLD;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__FEATURE_NOT_SUPPORTED;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__HAL_NOT_READY;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_STATUS_CALLED__API_STATUS__HAL_NOT_READY;
+import static com.android.internal.util.FrameworkStatsLog.THERMAL_STATUS_CALLED__API_STATUS__SUCCESS;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.StatsManager;
import android.content.Context;
import android.hardware.thermal.IThermal;
import android.hardware.thermal.IThermalChangedCallback;
@@ -48,11 +57,13 @@
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;
+import android.util.StatsEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.SystemService;
@@ -122,6 +133,8 @@
@VisibleForTesting
final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher();
+ private final Context mContext;
+
public ThermalManagerService(Context context) {
this(context, null);
}
@@ -129,6 +142,7 @@
@VisibleForTesting
ThermalManagerService(Context context, @Nullable ThermalHalWrapper halWrapper) {
super(context);
+ mContext = context;
mHalWrapper = halWrapper;
if (halWrapper != null) {
halWrapper.setCallback(this::onTemperatureChangedCallback);
@@ -146,6 +160,9 @@
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
onActivityManagerReady();
}
+ if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ registerStatsCallbacks();
+ }
}
private void onActivityManagerReady() {
@@ -326,6 +343,31 @@
}
}
+ private void registerStatsCallbacks() {
+ final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
+ if (statsManager != null) {
+ statsManager.setPullAtomCallback(
+ FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ this::onPullAtom);
+ }
+ }
+
+ private int onPullAtom(int atomTag, @NonNull List<StatsEvent> data) {
+ if (atomTag == FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS) {
+ final float[] thresholds;
+ synchronized (mTemperatureWatcher.mSamples) {
+ thresholds = Arrays.copyOf(mTemperatureWatcher.mHeadroomThresholds,
+ mTemperatureWatcher.mHeadroomThresholds.length);
+ }
+ data.add(
+ FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS,
+ thresholds));
+ }
+ return android.app.StatsManager.PULL_SUCCESS;
+ }
+
@VisibleForTesting
final IThermalService.Stub mService = new IThermalService.Stub() {
@Override
@@ -449,6 +491,12 @@
synchronized (mLock) {
final long token = Binder.clearCallingIdentity();
try {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_STATUS_CALLED,
+ Binder.getCallingUid(),
+ mHalReady.get()
+ ? THERMAL_STATUS_CALLED__API_STATUS__SUCCESS
+ : THERMAL_STATUS_CALLED__API_STATUS__HAL_NOT_READY,
+ thermalSeverityToStatsdStatus(mStatus));
return mStatus;
} finally {
Binder.restoreCallingIdentity(token);
@@ -493,6 +541,9 @@
@Override
public float getThermalHeadroom(int forecastSeconds) {
if (!mHalReady.get()) {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED, getCallingUid(),
+ FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__HAL_NOT_READY,
+ Float.NaN);
return Float.NaN;
}
@@ -500,6 +551,9 @@
if (DEBUG) {
Slog.d(TAG, "Invalid forecastSeconds: " + forecastSeconds);
}
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED, getCallingUid(),
+ FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__INVALID_ARGUMENT,
+ Float.NaN);
return Float.NaN;
}
@@ -509,12 +563,21 @@
@Override
public float[] getThermalHeadroomThresholds() {
if (!mHalReady.get()) {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED,
+ Binder.getCallingUid(),
+ THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__HAL_NOT_READY);
throw new IllegalStateException("Thermal HAL connection is not initialized");
}
if (!Flags.allowThermalHeadroomThresholds()) {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED,
+ Binder.getCallingUid(),
+ THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__FEATURE_NOT_SUPPORTED);
throw new UnsupportedOperationException("Thermal headroom thresholds not enabled");
}
synchronized (mTemperatureWatcher.mSamples) {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_THRESHOLDS_CALLED,
+ Binder.getCallingUid(),
+ THERMAL_HEADROOM_THRESHOLDS_CALLED__API_STATUS__SUCCESS);
return Arrays.copyOf(mTemperatureWatcher.mHeadroomThresholds,
mTemperatureWatcher.mHeadroomThresholds.length);
}
@@ -544,6 +607,27 @@
};
+ private static int thermalSeverityToStatsdStatus(int severity) {
+ switch (severity) {
+ case PowerManager.THERMAL_STATUS_NONE:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__NONE;
+ case PowerManager.THERMAL_STATUS_LIGHT:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__LIGHT;
+ case PowerManager.THERMAL_STATUS_MODERATE:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__MODERATE;
+ case PowerManager.THERMAL_STATUS_SEVERE:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__SEVERE;
+ case PowerManager.THERMAL_STATUS_CRITICAL:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__CRITICAL;
+ case PowerManager.THERMAL_STATUS_EMERGENCY:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__EMERGENCY;
+ case PowerManager.THERMAL_STATUS_SHUTDOWN:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__SHUTDOWN;
+ default:
+ return FrameworkStatsLog.THERMAL_STATUS_CALLED__STATUS__NONE;
+ }
+ }
+
private static void dumpItemsLocked(PrintWriter pw, String prefix,
Collection<?> items) {
for (Iterator iterator = items.iterator(); iterator.hasNext();) {
@@ -1492,13 +1576,15 @@
threshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE];
if (!Float.isNaN(severeThreshold)) {
mSevereThresholds.put(threshold.name, severeThreshold);
- for (int severity = ThrottlingSeverity.LIGHT;
- severity <= ThrottlingSeverity.SHUTDOWN; severity++) {
- if (Flags.allowThermalHeadroomThresholds()
- && threshold.hotThrottlingThresholds.length > severity) {
- updateHeadroomThreshold(severity,
- threshold.hotThrottlingThresholds[severity],
- severeThreshold);
+ if (Flags.allowThermalHeadroomThresholds()) {
+ for (int severity = ThrottlingSeverity.LIGHT;
+ severity <= ThrottlingSeverity.SHUTDOWN; severity++) {
+ if (severity != ThrottlingSeverity.SEVERE
+ && threshold.hotThrottlingThresholds.length > severity) {
+ updateHeadroomThreshold(severity,
+ threshold.hotThrottlingThresholds[severity],
+ severeThreshold);
+ }
}
}
}
@@ -1506,11 +1592,15 @@
}
}
- // For a older device with multiple SKIN sensors, we will set a severity's headroom
+ // For an older device with multiple SKIN sensors, we will set a severity's headroom
// threshold based on the minimum value of all as a workaround.
void updateHeadroomThreshold(int severity, float threshold, float severeThreshold) {
if (!Float.isNaN(threshold)) {
synchronized (mSamples) {
+ if (severity == ThrottlingSeverity.SEVERE) {
+ mHeadroomThresholds[severity] = 1.0f;
+ return;
+ }
float headroom = normalizeTemperature(threshold, severeThreshold);
if (Float.isNaN(mHeadroomThresholds[severity])) {
mHeadroomThresholds[severity] = headroom;
@@ -1620,6 +1710,10 @@
// to sample, return early
if (mSamples.isEmpty()) {
Slog.e(TAG, "No temperature samples found");
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED,
+ Binder.getCallingUid(),
+ FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__NO_TEMPERATURE,
+ Float.NaN);
return Float.NaN;
}
@@ -1627,16 +1721,22 @@
// so return early
if (mSevereThresholds.isEmpty()) {
Slog.e(TAG, "No temperature thresholds found");
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED,
+ Binder.getCallingUid(),
+ THERMAL_HEADROOM_CALLED__API_STATUS__NO_TEMPERATURE_THRESHOLD,
+ Float.NaN);
return Float.NaN;
}
float maxNormalized = Float.NaN;
+ int noThresholdSampleCount = 0;
for (Map.Entry<String, ArrayList<Sample>> entry : mSamples.entrySet()) {
String name = entry.getKey();
ArrayList<Sample> samples = entry.getValue();
Float threshold = mSevereThresholds.get(name);
if (threshold == null) {
+ noThresholdSampleCount++;
Slog.e(TAG, "No threshold found for " + name);
continue;
}
@@ -1659,7 +1759,17 @@
maxNormalized = normalized;
}
}
-
+ if (noThresholdSampleCount == mSamples.size()) {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED,
+ Binder.getCallingUid(),
+ THERMAL_HEADROOM_CALLED__API_STATUS__NO_TEMPERATURE_THRESHOLD,
+ Float.NaN);
+ } else {
+ FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_HEADROOM_CALLED,
+ Binder.getCallingUid(),
+ FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__SUCCESS,
+ maxNormalized);
+ }
return maxNormalized;
}
}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index c17d6ab..7c833cb 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -32,6 +32,8 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.WorkDuration;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseIntArray;
@@ -196,6 +198,9 @@
private static native void nativeSetMode(long halPtr, int mode, boolean enabled);
+ private static native void nativeReportActualWorkDuration(long halPtr,
+ WorkDuration[] workDurations);
+
/** Wrapper for HintManager.nativeInit */
public void halInit() {
nativeInit();
@@ -253,6 +258,10 @@
nativeSetMode(halPtr, mode, enabled);
}
+ /** Wrapper for HintManager.nativeReportActualWorkDuration */
+ public void halReportActualWorkDuration(long halPtr, WorkDuration[] workDurations) {
+ nativeReportActualWorkDuration(halPtr, workDurations);
+ }
}
@VisibleForTesting
@@ -629,6 +638,56 @@
}
}
+ @Override
+ public void reportActualWorkDuration2(WorkDuration[] workDurations) {
+ synchronized (this) {
+ if (mHalSessionPtr == 0 || !mUpdateAllowed) {
+ return;
+ }
+ Preconditions.checkArgument(workDurations.length != 0, "the count"
+ + " of work durations shouldn't be 0.");
+ for (WorkDuration workDuration : workDurations) {
+ validateWorkDuration(workDuration);
+ }
+ mNativeWrapper.halReportActualWorkDuration(mHalSessionPtr, workDurations);
+ }
+ }
+
+ void validateWorkDuration(WorkDuration workDuration) {
+ if (DEBUG) {
+ Slogf.d(TAG, "WorkDuration(" + workDuration.getTimestampNanos() + ", "
+ + workDuration.getWorkPeriodStartTimestampNanos() + ", "
+ + workDuration.getActualTotalDurationNanos() + ", "
+ + workDuration.getActualCpuDurationNanos() + ", "
+ + workDuration.getActualGpuDurationNanos() + ")");
+ }
+
+ // Allow work period start timestamp to be zero in system server side because
+ // legacy API call will use zero value. It can not be estimated with the timestamp
+ // the sample is received because the samples could stack up.
+ if (workDuration.getWorkPeriodStartTimestampNanos() < 0) {
+ throw new IllegalArgumentException(
+ TextUtils.formatSimple(
+ "Work period start timestamp (%d) should be greater than 0",
+ workDuration.getWorkPeriodStartTimestampNanos()));
+ }
+ if (workDuration.getActualTotalDurationNanos() <= 0) {
+ throw new IllegalArgumentException(
+ TextUtils.formatSimple("Actual total duration (%d) should be greater than 0",
+ workDuration.getActualTotalDurationNanos()));
+ }
+ if (workDuration.getActualCpuDurationNanos() <= 0) {
+ throw new IllegalArgumentException(
+ TextUtils.formatSimple("Actual CPU duration (%d) should be greater than 0",
+ workDuration.getActualCpuDurationNanos()));
+ }
+ if (workDuration.getActualGpuDurationNanos() < 0) {
+ throw new IllegalArgumentException(
+ TextUtils.formatSimple("Actual GPU duration (%d) should be non negative",
+ workDuration.getActualGpuDurationNanos()));
+ }
+ }
+
private void onProcStateChanged(boolean updateAllowed) {
updateHintAllowed(updateAllowed);
}
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 b8d26d9..698f6ea 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -49,6 +49,7 @@
import android.os.Binder;
import android.os.BluetoothBatteryStats;
import android.os.Build;
+import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBatteryPropertiesRegistrar;
import android.os.Looper;
@@ -137,7 +138,6 @@
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.net.module.util.NetworkCapabilitiesUtils;
-import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import libcore.util.EmptyArray;
@@ -10543,7 +10543,7 @@
final int batteryConsumerProcessState =
mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
- if (mBsi.mSystemReady && Flags.streamlinedBatteryStats()) {
+ if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled) {
mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
batteryConsumerProcessState);
}
@@ -11712,6 +11712,10 @@
// Store the empty state to disk to ensure consistency
writeSyncLocked();
+ if (mPowerStatsCollectorEnabled) {
+ schedulePowerStatsSampleCollection();
+ }
+
// Flush external data, gathering snapshots, but don't process it since it is pre-reset data
mIgnoreNextExternalStats = true;
mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
@@ -15762,6 +15766,16 @@
}
/**
+ * Schedules an immediate collection of PowerStats samples and awaits the result.
+ */
+ public void collectPowerStatsSamples() {
+ schedulePowerStatsSampleCollection();
+ ConditionVariable done = new ConditionVariable();
+ mHandler.post(done::open);
+ done.block();
+ }
+
+ /**
* Grabs one sample of PowerStats and prints it.
*/
public void dumpStatsSample(PrintWriter pw) {
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 391dd77..096c5e6 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -126,6 +126,10 @@
*/
public List<BatteryUsageStats> getBatteryUsageStats(BatteryStatsImpl stats,
List<BatteryUsageStatsQuery> queries) {
+ if (mPowerStatsExporterEnabled) {
+ stats.collectPowerStatsSamples();
+ }
+
ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
synchronized (stats) {
stats.prepareForDumpLocked();
@@ -168,15 +172,16 @@
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);
final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
- final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
- stats.getCustomEnergyConsumerNames(), includePowerModels,
- includeProcessStateData, minConsumedPowerThreshold);
- // TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration
- // of batteryUsageStats sessions to wall-clock adjustments
- batteryUsageStatsBuilder.setStatsStartTimestamp(stats.getStartClockTime());
- batteryUsageStatsBuilder.setStatsEndTimestamp(currentTimeMs);
-
+ final BatteryUsageStats.Builder batteryUsageStatsBuilder;
synchronized (stats) {
+ batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
+ stats.getCustomEnergyConsumerNames(), includePowerModels,
+ includeProcessStateData, minConsumedPowerThreshold);
+
+ // TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration
+ // of batteryUsageStats sessions to wall-clock adjustments
+ batteryUsageStatsBuilder.setStatsStartTimestamp(stats.getStartClockTime());
+ batteryUsageStatsBuilder.setStatsEndTimestamp(currentTimeMs);
SparseArray<? extends BatteryStats.Uid> uidStats = stats.getUidStats();
for (int i = uidStats.size() - 1; i >= 0; i--) {
final BatteryStats.Uid uid = uidStats.valueAt(i);
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
index 70c24d5..1f6f113 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
@@ -60,6 +60,7 @@
*/
public void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder,
long monotonicStartTime, long monotonicEndTime) {
+ boolean hasStoredSpans = false;
long maxEndTime = monotonicStartTime;
List<PowerStatsSpan.Metadata> spans = mPowerStatsStore.getTableOfContents();
for (int i = spans.size() - 1; i >= 0; i--) {
@@ -99,13 +100,14 @@
}
List<PowerStatsSpan.Section> sections = span.getSections();
for (int k = 0; k < sections.size(); k++) {
+ hasStoredSpans = true;
PowerStatsSpan.Section section = sections.get(k);
populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder,
((AggregatedPowerStatsSection) section).getAggregatedPowerStats());
}
}
- if (maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) {
+ if (!hasStoredSpans || maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) {
mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime,
stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats));
}
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 7123bcb..7bcdc71 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsStore.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
@@ -171,7 +171,7 @@
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
return PowerStatsSpan.read(inputStream, parser, mSectionReader, sectionTypes);
} catch (IOException | XmlPullParserException e) {
- Slog.wtf(TAG, "Cannot read PowerStatsSpan file: " + file);
+ Slog.wtf(TAG, "Cannot read PowerStatsSpan file: " + file, e);
}
} finally {
unlockStoreDirectory();
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index 8b57f87..8e9c889 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -38,6 +38,7 @@
import android.speech.IRecognitionSupportCallback;
import android.speech.RecognitionService;
import android.speech.SpeechRecognizer;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -253,6 +254,7 @@
@GuardedBy("mLock")
private void incrementSessionCountForUidLocked(int uid) {
mSessionCountByUid.put(uid, mSessionCountByUid.get(uid, 0) + 1);
+ Log.i(TAG, "Client " + uid + " has opened " + mSessionCountByUid.get(uid, 0) + " sessions");
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 940feb5..e876241 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -4871,7 +4871,7 @@
}
private int pullCachedAppsHighWatermark(int atomTag, List<StatsEvent> pulledData) {
- pulledData.add(LocalServices.getService(ActivityManagerInternal.class)
+ pulledData.add((StatsEvent) LocalServices.getService(ActivityManagerInternal.class)
.getCachedAppsHighWatermarkStats(atomTag, true));
return StatsManager.PULL_SUCCESS;
}
diff --git a/services/core/java/com/android/server/timezonedetector/TEST_MAPPING b/services/core/java/com/android/server/timezonedetector/TEST_MAPPING
index 358618a..004d7996 100644
--- a/services/core/java/com/android/server/timezonedetector/TEST_MAPPING
+++ b/services/core/java/com/android/server/timezonedetector/TEST_MAPPING
@@ -10,10 +10,7 @@
},
{
"name": "FrameworksTimeServicesTests"
- }
- ],
- // TODO(b/182461754): Change to "presubmit" when go/test-mapping-slo-guide allows.
- "postsubmit": [
+ },
{
"name": "CtsLocationTimeZoneManagerHostTest"
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2bf7075..d172d3f 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -1598,8 +1598,22 @@
fout.printf(" User \"%s\" (id=%d, flags=%#x)",
user.name, user.id, user.flags);
if (!user.supportsSwitchToByUser()) {
- fout.println("(managed profile)");
- fout.println(" disabled because switching to this user is not possible.");
+ final boolean locked;
+ if (user.isProfile()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id)) {
+ fout.print(" (profile with separate challenge)");
+ locked = isDeviceLockedInner(user.id);
+ } else {
+ fout.print(" (profile with unified challenge)");
+ locked = isDeviceLockedInner(resolveProfileParent(user.id));
+ }
+ } else {
+ fout.println(" (user that cannot be switched to)");
+ locked = isDeviceLockedInner(user.id);
+ }
+ fout.println(": deviceLocked=" + dumpBool(locked));
+ fout.println(
+ " Trust agents disabled because switching to this user is not possible.");
return;
}
if (isCurrent) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6e9219a..0d06f5b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3390,7 +3390,8 @@
if (currentFocusedApp != null && currentFocusedApp.task == task
&& topFocusedDisplayId == mDisplayContent.getDisplayId()) {
final Task topFocusableTask = mDisplayContent.getTask(
- (t) -> t.isLeafTask() && t.isFocusable(), true /* traverseTopToBottom */);
+ (t) -> t.isLeafTask() && t.isFocusable() && !t.inPinnedWindowingMode(),
+ true /* traverseTopToBottom */);
if (task == topFocusableTask) {
if (currentFocusedApp == this) {
ProtoLog.d(WM_DEBUG_FOCUS, "moveFocusableActivityToTop: already on top "
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 6f5c676..b8b102f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5280,6 +5280,9 @@
/** Applies latest configuration and/or visibility updates if needed. */
boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
+ if (starting == null && mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
+ return true;
+ }
boolean kept = true;
final Task mainRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
// mainRootTask is null during startup.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index e5604ec..4243948 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2857,12 +2857,18 @@
return false;
}
- /** Applies the new configuration for the changed displays. */
- void applyDisplayChangeIfNeeded() {
+ /**
+ * Applies the new configuration for the changed displays. Returns the activities that should
+ * check whether to deliver the new configuration to clients.
+ */
+ @Nullable
+ ArrayList<ActivityRecord> applyDisplayChangeIfNeeded() {
+ ArrayList<ActivityRecord> activitiesMayChange = null;
for (int i = mParticipants.size() - 1; i >= 0; --i) {
final WindowContainer<?> wc = mParticipants.valueAt(i);
final DisplayContent dc = wc.asDisplayContent();
if (dc == null || !mChanges.get(dc).hasChanged()) continue;
+ final int originalSeq = dc.getConfiguration().seq;
dc.sendNewConfiguration();
// Set to ready if no other change controls the ready state. But if there is, such as
// if an activity is pausing, it will call setReady(ar, false) and wait for the next
@@ -2871,7 +2877,22 @@
if (!mReadyTrackerOld.mUsed) {
setReady(dc, true);
}
+ if (originalSeq == dc.getConfiguration().seq) continue;
+ // If the update is deferred, sendNewConfiguration won't deliver new configuration to
+ // clients, then it is the caller's responsibility to deliver the changes.
+ if (mController.mAtm.mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
+ if (activitiesMayChange == null) {
+ activitiesMayChange = new ArrayList<>();
+ }
+ final ArrayList<ActivityRecord> visibleActivities = activitiesMayChange;
+ dc.forAllActivities(r -> {
+ if (r.isVisibleRequested()) {
+ visibleActivities.add(r);
+ }
+ });
+ }
}
+ return activitiesMayChange;
}
boolean getLegacyIsReady() {
diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
new file mode 100644
index 0000000..e82dc37
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
@@ -0,0 +1,448 @@
+/*
+ * Copyright 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.wm;
+
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TPL;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.IntArray;
+import android.util.Pair;
+import android.util.Size;
+import android.view.InputWindowHandle;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
+import android.window.WindowInfosListener;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.wm.utils.RegionUtils;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Optional;
+
+/**
+ * Class to handle TrustedPresentationListener registrations in a thread safe manner. This class
+ * also takes care of cleaning up listeners when the remote process dies.
+ */
+public class TrustedPresentationListenerController {
+
+ // Should only be accessed by the posting to the handler
+ private class Listeners {
+ private final class ListenerDeathRecipient implements IBinder.DeathRecipient {
+ IBinder mListenerBinder;
+ int mInstances;
+
+ ListenerDeathRecipient(IBinder listenerBinder) {
+ mListenerBinder = listenerBinder;
+ mInstances = 0;
+ try {
+ mListenerBinder.linkToDeath(this, 0);
+ } catch (RemoteException ignore) {
+ }
+ }
+
+ void addInstance() {
+ mInstances++;
+ }
+
+ // return true if there are no instances alive
+ boolean removeInstance() {
+ mInstances--;
+ if (mInstances > 0) {
+ return false;
+ }
+ mListenerBinder.unlinkToDeath(this, 0);
+ return true;
+ }
+
+ public void binderDied() {
+ mHandler.post(() -> {
+ mUniqueListeners.remove(mListenerBinder);
+ removeListeners(mListenerBinder, Optional.empty());
+ });
+ }
+ }
+
+ // tracks binder deaths for cleanup
+ ArrayMap<IBinder, ListenerDeathRecipient> mUniqueListeners = new ArrayMap<>();
+ ArrayMap<IBinder /*window*/, ArrayList<TrustedPresentationInfo>> mWindowToListeners =
+ new ArrayMap<>();
+
+ void register(IBinder window, ITrustedPresentationListener listener,
+ TrustedPresentationThresholds thresholds, int id) {
+ var listenersForWindow = mWindowToListeners.computeIfAbsent(window,
+ iBinder -> new ArrayList<>());
+ listenersForWindow.add(new TrustedPresentationInfo(thresholds, id, listener));
+
+ // register death listener
+ var listenerBinder = listener.asBinder();
+ var deathRecipient = mUniqueListeners.computeIfAbsent(listenerBinder,
+ ListenerDeathRecipient::new);
+ deathRecipient.addInstance();
+ }
+
+ void unregister(ITrustedPresentationListener trustedPresentationListener, int id) {
+ var listenerBinder = trustedPresentationListener.asBinder();
+ var deathRecipient = mUniqueListeners.get(listenerBinder);
+ if (deathRecipient == null) {
+ ProtoLog.e(WM_DEBUG_TPL, "unregister failed, couldn't find"
+ + " deathRecipient for %s with id=%d", trustedPresentationListener, id);
+ return;
+ }
+
+ if (deathRecipient.removeInstance()) {
+ mUniqueListeners.remove(listenerBinder);
+ }
+ removeListeners(listenerBinder, Optional.of(id));
+ }
+
+ boolean isEmpty() {
+ return mWindowToListeners.isEmpty();
+ }
+
+ ArrayList<TrustedPresentationInfo> get(IBinder windowToken) {
+ return mWindowToListeners.get(windowToken);
+ }
+
+ private void removeListeners(IBinder listenerBinder, Optional<Integer> id) {
+ for (int i = mWindowToListeners.size() - 1; i >= 0; i--) {
+ var listeners = mWindowToListeners.valueAt(i);
+ for (int j = listeners.size() - 1; j >= 0; j--) {
+ var listener = listeners.get(j);
+ if (listener.mListener.asBinder() == listenerBinder && (id.isEmpty()
+ || listener.mId == id.get())) {
+ listeners.remove(j);
+ }
+ }
+ if (listeners.isEmpty()) {
+ mWindowToListeners.removeAt(i);
+ }
+ }
+ }
+ }
+
+ private final Object mHandlerThreadLock = new Object();
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+
+ private WindowInfosListener mWindowInfosListener;
+
+ Listeners mRegisteredListeners = new Listeners();
+
+ private InputWindowHandle[] mLastWindowHandles;
+
+ private final Object mIgnoredWindowTokensLock = new Object();
+
+ private final ArraySet<IBinder> mIgnoredWindowTokens = new ArraySet<>();
+
+ private void startHandlerThreadIfNeeded() {
+ synchronized (mHandlerThreadLock) {
+ if (mHandler == null) {
+ mHandlerThread = new HandlerThread("WindowInfosListenerForTpl");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ }
+ }
+ }
+
+ void addIgnoredWindowTokens(IBinder token) {
+ synchronized (mIgnoredWindowTokensLock) {
+ mIgnoredWindowTokens.add(token);
+ }
+ }
+
+ void removeIgnoredWindowTokens(IBinder token) {
+ synchronized (mIgnoredWindowTokensLock) {
+ mIgnoredWindowTokens.remove(token);
+ }
+ }
+
+ void registerListener(IBinder window, ITrustedPresentationListener listener,
+ TrustedPresentationThresholds thresholds, int id) {
+ startHandlerThreadIfNeeded();
+ mHandler.post(() -> {
+ ProtoLog.d(WM_DEBUG_TPL, "Registering listener=%s with id=%d for window=%s with %s",
+ listener, id, window, thresholds);
+
+ mRegisteredListeners.register(window, listener, thresholds, id);
+ registerWindowInfosListener();
+ // Update the initial state for the new registered listener
+ computeTpl(mLastWindowHandles);
+ });
+ }
+
+ void unregisterListener(ITrustedPresentationListener listener, int id) {
+ startHandlerThreadIfNeeded();
+ mHandler.post(() -> {
+ ProtoLog.d(WM_DEBUG_TPL, "Unregistering listener=%s with id=%d",
+ listener, id);
+
+ mRegisteredListeners.unregister(listener, id);
+ if (mRegisteredListeners.isEmpty()) {
+ unregisterWindowInfosListener();
+ }
+ });
+ }
+
+ void dump(PrintWriter pw) {
+ final String innerPrefix = " ";
+ pw.println("TrustedPresentationListenerController:");
+ pw.println(innerPrefix + "Active unique listeners ("
+ + mRegisteredListeners.mUniqueListeners.size() + "):");
+ for (int i = 0; i < mRegisteredListeners.mWindowToListeners.size(); i++) {
+ pw.println(
+ innerPrefix + " window=" + mRegisteredListeners.mWindowToListeners.keyAt(i));
+ final var listeners = mRegisteredListeners.mWindowToListeners.valueAt(i);
+ for (int j = 0; j < listeners.size(); j++) {
+ final var listener = listeners.get(j);
+ pw.println(innerPrefix + innerPrefix + " listener=" + listener.mListener.asBinder()
+ + " id=" + listener.mId
+ + " thresholds=" + listener.mThresholds);
+ }
+ }
+ }
+
+ private void registerWindowInfosListener() {
+ if (mWindowInfosListener != null) {
+ return;
+ }
+
+ mWindowInfosListener = new WindowInfosListener() {
+ @Override
+ public void onWindowInfosChanged(InputWindowHandle[] windowHandles,
+ DisplayInfo[] displayInfos) {
+ mHandler.post(() -> computeTpl(windowHandles));
+ }
+ };
+ mLastWindowHandles = mWindowInfosListener.register().first;
+ }
+
+ private void unregisterWindowInfosListener() {
+ if (mWindowInfosListener == null) {
+ return;
+ }
+
+ mWindowInfosListener.unregister();
+ mWindowInfosListener = null;
+ mLastWindowHandles = null;
+ }
+
+ private void computeTpl(InputWindowHandle[] windowHandles) {
+ mLastWindowHandles = windowHandles;
+ if (mLastWindowHandles == null || mLastWindowHandles.length == 0
+ || mRegisteredListeners.isEmpty()) {
+ return;
+ }
+
+ Rect tmpRect = new Rect();
+ Matrix tmpInverseMatrix = new Matrix();
+ float[] tmpMatrix = new float[9];
+ Region coveredRegionsAbove = new Region();
+ long currTimeMs = System.currentTimeMillis();
+ ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.length);
+
+ ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates =
+ new ArrayMap<>();
+ ArraySet<IBinder> ignoredWindowTokens;
+ synchronized (mIgnoredWindowTokensLock) {
+ ignoredWindowTokens = new ArraySet<>(mIgnoredWindowTokens);
+ }
+ for (var windowHandle : mLastWindowHandles) {
+ if (ignoredWindowTokens.contains(windowHandle.getWindowToken())) {
+ ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name);
+ continue;
+ }
+ tmpRect.set(windowHandle.frame);
+ var listeners = mRegisteredListeners.get(windowHandle.getWindowToken());
+ if (listeners != null) {
+ Region region = new Region();
+ region.op(tmpRect, coveredRegionsAbove, Region.Op.DIFFERENCE);
+ windowHandle.transform.invert(tmpInverseMatrix);
+ tmpInverseMatrix.getValues(tmpMatrix);
+ float scaleX = (float) Math.sqrt(tmpMatrix[MSCALE_X] * tmpMatrix[MSCALE_X]
+ + tmpMatrix[MSKEW_X] * tmpMatrix[MSKEW_X]);
+ float scaleY = (float) Math.sqrt(tmpMatrix[MSCALE_Y] * tmpMatrix[MSCALE_Y]
+ + tmpMatrix[MSKEW_Y] * tmpMatrix[MSKEW_Y]);
+
+ float fractionRendered = computeFractionRendered(region, new RectF(tmpRect),
+ windowHandle.contentSize,
+ scaleX, scaleY);
+
+ checkIfInThreshold(listeners, listenerUpdates, fractionRendered, windowHandle.alpha,
+ currTimeMs);
+ }
+
+ coveredRegionsAbove.op(tmpRect, Region.Op.UNION);
+ ProtoLog.v(WM_DEBUG_TPL, "coveredRegionsAbove updated with %s frame:%s region:%s",
+ windowHandle.name, tmpRect.toShortString(), coveredRegionsAbove);
+ }
+
+ for (int i = 0; i < listenerUpdates.size(); i++) {
+ var updates = listenerUpdates.valueAt(i);
+ var listener = listenerUpdates.keyAt(i);
+ try {
+ listener.onTrustedPresentationChanged(updates.first.toArray(),
+ updates.second.toArray());
+ } catch (RemoteException ignore) {
+ }
+ }
+ }
+
+ private void addListenerUpdate(
+ ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates,
+ ITrustedPresentationListener listener, int id, boolean presentationState) {
+ var updates = listenerUpdates.get(listener);
+ if (updates == null) {
+ updates = new Pair<>(new IntArray(), new IntArray());
+ listenerUpdates.put(listener, updates);
+ }
+ if (presentationState) {
+ updates.first.add(id);
+ } else {
+ updates.second.add(id);
+ }
+ }
+
+
+ private void checkIfInThreshold(
+ ArrayList<TrustedPresentationInfo> listeners,
+ ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates,
+ float fractionRendered, float alpha, long currTimeMs) {
+ ProtoLog.v(WM_DEBUG_TPL, "checkIfInThreshold fractionRendered=%f alpha=%f currTimeMs=%d",
+ fractionRendered, alpha, currTimeMs);
+ for (int i = 0; i < listeners.size(); i++) {
+ var trustedPresentationInfo = listeners.get(i);
+ var listener = trustedPresentationInfo.mListener;
+ boolean lastState = trustedPresentationInfo.mLastComputedTrustedPresentationState;
+ boolean newState =
+ (alpha >= trustedPresentationInfo.mThresholds.mMinAlpha) && (fractionRendered
+ >= trustedPresentationInfo.mThresholds.mMinFractionRendered);
+ trustedPresentationInfo.mLastComputedTrustedPresentationState = newState;
+
+ ProtoLog.v(WM_DEBUG_TPL,
+ "lastState=%s newState=%s alpha=%f minAlpha=%f fractionRendered=%f "
+ + "minFractionRendered=%f",
+ lastState, newState, alpha, trustedPresentationInfo.mThresholds.mMinAlpha,
+ fractionRendered, trustedPresentationInfo.mThresholds.mMinFractionRendered);
+
+ if (lastState && !newState) {
+ // We were in the trusted presentation state, but now we left it,
+ // emit the callback if needed
+ if (trustedPresentationInfo.mLastReportedTrustedPresentationState) {
+ trustedPresentationInfo.mLastReportedTrustedPresentationState = false;
+ addListenerUpdate(listenerUpdates, listener,
+ trustedPresentationInfo.mId, /*presentationState*/ false);
+ ProtoLog.d(WM_DEBUG_TPL, "Adding untrusted state listener=%s with id=%d",
+ listener, trustedPresentationInfo.mId);
+ }
+ // Reset the timer
+ trustedPresentationInfo.mEnteredTrustedPresentationStateTime = -1;
+ } else if (!lastState && newState) {
+ // We were not in the trusted presentation state, but we entered it, begin the timer
+ // and make sure this gets called at least once more!
+ trustedPresentationInfo.mEnteredTrustedPresentationStateTime = currTimeMs;
+ mHandler.postDelayed(() -> {
+ computeTpl(mLastWindowHandles);
+ }, (long) (trustedPresentationInfo.mThresholds.mStabilityRequirementMs * 1.5));
+ }
+
+ // Has the timer elapsed, but we are still in the state? Emit a callback if needed
+ if (!trustedPresentationInfo.mLastReportedTrustedPresentationState && newState && (
+ currTimeMs - trustedPresentationInfo.mEnteredTrustedPresentationStateTime
+ > trustedPresentationInfo.mThresholds.mStabilityRequirementMs)) {
+ trustedPresentationInfo.mLastReportedTrustedPresentationState = true;
+ addListenerUpdate(listenerUpdates, listener,
+ trustedPresentationInfo.mId, /*presentationState*/ true);
+ ProtoLog.d(WM_DEBUG_TPL, "Adding trusted state listener=%s with id=%d",
+ listener, trustedPresentationInfo.mId);
+ }
+ }
+ }
+
+ private float computeFractionRendered(Region visibleRegion, RectF screenBounds,
+ Size contentSize,
+ float sx, float sy) {
+ ProtoLog.v(WM_DEBUG_TPL,
+ "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s "
+ + "scale=%f,%f",
+ visibleRegion, screenBounds, contentSize, sx, sy);
+
+ if (contentSize.getWidth() == 0 || contentSize.getHeight() == 0) {
+ return -1;
+ }
+ if (screenBounds.width() == 0 || screenBounds.height() == 0) {
+ return -1;
+ }
+
+ float fractionRendered = Math.min(sx * sy, 1.0f);
+ ProtoLog.v(WM_DEBUG_TPL, "fractionRendered scale=%f", fractionRendered);
+
+ float boundsOverSourceW = screenBounds.width() / (float) contentSize.getWidth();
+ float boundsOverSourceH = screenBounds.height() / (float) contentSize.getHeight();
+ fractionRendered *= boundsOverSourceW * boundsOverSourceH;
+ ProtoLog.v(WM_DEBUG_TPL, "fractionRendered boundsOverSource=%f", fractionRendered);
+ // Compute the size of all the rects since they may be disconnected.
+ float[] visibleSize = new float[1];
+ RegionUtils.forEachRect(visibleRegion, rect -> {
+ float size = rect.width() * rect.height();
+ visibleSize[0] += size;
+ });
+
+ fractionRendered *= visibleSize[0] / (screenBounds.width() * screenBounds.height());
+ return fractionRendered;
+ }
+
+ private static class TrustedPresentationInfo {
+ boolean mLastComputedTrustedPresentationState = false;
+ boolean mLastReportedTrustedPresentationState = false;
+ long mEnteredTrustedPresentationStateTime = -1;
+ final TrustedPresentationThresholds mThresholds;
+
+ final ITrustedPresentationListener mListener;
+ final int mId;
+
+ private TrustedPresentationInfo(TrustedPresentationThresholds thresholds, int id,
+ ITrustedPresentationListener listener) {
+ mThresholds = thresholds;
+ mId = id;
+ mListener = listener;
+ checkValid(thresholds);
+ }
+
+ private void checkValid(TrustedPresentationThresholds thresholds) {
+ if (thresholds.mMinAlpha <= 0 || thresholds.mMinFractionRendered <= 0
+ || thresholds.mStabilityRequirementMs < 1) {
+ throw new IllegalArgumentException(
+ "TrustedPresentationThresholds values are invalid");
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0d2c94d..0c57036 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -303,9 +303,11 @@
import android.window.ClientWindowFrames;
import android.window.ISurfaceSyncGroupCompletedListener;
import android.window.ITaskFpsCallback;
+import android.window.ITrustedPresentationListener;
import android.window.ScreenCapture;
import android.window.SystemPerformanceHinter;
import android.window.TaskSnapshot;
+import android.window.TrustedPresentationThresholds;
import android.window.WindowContainerToken;
import android.window.WindowContextInfo;
@@ -764,6 +766,9 @@
private final SurfaceSyncGroupController mSurfaceSyncGroupController =
new SurfaceSyncGroupController();
+ final TrustedPresentationListenerController mTrustedPresentationListenerController =
+ new TrustedPresentationListenerController();
+
@VisibleForTesting
final class SettingsObserver extends ContentObserver {
private final Uri mDisplayInversionEnabledUri =
@@ -7171,6 +7176,7 @@
pw.println(separator);
}
mSystemPerformanceHinter.dump(pw, "");
+ mTrustedPresentationListenerController.dump(pw);
}
}
@@ -9771,4 +9777,17 @@
Binder.restoreCallingIdentity(origId);
}
}
+
+ @Override
+ public void registerTrustedPresentationListener(IBinder window,
+ ITrustedPresentationListener listener,
+ TrustedPresentationThresholds thresholds, int id) {
+ mTrustedPresentationListenerController.registerListener(window, listener, thresholds, id);
+ }
+
+ @Override
+ public void unregisterTrustedPresentationListener(ITrustedPresentationListener listener,
+ int id) {
+ mTrustedPresentationListenerController.unregisterListener(listener, id);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 2af6569..a872fd0 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -570,8 +570,10 @@
mService.deferWindowLayout();
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
try {
- if (transition != null) {
- transition.applyDisplayChangeIfNeeded();
+ final ArrayList<ActivityRecord> activitiesMayChange =
+ transition != null ? transition.applyDisplayChangeIfNeeded() : null;
+ if (activitiesMayChange != null) {
+ effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
}
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
@@ -695,8 +697,23 @@
for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
haveConfigChanges.valueAt(i).forAllActivities(r -> {
r.ensureActivityConfiguration(0, PRESERVE_WINDOWS);
+ if (activitiesMayChange != null) {
+ activitiesMayChange.remove(r);
+ }
});
}
+ // TODO(b/258618073): Combine with haveConfigChanges after confirming that there
+ // is no problem to always preserve window. Currently this uses the parameters
+ // as ATMS#ensureConfigAndVisibilityAfterUpdate.
+ if (activitiesMayChange != null) {
+ for (int i = activitiesMayChange.size() - 1; i >= 0; --i) {
+ final ActivityRecord ar = activitiesMayChange.get(i);
+ if (!ar.isVisibleRequested()) continue;
+ ar.ensureActivityConfiguration(0 /* globalChanges */,
+ !PRESERVE_WINDOWS, true /* ignoreVisibility */,
+ false /* isRequestedOrientationChanged */);
+ }
+ }
}
if (effects != 0) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e1f1f66..7bc7e2c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1189,6 +1189,11 @@
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
parentWindow.addChild(this, sWindowSubLayerComparator);
}
+
+ if (token.mRoundedCornerOverlay) {
+ mWmService.mTrustedPresentationListenerController.addIgnoredWindowTokens(
+ getWindowToken());
+ }
}
@Override
@@ -2393,6 +2398,9 @@
}
mWmService.postWindowRemoveCleanupLocked(this);
+
+ mWmService.mTrustedPresentationListenerController.removeIgnoredWindowTokens(
+ getWindowToken());
}
@Override
diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp
index 7edf445..ccd9bd0 100644
--- a/services/core/jni/com_android_server_hint_HintManagerService.cpp
+++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp
@@ -20,6 +20,7 @@
#include <aidl/android/hardware/power/IPower.h>
#include <android-base/stringprintf.h>
+#include <inttypes.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <powermanager/PowerHalController.h>
@@ -38,6 +39,15 @@
namespace android {
+static struct {
+ jclass clazz{};
+ jfieldID workPeriodStartTimestampNanos{};
+ jfieldID actualTotalDurationNanos{};
+ jfieldID actualCpuDurationNanos{};
+ jfieldID actualGpuDurationNanos{};
+ jfieldID timestampNanos{};
+} gWorkDurationInfo;
+
static power::PowerHalController gPowerHalController;
static std::unordered_map<jlong, std::shared_ptr<IPowerHintSession>> gSessionMap;
static std::mutex gSessionMapLock;
@@ -180,6 +190,26 @@
setMode(session_ptr, static_cast<SessionMode>(mode), enabled);
}
+static void nativeReportActualWorkDuration2(JNIEnv* env, jclass /* clazz */, jlong session_ptr,
+ jobjectArray jWorkDurations) {
+ int size = env->GetArrayLength(jWorkDurations);
+ std::vector<WorkDuration> workDurations(size);
+ for (int i = 0; i < size; i++) {
+ jobject workDuration = env->GetObjectArrayElement(jWorkDurations, i);
+ workDurations[i].workPeriodStartTimestampNanos =
+ env->GetLongField(workDuration, gWorkDurationInfo.workPeriodStartTimestampNanos);
+ workDurations[i].durationNanos =
+ env->GetLongField(workDuration, gWorkDurationInfo.actualTotalDurationNanos);
+ workDurations[i].cpuDurationNanos =
+ env->GetLongField(workDuration, gWorkDurationInfo.actualCpuDurationNanos);
+ workDurations[i].gpuDurationNanos =
+ env->GetLongField(workDuration, gWorkDurationInfo.actualGpuDurationNanos);
+ workDurations[i].timeStampNanos =
+ env->GetLongField(workDuration, gWorkDurationInfo.timestampNanos);
+ }
+ reportActualWorkDuration(session_ptr, workDurations);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sHintManagerServiceMethods[] = {
/* name, signature, funcPtr */
@@ -194,9 +224,23 @@
{"nativeSendHint", "(JI)V", (void*)nativeSendHint},
{"nativeSetThreads", "(J[I)V", (void*)nativeSetThreads},
{"nativeSetMode", "(JIZ)V", (void*)nativeSetMode},
+ {"nativeReportActualWorkDuration", "(J[Landroid/os/WorkDuration;)V",
+ (void*)nativeReportActualWorkDuration2},
};
int register_android_server_HintManagerService(JNIEnv* env) {
+ gWorkDurationInfo.clazz = env->FindClass("android/os/WorkDuration");
+ gWorkDurationInfo.workPeriodStartTimestampNanos =
+ env->GetFieldID(gWorkDurationInfo.clazz, "mWorkPeriodStartTimestampNanos", "J");
+ gWorkDurationInfo.actualTotalDurationNanos =
+ env->GetFieldID(gWorkDurationInfo.clazz, "mActualTotalDurationNanos", "J");
+ gWorkDurationInfo.actualCpuDurationNanos =
+ env->GetFieldID(gWorkDurationInfo.clazz, "mActualCpuDurationNanos", "J");
+ gWorkDurationInfo.actualGpuDurationNanos =
+ env->GetFieldID(gWorkDurationInfo.clazz, "mActualGpuDurationNanos", "J");
+ gWorkDurationInfo.timestampNanos =
+ env->GetFieldID(gWorkDurationInfo.clazz, "mTimestampNanos", "J");
+
return jniRegisterNativeMethods(env,
"com/android/server/power/hint/"
"HintManagerService$NativeWrapper",
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 627461a..4a2e1cb 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -65,6 +65,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
import com.android.server.credentials.metrics.ApiName;
import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.infra.AbstractMasterSystemService;
@@ -101,6 +102,13 @@
private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
"enable_credential_description_api";
+ /**
+ * Value stored in autofill pref when credential provider is primary. This is
+ * used as a placeholder since a credman only provider will not have an
+ * autofill service.
+ */
+ public static final String AUTOFILL_PLACEHOLDER_VALUE = "credential-provider";
+
private final Context mContext;
/** Cache of system service list per user id. */
@@ -194,6 +202,8 @@
@SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
// this.mLock
protected void handlePackageRemovedMultiModeLocked(String packageName, int userId) {
+ updateProvidersWhenPackageRemoved(mContext, packageName);
+
List<CredentialManagerServiceImpl> services = peekServiceListForUserLocked(userId);
if (services == null) {
return;
@@ -216,8 +226,6 @@
for (CredentialManagerServiceImpl serviceToBeRemoved : servicesToBeRemoved) {
removeServiceFromCache(serviceToBeRemoved, userId);
removeServiceFromSystemServicesCache(serviceToBeRemoved, userId);
- removeServiceFromMultiModeSettings(serviceToBeRemoved.getComponentName()
- .flattenToString(), userId);
CredentialDescriptionRegistry.forUser(userId)
.evictProviderWithPackageName(serviceToBeRemoved.getServicePackageName());
}
@@ -1114,4 +1122,101 @@
mRequestSessions.get(userId).put(token, requestSession);
}
}
+
+ /** Updates the list of providers when an app is uninstalled. */
+ public static void updateProvidersWhenPackageRemoved(Context context, String packageName) {
+ // Get the current providers.
+ String rawProviders =
+ Settings.Secure.getStringForUser(
+ context.getContentResolver(),
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ UserHandle.myUserId());
+ if (rawProviders == null) {
+ Slog.w(TAG, "settings key is null");
+ return;
+ }
+
+ // Remove any providers from the primary setting that contain the package name
+ // being removed.
+ Set<String> primaryProviders =
+ getStoredProviders(rawProviders, packageName);
+ if (!Settings.Secure.putString(
+ context.getContentResolver(),
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ String.join(":", primaryProviders))) {
+ Slog.w(TAG, "Failed to remove primary package: " + packageName);
+ return;
+ }
+
+ // Read the autofill provider so we don't accidentally erase it.
+ String autofillProvider =
+ Settings.Secure.getStringForUser(
+ context.getContentResolver(),
+ Settings.Secure.AUTOFILL_SERVICE,
+ UserHandle.myUserId());
+
+ // If there is an autofill provider and it is the placeholder indicating
+ // that the currently selected primary provider does not support autofill
+ // then we should wipe the setting to keep it in sync.
+ if (autofillProvider != null && primaryProviders.isEmpty()) {
+ if (autofillProvider.equals(AUTOFILL_PLACEHOLDER_VALUE)) {
+ if (!Settings.Secure.putString(
+ context.getContentResolver(),
+ Settings.Secure.AUTOFILL_SERVICE,
+ "")) {
+ Slog.w(TAG, "Failed to remove autofill package: " + packageName);
+ }
+ } else {
+ // If the existing autofill provider is from the app being removed
+ // then erase the autofill service setting.
+ ComponentName cn = ComponentName.unflattenFromString(autofillProvider);
+ if (cn != null && cn.getPackageName().equals(packageName)) {
+ if (!Settings.Secure.putString(
+ context.getContentResolver(),
+ Settings.Secure.AUTOFILL_SERVICE,
+ "")) {
+ Slog.w(TAG, "Failed to remove autofill package: " + packageName);
+ }
+ }
+ }
+ }
+
+ // Read the credential providers to remove any reference of the removed app.
+ String rawCredentialProviders =
+ Settings.Secure.getStringForUser(
+ context.getContentResolver(),
+ Settings.Secure.CREDENTIAL_SERVICE,
+ UserHandle.myUserId());
+
+ // Remove any providers that belong to the removed app.
+ Set<String> credentialProviders =
+ getStoredProviders(rawCredentialProviders, packageName);
+ if (!Settings.Secure.putString(
+ context.getContentResolver(),
+ Settings.Secure.CREDENTIAL_SERVICE,
+ String.join(":", credentialProviders))) {
+ Slog.w(TAG, "Failed to remove secondary package: " + packageName);
+ }
+ }
+
+ /** Gets the list of stored providers from a string removing any mention of package name. */
+ public static Set<String> getStoredProviders(String rawProviders, String packageName) {
+ // If the app being removed matches any of the package names from
+ // this list then don't add it in the output.
+ Set<String> providers = new HashSet<>();
+ for (String rawComponentName : rawProviders.split(":")) {
+ if (TextUtils.isEmpty(rawComponentName)
+ || rawComponentName.equals("null")) {
+ Slog.d(TAG, "provider component name is empty or null");
+ continue;
+ }
+
+ ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
+ if (cn != null && !cn.getPackageName().equals(packageName)) {
+ providers.add(cn.flattenToString());
+ }
+ }
+
+ return providers;
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1919eb3..59e95e7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -268,6 +268,8 @@
"com.android.server.backup.BackupManagerService$Lifecycle";
private static final String APPWIDGET_SERVICE_CLASS =
"com.android.server.appwidget.AppWidgetService";
+ private static final String ARC_PERSISTENT_DATA_BLOCK_SERVICE_CLASS =
+ "com.android.server.arc.persistent_data_block.ArcPersistentDataBlockService";
private static final String ARC_SYSTEM_HEALTH_SERVICE =
"com.android.server.arc.health.ArcSystemHealthService";
private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
@@ -1489,8 +1491,6 @@
boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
false);
- boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1");
-
boolean isWatch = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WATCH);
@@ -1892,6 +1892,12 @@
t.traceEnd();
}
+ if (Build.IS_ARC && SystemProperties.getInt("ro.boot.dev_mode", 0) == 1) {
+ t.traceBegin("StartArcPersistentDataBlock");
+ mSystemServiceManager.startService(ARC_PERSISTENT_DATA_BLOCK_SERVICE_CLASS);
+ t.traceEnd();
+ }
+
t.traceBegin("StartTestHarnessMode");
mSystemServiceManager.startService(TestHarnessModeService.class);
t.traceEnd();
@@ -2318,7 +2324,7 @@
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
|| mPackageManager.hasSystemFeature(
PackageManager.FEATURE_USB_ACCESSORY)
- || isEmulator) {
+ || Build.IS_EMULATOR) {
// Manage USB host and device support
t.traceBegin("StartUsbService");
mSystemServiceManager.startService(USB_SERVICE_CLASS);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
index 693cafe..acd9dce 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -727,6 +727,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS)
public void testDisplayBrightnessHdr_SkipAnimationOnHdrAppearance() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
@@ -762,6 +763,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS)
public void testDisplayBrightnessHdr_SkipAnimationOnHdrRemoval() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index b227993..50b0e16 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1202,6 +1202,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS)
public void testDisplayBrightnessHdr_SkipAnimationOnHdrAppearance() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
@@ -1236,6 +1237,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS)
public void testDisplayBrightnessHdr_SkipAnimationOnHdrRemoval() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
index 72dc725..4ba9d60 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -44,6 +43,9 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.AlarmManagerInternal;
import com.android.server.DropBoxManagerInternal;
import com.android.server.LocalServices;
@@ -85,6 +87,12 @@
public final ApplicationExitInfoTest.ServiceThreadRule
mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .spyStatic(FrameworkStatsLog.class)
+ .spyStatic(ProcessList.class)
+ .build();
+
@Mock
AppOpsService mAppOpsService;
@Mock
@@ -140,6 +148,7 @@
realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal());
realAms.mOomAdjuster = spy(realAms.mOomAdjuster);
+ ExtendedMockito.doNothing().when(() -> ProcessList.setOomAdj(anyInt(), anyInt(), anyInt()));
realAms.mPackageManagerInt = mPackageManagerInt;
realAms.mUsageStatsService = mUsageStatsManagerInt;
realAms.mProcessesReady = true;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 2378416..c03799d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -79,11 +79,9 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.modules.utils.testing.ExtendedMockitoRule;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
@@ -112,11 +110,6 @@
BroadcastProcessQueue mHead;
- @Rule
- public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
- .spyStatic(FrameworkStatsLog.class)
- .build();
-
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 646f486..79b39b8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -20,7 +20,9 @@
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_FLAG_SELF;
+import static android.app.AppOpsManager.OP_READ_DEVICE_IDENTIFIERS;
import static android.app.AppOpsManager.OP_READ_SMS;
+import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS;
import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.OP_WRITE_SMS;
import static android.os.UserHandle.getAppId;
@@ -49,8 +51,10 @@
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
+import android.app.SyncNotedAppOp;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
@@ -58,6 +62,7 @@
import android.permission.PermissionManager;
import android.provider.Settings;
import android.util.ArrayMap;
+import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -79,7 +84,6 @@
import org.mockito.quality.Strictness;
import java.io.File;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -99,12 +103,15 @@
private static final Context sContext = InstrumentationRegistry.getTargetContext();
private static final String sMyPackageName = sContext.getOpPackageName();
+ private static final String sSdkSandboxPackageName = sContext.getPackageManager()
+ .getSdkSandboxPackageName();
private File mStorageFile;
private File mRecentAccessesFile;
private Handler mHandler;
private AppOpsService mAppOpsService;
private int mMyUid;
+ private int mSdkSandboxPackageUid;
private long mTestStartMillis;
private StaticMockitoSession mMockingSession;
@@ -132,6 +139,7 @@
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
mMyUid = Process.myUid();
+ mSdkSandboxPackageUid = resolveSdkSandboxPackageUid();
initializeStaticMocks();
@@ -152,6 +160,39 @@
mMockingSession.finishMocking();
}
+ private static int resolveSdkSandboxPackageUid() {
+ try {
+ return sContext.getPackageManager().getPackageUid(
+ sSdkSandboxPackageName,
+ PackageManager.PackageInfoFlags.of(0)
+ );
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Can't resolve sandbox package uid", e);
+ return Process.INVALID_UID;
+ }
+ }
+
+ private static void mockGetPackage(
+ PackageManagerInternal managerMock,
+ String packageName
+ ) {
+ AndroidPackage packageMock = mock(AndroidPackage.class);
+ when(managerMock.getPackage(packageName)).thenReturn(packageMock);
+ }
+
+ private static void mockGetPackageStateInternal(
+ PackageManagerInternal managerMock,
+ String packageName,
+ int uid
+ ) {
+ PackageStateInternal packageStateInternalMock = mock(PackageStateInternal.class);
+ when(packageStateInternalMock.isPrivileged()).thenReturn(false);
+ when(packageStateInternalMock.getAppId()).thenReturn(uid);
+ when(packageStateInternalMock.getAndroidPackage()).thenReturn(mock(AndroidPackage.class));
+ when(managerMock.getPackageStateInternal(packageName))
+ .thenReturn(packageStateInternalMock);
+ }
+
private void initializeStaticMocks() {
mMockingSession = mockitoSession()
.strictness(Strictness.LENIENT)
@@ -163,16 +204,11 @@
// Mock LocalServices.getService(PackageManagerInternal.class).getPackageStateInternal
// and getPackage dependency needed by AppOpsService
PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class);
- AndroidPackage mockMyPkg = mock(AndroidPackage.class);
- when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList());
- PackageStateInternal mockMyPSInternal = mock(PackageStateInternal.class);
- when(mockMyPSInternal.isPrivileged()).thenReturn(false);
- when(mockMyPSInternal.getAppId()).thenReturn(mMyUid);
- when(mockMyPSInternal.getAndroidPackage()).thenReturn(mockMyPkg);
-
- when(mockPackageManagerInternal.getPackageStateInternal(sMyPackageName))
- .thenReturn(mockMyPSInternal);
- when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
+ mockGetPackage(mockPackageManagerInternal, sMyPackageName);
+ mockGetPackageStateInternal(mockPackageManagerInternal, sMyPackageName, mMyUid);
+ mockGetPackage(mockPackageManagerInternal, sSdkSandboxPackageName);
+ mockGetPackageStateInternal(mockPackageManagerInternal, sSdkSandboxPackageName,
+ mSdkSandboxPackageUid);
when(mockPackageManagerInternal.getPackageUid(eq(sMyPackageName), anyLong(),
eq(getUserId(mMyUid)))).thenReturn(mMyUid);
doReturn(mockPackageManagerInternal).when(
@@ -233,6 +269,21 @@
assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
}
+ @Test
+ public void testNoteOperationFromSdkSandbox() {
+ int sandboxUid = Process.toSdkSandboxUid(mMyUid);
+
+ // Note an op that's allowed.
+ SyncNotedAppOp allowedResult = mAppOpsService.noteOperation(OP_TAKE_AUDIO_FOCUS, sandboxUid,
+ sSdkSandboxPackageName, null, false, null, false);
+ assertThat(allowedResult.getOpMode()).isEqualTo(MODE_ALLOWED);
+
+ // Note another op that's not allowed.
+ SyncNotedAppOp erroredResult = mAppOpsService.noteOperation(OP_READ_DEVICE_IDENTIFIERS,
+ sandboxUid, sSdkSandboxPackageName, null, false, null, false);
+ assertThat(erroredResult.getOpMode()).isEqualTo(MODE_ERRORED);
+ }
+
/**
* Tests the scenario where an operation's permission is controlled by another operation.
* For example the results of a WIFI_SCAN can be used to infer the location of a user, so the
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index e5291d3..eaf0ffd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -113,7 +113,7 @@
}
@Before
- public void setUp() {
+ public void setUp() throws Exception {
mMockingSession = mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
@@ -178,6 +178,7 @@
when(mContext.getSystemService(UiModeManager.class)).thenReturn(mock(UiModeManager.class));
mService = new TestJobSchedulerService(mContext);
+ mService.waitOnAsyncLoadingForTesting();
}
@After
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
index 3ba5d1e..d4ef647 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
@@ -109,6 +109,7 @@
mFlexibilityController =
new FlexibilityController(mJobSchedulerService, mock(PrefetchController.class));
mBatteryController = new BatteryController(mJobSchedulerService, mFlexibilityController);
+ mBatteryController.startTrackingLocked();
verify(mContext).registerReceiver(receiverCaptor.capture(),
ArgumentMatchers.argThat(filter ->
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index debc696..4fb9472 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -70,6 +70,8 @@
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -269,19 +271,19 @@
@Test
public void testOnConstantsUpdated_PercentsToDropConstraintsInvalidValues() {
- JobInfo.Builder jb = createJob(0).setOverrideDeadline(100L);
+ JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb);
- js.enqueueTime = 100L;
- assertEquals(150L,
+ js.enqueueTime = JobSchedulerService.sElapsedRealtimeClock.millis();
+ assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,20a,030,40");
- assertEquals(150L,
+ assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,40");
- assertEquals(150L,
+ assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,40,10,40");
- assertEquals(150L,
+ assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
}
@@ -369,7 +371,7 @@
@Test
public void testCurPercent() {
- long deadline = 1000;
+ long deadline = 100 * MINUTE_IN_MILLIS;
long nowElapsed;
JobInfo.Builder jb = createJob(0).setOverrideDeadline(deadline);
JobStatus js = createJobStatus("time", jb);
@@ -377,17 +379,17 @@
assertEquals(FROZEN_TIME, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
assertEquals(deadline + FROZEN_TIME,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME));
- nowElapsed = 600 + FROZEN_TIME;
+ nowElapsed = FROZEN_TIME + 60 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = 1400;
+ nowElapsed = FROZEN_TIME + 130 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = 950 + FROZEN_TIME;
+ nowElapsed = FROZEN_TIME + 95 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
@@ -395,8 +397,8 @@
nowElapsed = FROZEN_TIME;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- long delay = 100;
- deadline = 1100;
+ long delay = MINUTE_IN_MILLIS;
+ deadline = 101 * MINUTE_IN_MILLIS;
jb = createJob(0).setOverrideDeadline(deadline).setMinimumLatency(delay);
js = createJobStatus("time", jb);
@@ -405,18 +407,18 @@
assertEquals(deadline + FROZEN_TIME,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME + delay));
- nowElapsed = 600 + FROZEN_TIME + delay;
+ nowElapsed = FROZEN_TIME + delay + 60 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = 1400;
+ nowElapsed = FROZEN_TIME + 130 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = 950 + FROZEN_TIME + delay;
+ nowElapsed = FROZEN_TIME + delay + 95 * MINUTE_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
@@ -541,20 +543,20 @@
@Test
public void testGetLifeCycleEndElapsedLocked_NonPrefetch() {
// deadline
- JobInfo.Builder jb = createJob(0).setOverrideDeadline(1000L);
+ JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("time", jb);
- assertEquals(1000L + FROZEN_TIME,
+ assertEquals(HOUR_IN_MILLIS + FROZEN_TIME,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0));
// no deadline
jb = createJob(0);
js = createJobStatus("time", jb);
- assertEquals(100L + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS,
+ assertEquals(FROZEN_TIME + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, 100L));
}
@Test
public void testGetLifeCycleEndElapsedLocked_Rescheduled() {
- JobInfo.Builder jb = createJob(0).setOverrideDeadline(1000L);
+ JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("time", jb);
js = new JobStatus(
js, FROZEN_TIME, NO_LATEST_RUNTIME, /* numFailures */ 2, /* numSystemStops */ 0,
@@ -693,6 +695,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testExceptions_ShortWindow() {
JobInfo.Builder jb = createJob(0);
jb.setMinimumLatency(1);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 92aa982..8397b877 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -16,6 +16,8 @@
package com.android.server.job.controllers;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -261,7 +263,7 @@
public void testMediaBackupExemption_lateConstraint() {
final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
.addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
- .setOverrideDeadline(12)
+ .setOverrideDeadline(HOUR_IN_MILLIS)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
when(mJobSchedulerInternal.getCloudMediaProviderPackage(eq(0))).thenReturn(TEST_PACKAGE);
@@ -869,7 +871,7 @@
public void testWouldBeReadyWithConstraint_RequestedOverrideDeadline() {
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
- .setOverrideDeadline(300_000)
+ .setOverrideDeadline(HOUR_IN_MILLIS)
.build();
final JobStatus job = createJobStatus(jobInfo);
@@ -1025,7 +1027,7 @@
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setRequiresCharging(true)
- .setOverrideDeadline(300_000)
+ .setOverrideDeadline(HOUR_IN_MILLIS)
.addTriggerContentUri(new JobInfo.TriggerContentUri(
MediaStore.Images.Media.INTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
index 4329b6f..1a95d66 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
@@ -158,6 +158,7 @@
ArgumentCaptor<EstimatedLaunchTimeChangedListener> eltListenerCaptor =
ArgumentCaptor.forClass(EstimatedLaunchTimeChangedListener.class);
mPrefetchController = new PrefetchController(mJobSchedulerService);
+ mPrefetchController.startTrackingLocked();
mPcConstants = mPrefetchController.getPcConstants();
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
index 27efcfa..8fb7bd2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
@@ -48,6 +48,8 @@
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobSchedulerService.Constants;
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -141,6 +143,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testMaybeStartTrackingJobLocked_AlreadySatisfied() {
JobStatus delaySatisfied = createJobStatus(
"testMaybeStartTrackingJobLocked_AlreadySatisfied",
@@ -294,6 +297,7 @@
runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
}
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
private void runTestMaybeStartTrackingJobLocked_DeadlineInOrder() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -319,6 +323,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testMaybeStartTrackingJobLocked_DeadlineInOrder_SomeNotReady() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -357,6 +362,7 @@
runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
}
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
private void runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -387,6 +393,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_SomeNotReady() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -535,6 +542,7 @@
runTestCheckExpiredDeadlinesAndResetAlarm();
}
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
private void runTestCheckExpiredDeadlinesAndResetAlarm() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -585,6 +593,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testCheckExpiredDeadlinesAndResetAlarm_SomeNotReady() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -740,6 +749,7 @@
}
@Test
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testEvaluateStateLocked_Deadline() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index 733a433..3e73aa3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -45,6 +45,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
@@ -92,6 +93,7 @@
private static final String PACKAGE = "com.example";
private static final String CALLER_PACKAGE = "com.caller";
private static final String INSTALLER_PACKAGE = "com.installer";
+ private static final String INSTALLER_LABEL = "Installer";
private static final Path ICON_PATH = Path.of("icon.png");
@Rule
@@ -198,6 +200,10 @@
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getResourcesForApplication(eq(PACKAGE))).thenReturn(
mock(Resources.class));
+ ApplicationInfo installerAi = mock(ApplicationInfo.class);
+ when(mComputer.getApplicationInfo(eq(INSTALLER_PACKAGE), anyLong(), anyInt())).thenReturn(
+ installerAi);
+ when(installerAi.loadLabel(any())).thenReturn(INSTALLER_LABEL);
when(mInstallerService.createSessionInternal(any(), any(), any(), anyInt(),
anyInt())).thenReturn(1);
when(mInstallerService.getExistingDraftSessionId(anyInt(), any(), anyInt())).thenReturn(
@@ -222,7 +228,7 @@
Exception e = assertThrows(
SecurityException.class,
() -> mArchiveManager.requestArchive(PACKAGE, "different", mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e).hasMessageThat().isEqualTo(
String.format(
"The UID %s of callerPackageName set by the caller doesn't match the "
@@ -239,7 +245,7 @@
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
String.format("Package %s not found.", PACKAGE));
@@ -249,7 +255,8 @@
public void archiveApp_packageNotInstalledForUser() throws IntentSender.SendIntentException {
mPackageSetting.modifyUserState(UserHandle.CURRENT.getIdentifier()).setInstalled(false);
- mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
+ mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT,
+ 0);
rule.mocks().getHandler().flush();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -279,7 +286,7 @@
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo("No installer found");
}
@@ -293,7 +300,7 @@
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
"Installer does not support unarchival");
@@ -307,7 +314,7 @@
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
TextUtils.formatSimple("The app %s does not have a main activity.", PACKAGE));
@@ -319,7 +326,8 @@
doThrow(e).when(mArchiveManager).storeIcon(eq(PACKAGE),
any(LauncherActivityInfo.class), eq(mUserId), anyInt(), anyInt());
- mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
+ mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT,
+ 0);
rule.mocks().getHandler().flush();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -342,15 +350,16 @@
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT));
+ UserHandle.CURRENT, 0));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
TextUtils.formatSimple("The app %s is opted out of archiving.", PACKAGE));
}
@Test
- public void archiveApp_success() {
- mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
+ public void archiveApp_withNoAdditionalFlags_success() {
+ mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT,
+ 0);
rule.mocks().getHandler().flush();
verify(mInstallerService).uninstall(
@@ -363,6 +372,23 @@
}
@Test
+ public void archiveApp_withAdditionalFlags_success() {
+ mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT,
+ PackageManager.DELETE_SHOW_DIALOG);
+ rule.mocks().getHandler().flush();
+
+ verify(mInstallerService).uninstall(
+ eq(new VersionedPackage(PACKAGE, PackageManager.VERSION_CODE_HIGHEST)),
+ eq(CALLER_PACKAGE),
+ eq(DELETE_ARCHIVE | DELETE_KEEP_DATA | PackageManager.DELETE_SHOW_DIALOG),
+ eq(mIntentSender),
+ eq(UserHandle.CURRENT.getIdentifier()), anyInt());
+ assertThat(mPackageSetting.readUserState(
+ UserHandle.CURRENT.getIdentifier()).getArchiveState()).isEqualTo(
+ createArchiveState());
+ }
+
+ @Test
public void isAppArchivable_success() throws PackageManager.NameNotFoundException {
assertThat(mArchiveManager.isAppArchivable(PACKAGE, UserHandle.CURRENT)).isTrue();
}
@@ -545,7 +571,7 @@
ICON_PATH, null);
activityInfos.add(activityInfo);
}
- return new ArchiveState(activityInfos, INSTALLER_PACKAGE);
+ return new ArchiveState(activityInfos, INSTALLER_LABEL);
}
private static List<LauncherActivityInfo> createLauncherActivities() {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 3b39160..9114027 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -588,6 +588,38 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+ public void testTwoFingerTap_StateIsActivated_shouldInDelegating() {
+ assumeTrue(mMgh.mIsSinglePanningEnabled);
+ mMgh.setSinglePanningEnabled(false);
+ goFromStateIdleTo(STATE_ACTIVATED);
+ allowEventDelegation();
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
+ send(upEvent());
+ fastForward(ViewConfiguration.getDoubleTapTimeout());
+
+ assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+ public void testTwoFingerTap_StateIsIdle_shouldInDelegating() {
+ assumeTrue(mMgh.mIsSinglePanningEnabled);
+ mMgh.setSinglePanningEnabled(false);
+ goFromStateIdleTo(STATE_IDLE);
+ allowEventDelegation();
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
+ send(upEvent());
+ fastForward(ViewConfiguration.getDoubleTapTimeout());
+
+ assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState);
+ }
+
+ @Test
public void testMultiTap_outOfDistanceSlop_shouldInIdle() {
// All delay motion events should be sent, if multi-tap with out of distance slop.
// STATE_IDLE will check if tapCount() < 2.
@@ -719,6 +751,20 @@
}
@Test
+ public void testTwoFingerDown_twoPointerDownAndActivatedState_panningState() {
+ goFromStateIdleTo(STATE_ACTIVATED);
+ PointF pointer1 = DEFAULT_POINT;
+ PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
+ fastForward(ViewConfiguration.getTapTimeout());
+ assertIn(STATE_PANNING);
+
+ returnToNormalFrom(STATE_PANNING);
+ }
+
+ @Test
public void testActivatedWithTripleTap_invokeShowWindowPromptAction() {
goFromStateIdleTo(STATE_ACTIVATED);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index 4375105..1b9e6fb 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -179,6 +179,29 @@
}
@Test
+ public void testSubscribesToFoldState() throws RemoteException {
+ final List<Integer> actual = new ArrayList<>();
+ final List<Integer> expected = List.of(FoldState.FULLY_CLOSED, FoldState.FULLY_OPENED,
+ FoldState.UNKNOWN, FoldState.HALF_OPENED);
+ mProvider.subscribe(mOpContext, ctx -> {
+ assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
+ assertThat(mProvider.getFoldState()).isEqualTo(ctx.foldState);
+ actual.add(ctx.foldState);
+ });
+
+ for (int v : expected) {
+ mListener.onFoldChanged(v);
+ }
+
+ assertThat(actual).containsExactly(
+ FoldState.FULLY_CLOSED,
+ FoldState.FULLY_OPENED,
+ FoldState.UNKNOWN,
+ FoldState.HALF_OPENED
+ ).inOrder();
+ }
+
+ @Test
public void testSubscribesToDisplayState() throws RemoteException {
final List<Integer> actual = new ArrayList<>();
final List<Integer> expected = List.of(AuthenticateOptions.DISPLAY_STATE_AOD,
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
new file mode 100644
index 0000000..fd1abff
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.cert.CertificateException;
+import java.util.HashSet;
+import java.util.Set;
+
+/** atest FrameworksServicesTests:com.android.server.credentials.CredentialManagerServiceTest */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class CredentialManagerServiceTest {
+
+ Context mContext = null;
+
+ @Before
+ public void setUp() throws CertificateException {
+ mContext = ApplicationProvider.getApplicationContext();
+ }
+
+ @Test
+ public void getStoredProviders_emptyValue_success() {
+ Set<String> providers = CredentialManagerService.getStoredProviders("", "");
+ assertThat(providers.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void getStoredProviders_success() {
+ Set<String> providers =
+ CredentialManagerService.getStoredProviders(
+ "com.example.test/.TestActivity:com.example.test/.TestActivity2:"
+ + "com.example.test2/.TestActivity:blank",
+ "com.example.test");
+ assertThat(providers.size()).isEqualTo(1);
+ assertThat(providers.contains("com.example.test2/com.example.test2.TestActivity")).isTrue();
+ }
+
+ @Test
+ public void onProviderRemoved_success() {
+ setSettingsKey(
+ Settings.Secure.AUTOFILL_SERVICE,
+ CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
+ setSettingsKey(
+ Settings.Secure.CREDENTIAL_SERVICE,
+ "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity");
+ setSettingsKey(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ "com.example.test/com.example.test.TestActivity");
+
+ CredentialManagerService.updateProvidersWhenPackageRemoved(mContext, "com.example.test");
+
+ assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
+ assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
+ .isEqualTo("com.example.test2/com.example.test2.TestActivity");
+ assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY)).isEqualTo("");
+ }
+
+ @Test
+ public void onProviderRemoved_notPrimaryRemoved_success() {
+ final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
+ final String testCredentialValue =
+ "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
+
+ setSettingsKey(
+ Settings.Secure.AUTOFILL_SERVICE,
+ CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
+ setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE, testCredentialValue);
+ setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
+
+ CredentialManagerService.updateProvidersWhenPackageRemoved(mContext, "com.example.test3");
+
+ // Since the provider removed was not a primary provider then we should do nothing.
+ assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE))
+ .isEqualTo(CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
+ assertCredentialPropertyEquals(
+ getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE), testCredentialValue);
+ assertCredentialPropertyEquals(
+ getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY),
+ testCredentialPrimaryValue);
+ }
+
+ @Test
+ public void onProviderRemoved_isAlsoAutofillProvider_success() {
+ setSettingsKey(
+ Settings.Secure.AUTOFILL_SERVICE,
+ "com.example.test/com.example.test.AutofillProvider");
+ setSettingsKey(
+ Settings.Secure.CREDENTIAL_SERVICE,
+ "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity");
+ setSettingsKey(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ "com.example.test/com.example.test.TestActivity");
+
+ CredentialManagerService.updateProvidersWhenPackageRemoved(mContext, "com.example.test");
+
+ assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
+ assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
+ .isEqualTo("com.example.test2/com.example.test2.TestActivity");
+ assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY)).isEqualTo("");
+ }
+
+ @Test
+ public void onProviderRemoved_notPrimaryRemoved_isAlsoAutofillProvider_success() {
+ final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
+ final String testCredentialValue =
+ "com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
+ final String testAutofillValue = "com.example.test/com.example.test.TestAutofillActivity";
+
+ setSettingsKey(Settings.Secure.AUTOFILL_SERVICE, testAutofillValue);
+ setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE, testCredentialValue);
+ setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
+
+ CredentialManagerService.updateProvidersWhenPackageRemoved(mContext, "com.example.test3");
+
+ // Since the provider removed was not a primary provider then we should do nothing.
+ assertCredentialPropertyEquals(
+ getSettingsKey(Settings.Secure.AUTOFILL_SERVICE), testAutofillValue);
+ assertCredentialPropertyEquals(
+ getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE), testCredentialValue);
+ assertCredentialPropertyEquals(
+ getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY),
+ testCredentialPrimaryValue);
+ }
+
+ private void assertCredentialPropertyEquals(String actualValue, String newValue) {
+ Set<ComponentName> actualValueSet = new HashSet<>();
+ for (String rawComponentName : actualValue.split(":")) {
+ ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
+ if (cn != null) {
+ actualValueSet.add(cn);
+ }
+ }
+
+ Set<ComponentName> newValueSet = new HashSet<>();
+ for (String rawComponentName : newValue.split(":")) {
+ ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
+ if (cn != null) {
+ newValueSet.add(cn);
+ }
+ }
+
+ assertThat(actualValueSet).isEqualTo(newValueSet);
+ }
+
+ private void setSettingsKey(String key, String value) {
+ assertThat(Settings.Secure.putString(mContext.getContentResolver(), key, value)).isTrue();
+ }
+
+ private String getSettingsKey(String key) {
+ return Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), key, UserHandle.myUserId());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
index 1726ec1..a33f35a 100644
--- a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
@@ -29,6 +29,8 @@
import com.android.server.job.MockBiasJobService.TestEnvironment;
import com.android.server.job.MockBiasJobService.TestEnvironment.Event;
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
import java.util.ArrayList;
@TargetApi(24)
@@ -61,6 +63,7 @@
}
@FlakyTest(bugId = 293589359)
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testLowerBiasJobPreempted() throws Exception {
for (int i = 0; i < JobConcurrencyManager.MAX_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
@@ -92,6 +95,7 @@
assertTrue("Lower bias jobs were not preempted.", wasJobHigherExecuted);
}
+ @CoreCompatChangeRule.DisableCompatChanges({JobInfo.ENFORCE_MINIMUM_TIME_WINDOWS})
public void testHigherBiasJobNotPreempted() throws Exception {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 46ead85..3069b67 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -3,6 +3,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static com.android.server.job.JobStore.JOB_FILE_SPLIT_PREFIX;
@@ -141,7 +142,7 @@
final JobInfo task2 = new Builder(12, mComponent)
.setMinimumLatency(5000L)
.setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
- .setOverrideDeadline(30000L)
+ .setOverrideDeadline(4 * HOUR_IN_MILLIS)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.build();
@@ -194,7 +195,7 @@
final JobInfo task2 = new Builder(12, mComponent)
.setMinimumLatency(5000L)
.setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
- .setOverrideDeadline(30000L)
+ .setOverrideDeadline(3 * HOUR_IN_MILLIS)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.build();
@@ -224,7 +225,7 @@
final JobInfo task2 = new Builder(12, mComponent)
.setMinimumLatency(5000L)
.setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
- .setOverrideDeadline(30000L)
+ .setOverrideDeadline(5 * HOUR_IN_MILLIS)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.build();
@@ -330,7 +331,6 @@
@Test
public void testMaybeWriteStatusToDisk() throws Exception {
int taskId = 5;
- long runByMillis = 20000L; // 20s
long runFromMillis = 2000L; // 2s
long initialBackoff = 10000L; // 10s
@@ -338,7 +338,7 @@
.setRequiresCharging(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL)
- .setOverrideDeadline(runByMillis)
+ .setOverrideDeadline(6 * HOUR_IN_MILLIS)
.setMinimumLatency(runFromMillis)
.setPersisted(true)
.build();
@@ -379,7 +379,7 @@
final JobInfo task2 = new Builder(12, mComponent)
.setMinimumLatency(5000L)
.setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
- .setOverrideDeadline(30000L)
+ .setOverrideDeadline(7 * HOUR_IN_MILLIS)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.build();
@@ -542,7 +542,7 @@
@Test
public void testBiasPersisted() throws Exception {
JobInfo.Builder b = new Builder(92, mComponent)
- .setOverrideDeadline(5000)
+ .setOverrideDeadline(8 * HOUR_IN_MILLIS)
.setBias(42)
.setPersisted(true);
final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null, null);
@@ -613,7 +613,7 @@
@Test
public void testPriorityPersisted() throws Exception {
final JobInfo job = new Builder(92, mComponent)
- .setOverrideDeadline(5000)
+ .setOverrideDeadline(9 * HOUR_IN_MILLIS)
.setPriority(JobInfo.PRIORITY_MIN)
.setPersisted(true)
.build();
@@ -634,13 +634,13 @@
@Test
public void testNonPersistedTaskIsNotPersisted() throws Exception {
JobInfo.Builder b = new Builder(42, mComponent)
- .setOverrideDeadline(10000)
+ .setOverrideDeadline(10 * HOUR_IN_MILLIS)
.setPersisted(false);
JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(),
SOME_UID, null, -1, null, null);
mTaskStoreUnderTest.add(jsNonPersisted);
b = new Builder(43, mComponent)
- .setOverrideDeadline(10000)
+ .setOverrideDeadline(11 * HOUR_IN_MILLIS)
.setPersisted(true);
JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(),
SOME_UID, null, -1, null, null);
diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
index 44dad59..32bbc7a 100644
--- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
@@ -482,6 +482,35 @@
}
@Test
+ public void testGetThermalHeadroomThresholdsOnDefaultHalResult() throws Exception {
+ TemperatureWatcher watcher = mService.mTemperatureWatcher;
+ ArrayList<TemperatureThreshold> thresholds = new ArrayList<>();
+ mFakeHal.mTemperatureThresholdList = thresholds;
+ watcher.updateThresholds();
+ synchronized (watcher.mSamples) {
+ assertArrayEquals(
+ new float[]{Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN,
+ Float.NaN},
+ watcher.mHeadroomThresholds, 0.01f);
+ }
+ TemperatureThreshold nanThresholds = new TemperatureThreshold();
+ nanThresholds.name = "nan";
+ nanThresholds.type = Temperature.TYPE_SKIN;
+ nanThresholds.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1];
+ nanThresholds.coldThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1];
+ Arrays.fill(nanThresholds.hotThrottlingThresholds, Float.NaN);
+ Arrays.fill(nanThresholds.coldThrottlingThresholds, Float.NaN);
+ thresholds.add(nanThresholds);
+ watcher.updateThresholds();
+ synchronized (watcher.mSamples) {
+ assertArrayEquals(
+ new float[]{Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN,
+ Float.NaN},
+ watcher.mHeadroomThresholds, 0.01f);
+ }
+ }
+
+ @Test
public void testTemperatureWatcherGetSlopeOf() throws RemoteException {
TemperatureWatcher watcher = mService.mTemperatureWatcher;
List<TemperatureWatcher.Sample> samples = new ArrayList<>();
diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
index d09aa89..ffb3bce 100644
--- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -44,6 +44,7 @@
import android.os.IHintSession;
import android.os.PerformanceHintManager;
import android.os.Process;
+import android.os.WorkDuration;
import android.util.Log;
import com.android.server.FgThread;
@@ -89,6 +90,11 @@
private static final long[] DURATIONS_ZERO = new long[] {};
private static final long[] TIMESTAMPS_ZERO = new long[] {};
private static final long[] TIMESTAMPS_TWO = new long[] {1L, 2L};
+ private static final WorkDuration[] WORK_DURATIONS_THREE = new WorkDuration[] {
+ new WorkDuration(1L, 11L, 8L, 4L, 1L),
+ new WorkDuration(2L, 13L, 8L, 6L, 2L),
+ new WorkDuration(3L, 333333333L, 8L, 333333333L, 3L),
+ };
@Mock private Context mContext;
@Mock private HintManagerService.NativeWrapper mNativeWrapperMock;
@@ -593,4 +599,56 @@
}
a.close();
}
+
+ @Test
+ public void testReportActualWorkDuration2() throws Exception {
+ HintManagerService service = createService();
+ IBinder token = new Binder();
+
+ AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
+ .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+
+ a.updateTargetWorkDuration(100L);
+ a.reportActualWorkDuration2(WORK_DURATIONS_THREE);
+ verify(mNativeWrapperMock, times(1)).halReportActualWorkDuration(anyLong(),
+ eq(WORK_DURATIONS_THREE));
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ a.reportActualWorkDuration2(new WorkDuration[] {});
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ a.reportActualWorkDuration2(
+ new WorkDuration[] {new WorkDuration(-1L, 11L, 8L, 4L, 1L)});
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ a.reportActualWorkDuration2(new WorkDuration[] {new WorkDuration(1L, 0L, 8L, 4L, 1L)});
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ a.reportActualWorkDuration2(new WorkDuration[] {new WorkDuration(1L, 11L, 0L, 4L, 1L)});
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ a.reportActualWorkDuration2(
+ new WorkDuration[] {new WorkDuration(1L, 11L, 8L, -1L, 1L)});
+ });
+
+ reset(mNativeWrapperMock);
+ // Set session to background, then the duration would not be updated.
+ service.mUidObserver.onUidStateChanged(
+ a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0);
+
+ // Using CountDownLatch to ensure above onUidStateChanged() job was digested.
+ final CountDownLatch latch = new CountDownLatch(1);
+ FgThread.getHandler().post(() -> {
+ latch.countDown();
+ });
+ latch.await();
+
+ assertFalse(service.mUidObserver.isUidForeground(a.mUid));
+ a.reportActualWorkDuration2(WORK_DURATIONS_THREE);
+ verify(mNativeWrapperMock, never()).halReportActualWorkDuration(anyLong(), any(), any());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
index 337dd22..44dbe385 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
@@ -20,6 +20,7 @@
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.truth.Truth.assertThat;
+import android.app.Flags;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Person;
@@ -33,6 +34,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,6 +44,7 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.server.UiServiceTestCase;
import com.google.common.base.Strings;
@@ -54,6 +57,7 @@
import com.google.common.collect.Multimap;
import com.google.common.truth.Expect;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -72,6 +76,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -83,15 +88,16 @@
@RunWith(AndroidJUnit4.class)
public class NotificationVisitUrisTest extends UiServiceTestCase {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String TAG = "VisitUrisTest";
// Methods that are known to add Uris that are *NOT* verified.
- // This list should be emptied! Items can be removed as bugs are fixed.
+ // This list should only be used temporarily if needed, and any element in this list should
+ // have a tracking bug associated.
private static final Multimap<Class<?>, String> KNOWN_BAD =
- ImmutableMultimap.<Class<?>, String>builder()
- .put(Person.Builder.class, "setUri") // TODO: b/281044385
- .build();
+ ImmutableMultimap.<Class<?>, String>builder().build();
// Types that we can't really produce. No methods receiving these parameters will be invoked.
private static final ImmutableSet<Class<?>> UNUSABLE_TYPES =
@@ -155,6 +161,12 @@
@Before
public void setUp() {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mSetFlagsRule.enableFlags(Flags.FLAG_VISIT_RISKY_URIS);
+ }
+
+ @After
+ public void tearDown() {
+ SystemUiSystemPropertiesFlags.TEST_RESOLVER = null;
}
@Test // This is a meta-test, checks that the generators are not broken.
@@ -229,13 +241,12 @@
notification.visitUris(visitor);
Mockito.verify(visitor, Mockito.atLeastOnce()).accept(visitedUriCaptor.capture());
- List<Uri> visitedUris = new ArrayList<>(visitedUriCaptor.getAllValues());
+ Set<Uri> visitedUris = new HashSet<>(visitedUriCaptor.getAllValues());
visitedUris.remove(null);
expect.withMessage(notificationTypeMessage)
.that(visitedUris)
- .containsAtLeastElementsIn(includedUris);
- expect.that(KNOWN_BAD).isNotEmpty(); // Once empty, switch to containsExactlyElementsIn()
+ .containsExactlyElementsIn(includedUris);
}
private static Generated<Notification> buildNotification(Context context,
@@ -520,7 +531,7 @@
&& !EXCLUDED_SETTERS.containsEntry(clazz, method.getName())
&& !EXCLUDED_SETTERS_OVERLOADS.containsEntry(clazz, method)
&& Arrays.stream(method.getParameterTypes())
- .noneMatch(excludingParameterTypes::contains)) {
+ .noneMatch(excludingParameterTypes::contains)) {
methods.put(method.getName(), method);
}
}
@@ -535,14 +546,14 @@
List<Method> excludedSetters = setters.stream().filter(
m1 -> m1.getName().startsWith("set")
&& setters.stream().anyMatch(
- m2 -> {
- Class<?> param1 = m1.getParameterTypes()[0];
- Class<?> param2 = m2.getParameterTypes()[0];
- return m2.getName().startsWith("add")
- && param1.isArray()
- && !param2.isArray() && !param2.isPrimitive()
- && param1.getComponentType().equals(param2);
- })).toList();
+ m2 -> {
+ Class<?> param1 = m1.getParameterTypes()[0];
+ Class<?> param2 = m2.getParameterTypes()[0];
+ return m2.getName().startsWith("add")
+ && param1.isArray()
+ && !param2.isArray() && !param2.isPrimitive()
+ && param1.getComponentType().equals(param2);
+ })).toList();
setters.removeAll(excludedSetters);
return setters;
@@ -597,9 +608,8 @@
private static class SpecialParameterGenerator {
private static final ImmutableSet<Class<?>> INTERESTING_CLASSES =
- ImmutableSet.of(
- Person.class, Uri.class, Icon.class, Intent.class, PendingIntent.class,
- RemoteViews.class);
+ ImmutableSet.of(Person.class, Uri.class, Icon.class, Intent.class,
+ PendingIntent.class, RemoteViews.class);
private static final ImmutableSet<Class<?>> MOCKED_CLASSES = ImmutableSet.of();
private static final ImmutableMap<Class<?>, Object> PRIMITIVE_VALUES =
@@ -623,7 +633,7 @@
}
static boolean canGenerate(Class<?> clazz) {
- return (INTERESTING_CLASSES.contains(clazz) && !clazz.equals(Person.class))
+ return INTERESTING_CLASSES.contains(clazz)
|| MOCKED_CLASSES.contains(clazz)
|| clazz.equals(Context.class)
|| clazz.equals(Bundle.class)
@@ -658,6 +668,17 @@
return Icon.createWithContentUri(iconUri);
}
+ if (clazz == Person.class) {
+ // TODO(b/310189261): Person.setUri takes a string instead of a URI. We should
+ // find a way to use the SpecialParameterGenerator instead of this custom one.
+ Uri personUri = generateUri(
+ where.plus(Person.Builder.class).plus("setUri", String.class));
+ Uri iconUri = generateUri(where.plus(Person.Builder.class).plus("setIcon",
+ Icon.class).plus(Icon.class).plus("createWithContentUri", Uri.class));
+ return new Person.Builder().setUri(personUri.toString()).setIcon(
+ Icon.createWithContentUri(iconUri)).setName("John Doe").build();
+ }
+
if (clazz == Intent.class) {
// TODO(b/281044385): Are Intent Uris (new Intent(String,Uri)) relevant?
return new Intent("action");
@@ -717,9 +738,12 @@
private static class Location {
private static class Item {
- @Nullable private final Class<?> mMaybeClass;
- @Nullable private final Executable mMaybeMethod;
- @Nullable private final String mExtra;
+ @Nullable
+ private final Class<?> mMaybeClass;
+ @Nullable
+ private final Executable mMaybeMethod;
+ @Nullable
+ private final String mExtra;
Item(@NonNull Class<?> clazz) {
mMaybeClass = checkNotNull(clazz);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 97b6b98..4d25eaa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -524,7 +524,7 @@
mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelper.applyRestrictions();
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
// only mute audio, not vibrations
verify(mAppOps, atLeastOnce()).setRestriction(eq(AppOpsManager.OP_PLAY_AUDIO),
@@ -546,7 +546,7 @@
mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelper.applyRestrictions();
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
verify(mAppOps).setRestriction(
eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(new String[]{PKG_O}));
verify(mAppOps).setRestriction(
@@ -561,7 +561,7 @@
mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelper.applyRestrictions();
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
verify(mAppOps).setRestriction(
eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
verify(mAppOps).setRestriction(
@@ -576,7 +576,7 @@
mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelper.applyRestrictions();
- for (int usage : AudioAttributes.SDK_USAGES) {
+ for (int usage : AudioAttributes.getSdkUsages()) {
verify(mAppOps).setRestriction(
eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
verify(mAppOps).setRestriction(
@@ -1052,6 +1052,88 @@
}
@Test
+ public void testProtoWithAutoRuleCustomPolicy_classic() throws Exception {
+ setupZenConfig();
+ // clear any automatic rules just to make sure
+ mZenModeHelper.mConfig.automaticRules = new ArrayMap<>();
+
+ // Add an automatic rule with a custom policy
+ ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID);
+ rule.zenPolicy = new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowRepeatCallers(false)
+ .allowCalls(PEOPLE_TYPE_STARRED)
+ .build();
+ mZenModeHelper.mConfig.automaticRules.put(rule.id, rule);
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelper.pullRules(events);
+
+ boolean foundCustomEvent = false;
+ for (StatsEvent ev : events) {
+ AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
+ assertTrue(atom.hasDndModeRule());
+ DNDModeProto cfg = atom.getDndModeRule();
+ if (cfg.getUid() == CUSTOM_PKG_UID) {
+ foundCustomEvent = true;
+ // Check that the pieces of the policy are applied.
+ assertThat(cfg.hasPolicy()).isTrue();
+ DNDPolicyProto policy = cfg.getPolicy();
+ assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW);
+ assertThat(policy.getRepeatCallers().getNumber())
+ .isEqualTo(DNDProtoEnums.STATE_DISALLOW);
+ assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW);
+ assertThat(policy.getAllowCallsFrom().getNumber())
+ .isEqualTo(DNDProtoEnums.PEOPLE_STARRED);
+ }
+ }
+ assertTrue("couldn't find custom rule", foundCustomEvent);
+ }
+
+ @Test
+ public void testProtoWithAutoRuleCustomPolicy() throws Exception {
+ // allowChannels is only valid under modes_api.
+ mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
+
+ setupZenConfig();
+ // clear any automatic rules just to make sure
+ mZenModeHelper.mConfig.automaticRules = new ArrayMap<>();
+
+ // Add an automatic rule with a custom policy
+ ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID);
+ rule.zenPolicy = new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowRepeatCallers(false)
+ .allowCalls(PEOPLE_TYPE_STARRED)
+ .allowChannels(ZenPolicy.CHANNEL_TYPE_NONE)
+ .build();
+ mZenModeHelper.mConfig.automaticRules.put(rule.id, rule);
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelper.pullRules(events);
+
+ boolean foundCustomEvent = false;
+ for (StatsEvent ev : events) {
+ AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
+ assertTrue(atom.hasDndModeRule());
+ DNDModeProto cfg = atom.getDndModeRule();
+ if (cfg.getUid() == CUSTOM_PKG_UID) {
+ foundCustomEvent = true;
+ // Check that the pieces of the policy are applied.
+ assertThat(cfg.hasPolicy()).isTrue();
+ DNDPolicyProto policy = cfg.getPolicy();
+ assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW);
+ assertThat(policy.getRepeatCallers().getNumber())
+ .isEqualTo(DNDProtoEnums.STATE_DISALLOW);
+ assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW);
+ assertThat(policy.getAllowCallsFrom().getNumber())
+ .isEqualTo(DNDProtoEnums.PEOPLE_STARRED);
+ assertThat(policy.getAllowChannels().getNumber())
+ .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE);
+ }
+ }
+ assertTrue("couldn't find custom rule", foundCustomEvent);
+ }
+
+ @Test
public void ruleUidsCached() throws Exception {
setupZenConfig();
// one enabled automatic rule
@@ -2722,6 +2804,55 @@
}
@Test
+ public void testZenModeEventLog_policyAllowChannels() {
+ // when modes_api flag is on, ensure that any change in allow_channels gets logged,
+ // even when there are no other changes.
+ mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
+
+ // Default zen config has allow channels = priority (aka on)
+ setupZenConfig();
+
+ // First just turn zen mode on
+ mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
+ Process.SYSTEM_UID, true);
+
+ // Now change only the channels part of the policy; want to confirm that this'll be
+ // reflected in the logs
+ ZenModeConfig newConfig = mZenModeHelper.mConfig.copy();
+ newConfig.allowPriorityChannels = false;
+ mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
+ true);
+
+ // Total events: one for turning on, one for changing policy
+ assertThat(mZenModeEventLogger.numLoggedChanges()).isEqualTo(2);
+
+ // The first event is just turning DND on; make sure the policy is what we expect there
+ // before it changes in the next stage
+ assertThat(mZenModeEventLogger.getEventId(0))
+ .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId());
+ DNDPolicyProto origDndProto = mZenModeEventLogger.getPolicyProto(0);
+ checkDndProtoMatchesSetupZenConfig(origDndProto);
+ assertThat(origDndProto.getAllowChannels().getNumber())
+ .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_PRIORITY);
+
+ // Second message where we change the policy:
+ // - DND_POLICY_CHANGED (indicates only the policy changed and nothing else)
+ // - rule type: unknown (it's a policy change, not a rule change)
+ // - user action (because it comes from a "system" uid)
+ // - change is in allow channels, and final policy
+ assertThat(mZenModeEventLogger.getEventId(1))
+ .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_POLICY_CHANGED.getId());
+ assertThat(mZenModeEventLogger.getChangedRuleType(1))
+ .isEqualTo(DNDProtoEnums.UNKNOWN_RULE);
+ assertThat(mZenModeEventLogger.getIsUserAction(1)).isTrue();
+ assertThat(mZenModeEventLogger.getPackageUid(1)).isEqualTo(Process.SYSTEM_UID);
+ DNDPolicyProto dndProto = mZenModeEventLogger.getPolicyProto(1);
+ assertThat(dndProto.getAllowChannels().getNumber())
+ .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE);
+ }
+
+ @Test
public void testUpdateConsolidatedPolicy_defaultRulesOnly() {
setupZenConfig();
@@ -3416,6 +3547,7 @@
return rule;
}
+ // TODO: b/310620812 - Update setup methods to include allowChannels() when MODES_API is inlined
private void setupZenConfig() {
mZenModeHelper.mZenMode = ZEN_MODE_OFF;
mZenModeHelper.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index c3074bb..a8d3fa1 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -99,7 +99,7 @@
android:theme="@style/WhiteBackgroundTheme"
android:exported="true"/>
- <activity android:name="com.android.server.wm.TrustedPresentationCallbackTest$TestActivity"
+ <activity android:name="com.android.server.wm.TrustedPresentationListenerTest$TestActivity"
android:exported="true"
android:showWhenLocked="true"
android:turnScreenOn="true" />
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 f2e54bc..7aa46a6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3727,6 +3727,24 @@
verify(task).moveTaskToBack(any());
}
+ /**
+ * Verifies the {@link ActivityRecord#moveFocusableActivityToTop} returns {@code false} if
+ * there's a PIP task on top.
+ */
+ @Test
+ public void testMoveFocusableActivityToTop() {
+ // Create a Task
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord ar = createActivityRecord(task);
+
+ // Create a PIP Task on top
+ final Task pipTask = createTask(mDisplayContent);
+ doReturn(true).when(pipTask).inPinnedWindowingMode();
+
+ // Verifies that the Task is not moving-to-top.
+ assertFalse(ar.moveFocusableActivityToTop("test"));
+ }
+
private ICompatCameraControlCallback getCompatCameraControlCallback() {
return new ICompatCameraControlCallback.Stub() {
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index acce2e2..71d2504 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -2086,15 +2086,17 @@
@Test
public void testShellTransitRotation() {
- DisplayContent dc = createNewDisplay();
- dc.setLastHasContent();
+ final DisplayContent dc = mDisplayContent;
+ // Create 2 visible activities to verify that they can both receive the new configuration.
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ doReturn(true).when(activity1).isSyncFinished(any());
+ doReturn(true).when(activity2).isSyncFinished(any());
final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final DisplayRotation dr = dc.getDisplayRotation();
- doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
- // Rotate 180 degree so the display doesn't have configuration change. This condition is
- // used for the later verification of stop-freezing (without setting mWaitingForConfig).
- doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt());
+ spyOn(dr);
+ doReturn((dr.getRotation() + 1) % 4).when(dr).rotationForOrientation(anyInt(), anyInt());
mWm.mDisplayChangeController =
new IDisplayChangeWindowController.Stub() {
@Override
@@ -2109,11 +2111,8 @@
}
};
- // kill any existing rotation animation (vestigial from test setup).
- dc.setRotationAnimation(null);
-
final int origRot = dc.getConfiguration().windowConfiguration.getRotation();
-
+ dc.setLastHasContent();
mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
// Should create a transition request without performing rotation
assertNotNull(testPlayer.mLastRequest);
@@ -2122,6 +2121,10 @@
// Once transition starts, rotation is applied and transition shows DC rotating.
testPlayer.startTransition();
waitUntilHandlersIdle();
+ verify(activity1).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
+ anyBoolean());
+ verify(activity2).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
+ anyBoolean());
assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation());
assertNotNull(testPlayer.mLastReady);
assertTrue(testPlayer.mController.isPlaying());
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
index 3b9ed26..ef427bb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
@@ -137,7 +137,7 @@
wasVisible = waitForWindowVisible(mView2);
if (!wasVisible) {
- dumpWindowsOnScreen(TAG, "requestFocusWithMultipleWindows");
+ dumpWindowsOnScreen(TAG, "requestFocusWithMultipleWindows-not visible");
}
assertTrue("Failed to wait for view2", wasVisible);
@@ -145,11 +145,21 @@
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(window,
mScvh1.getInputTransferToken(), true);
- assertTrue("Failed to gain focus for view1", waitForWindowFocus(mView1, true));
+
+ boolean gainedFocus = waitForWindowFocus(mView1, true);
+ if (!gainedFocus) {
+ dumpWindowsOnScreen(TAG, "requestFocusWithMultipleWindows-view1 not focus");
+ }
+ assertTrue("Failed to gain focus for view1", gainedFocus);
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(window,
mScvh2.getInputTransferToken(), true);
- assertTrue("Failed to gain focus for view2", waitForWindowFocus(mView2, true));
+
+ gainedFocus = waitForWindowFocus(mView2, true);
+ if (!gainedFocus) {
+ dumpWindowsOnScreen(TAG, "requestFocusWithMultipleWindows-view2 not focus");
+ }
+ assertTrue("Failed to gain focus for view2", gainedFocus);
}
private static class TestWindowlessWindowManager extends WindowlessWindowManager {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 267bec9..c876663 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -40,6 +40,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -167,7 +168,7 @@
@Presubmit
public void testTaskDescriptionChanged() throws Exception {
final Object[] params = new Object[2];
- final CountDownLatch latch = new CountDownLatch(1);
+ final CountDownLatch latch = new CountDownLatch(2);
registerTaskStackChangedListener(new TaskStackListener() {
int mTaskId = -1;
@@ -510,6 +511,8 @@
protected void onPostResume() {
super.onPostResume();
setTaskDescription(new TaskDescription("Test Label"));
+ // Sets the color of the status-bar should update the TaskDescription again.
+ getWindow().setStatusBarColor(Color.RED);
synchronized (sLock) {
// Hold the lock to ensure no one is trying to access fields of this Activity in
// this test.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java b/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java
deleted file mode 100644
index c5dd447..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java
+++ /dev/null
@@ -1,154 +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.wm;
-
-import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
-import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Activity;
-import android.platform.test.annotations.Presubmit;
-import android.server.wm.CtsWindowInfoUtils;
-import android.view.SurfaceControl;
-import android.view.SurfaceControl.TrustedPresentationThresholds;
-
-import androidx.annotation.GuardedBy;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-
-import com.android.server.wm.utils.CommonUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-
-import java.util.function.Consumer;
-
-/**
- * TODO (b/287076178): Move these tests to
- * {@link android.view.surfacecontrol.cts.TrustedPresentationCallbackTest} when API is made public
- */
-@Presubmit
-public class TrustedPresentationCallbackTest {
- private static final String TAG = "TrustedPresentationCallbackTest";
- private static final int STABILITY_REQUIREMENT_MS = 500;
- private static final long WAIT_TIME_MS = HW_TIMEOUT_MULTIPLIER * 2000L;
-
- private static final float FRACTION_VISIBLE = 0.1f;
-
- private final Object mResultsLock = new Object();
- @GuardedBy("mResultsLock")
- private boolean mResult;
- @GuardedBy("mResultsLock")
- private boolean mReceivedResults;
-
- @Rule
- public TestName mName = new TestName();
-
- @Rule
- public ActivityScenarioRule<TestActivity> mActivityRule = createFullscreenActivityScenarioRule(
- TestActivity.class);
-
- private TestActivity mActivity;
-
- @Before
- public void setup() {
- mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
- }
-
- @After
- public void tearDown() {
- CommonUtils.waitUntilActivityRemoved(mActivity);
- }
-
- @Test
- public void testAddTrustedPresentationListenerOnWindow() throws InterruptedException {
- TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
- 1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
- Runnable::run, inTrustedPresentationState -> {
- synchronized (mResultsLock) {
- mResult = inTrustedPresentationState;
- mReceivedResults = true;
- mResultsLock.notify();
- }
- });
- t.apply();
- synchronized (mResultsLock) {
- assertResults();
- }
- }
-
- @Test
- public void testRemoveTrustedPresentationListenerOnWindow() throws InterruptedException {
- TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
- 1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
- Consumer<Boolean> trustedPresentationCallback = inTrustedPresentationState -> {
- synchronized (mResultsLock) {
- mResult = inTrustedPresentationState;
- mReceivedResults = true;
- mResultsLock.notify();
- }
- };
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
- Runnable::run, trustedPresentationCallback);
- t.apply();
-
- synchronized (mResultsLock) {
- if (!mReceivedResults) {
- mResultsLock.wait(WAIT_TIME_MS);
- }
- assertResults();
- // reset the state
- mReceivedResults = false;
- }
-
- mActivity.getWindow().getRootSurfaceControl().removeTrustedPresentationCallback(t,
- trustedPresentationCallback);
- t.apply();
-
- synchronized (mResultsLock) {
- if (!mReceivedResults) {
- mResultsLock.wait(WAIT_TIME_MS);
- }
- // Ensure we waited the full time and never received a notify on the result from the
- // callback.
- assertFalse("Should never have received a callback", mReceivedResults);
- // results shouldn't have changed.
- assertTrue(mResult);
- }
- }
-
- @GuardedBy("mResultsLock")
- private void assertResults() throws InterruptedException {
- mResultsLock.wait(WAIT_TIME_MS);
-
- if (!mReceivedResults) {
- CtsWindowInfoUtils.dumpWindowsOnScreen(TAG, "test " + mName.getMethodName());
- }
- // Make sure we received the results and not just timed out
- assertTrue("Timed out waiting for results", mReceivedResults);
- assertTrue(mResult);
- }
-
- public static class TestActivity extends Activity {
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationListenerTest.java
new file mode 100644
index 0000000..96b66bf
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationListenerTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.wm;
+
+import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
+import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.server.wm.CtsWindowInfoUtils;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowManager;
+import android.window.TrustedPresentationThresholds;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+
+import com.android.server.wm.utils.CommonUtils;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * TODO (b/287076178): Move these tests to
+ * {@link android.view.surfacecontrol.cts.TrustedPresentationListenerTest} when API is made public
+ */
+@Presubmit
+public class TrustedPresentationListenerTest {
+ private static final String TAG = "TrustedPresentationListenerTest";
+ private static final int STABILITY_REQUIREMENT_MS = 500;
+ private static final long WAIT_TIME_MS = HW_TIMEOUT_MULTIPLIER * 2000L;
+
+ private static final float FRACTION_VISIBLE = 0.1f;
+
+ private final List<Boolean> mResults = Collections.synchronizedList(new ArrayList<>());
+ private CountDownLatch mReceivedResults = new CountDownLatch(1);
+
+ private TrustedPresentationThresholds mThresholds = new TrustedPresentationThresholds(
+ 1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
+
+ @Rule
+ public TestName mName = new TestName();
+
+ @Rule
+ public ActivityScenarioRule<TestActivity> mActivityRule = createFullscreenActivityScenarioRule(
+ TestActivity.class);
+
+ private TestActivity mActivity;
+
+ private SurfaceControlViewHost.SurfacePackage mSurfacePackage = null;
+
+ @Before
+ public void setup() {
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ mDefaultListener = new Listener(mReceivedResults);
+ }
+
+ @After
+ public void tearDown() {
+ if (mSurfacePackage != null) {
+ new SurfaceControl.Transaction().remove(mSurfacePackage.getSurfaceControl()).apply(
+ true);
+ mSurfacePackage.release();
+ }
+ CommonUtils.waitUntilActivityRemoved(mActivity);
+
+ }
+
+ private class Listener implements Consumer<Boolean> {
+ final CountDownLatch mLatch;
+
+ Listener(CountDownLatch latch) {
+ mLatch = latch;
+ }
+
+ @Override
+ public void accept(Boolean inTrustedPresentationState) {
+ Log.d(TAG, "onTrustedPresentationChanged " + inTrustedPresentationState);
+ mResults.add(inTrustedPresentationState);
+ mLatch.countDown();
+ }
+ }
+
+ private Consumer<Boolean> mDefaultListener;
+
+ @Test
+ public void testAddTrustedPresentationListenerOnWindow() {
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+ windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds, Runnable::run,
+ mDefaultListener);
+ assertResults(List.of(true));
+ }
+
+ @Test
+ public void testRemoveTrustedPresentationListenerOnWindow() throws InterruptedException {
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+ windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds, Runnable::run,
+ mDefaultListener);
+ assertResults(List.of(true));
+ // reset the latch
+ mReceivedResults = new CountDownLatch(1);
+
+ windowManager.unregisterTrustedPresentationListener(mDefaultListener);
+ mReceivedResults.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ // Ensure we waited the full time and never received a notify on the result from the
+ // callback.
+ assertEquals("Should never have received a callback", mReceivedResults.getCount(), 1);
+ // results shouldn't have changed.
+ assertEquals(mResults, List.of(true));
+ }
+
+ @Test
+ public void testRemovingUnknownListenerIsANoop() {
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+ assertNotNull(windowManager);
+ windowManager.unregisterTrustedPresentationListener(mDefaultListener);
+ }
+
+ @Test
+ public void testAddDuplicateListenerThrowsException() {
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+ assertNotNull(windowManager);
+ windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds,
+ Runnable::run, mDefaultListener);
+ assertThrows(AndroidRuntimeException.class,
+ () -> windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds,
+ Runnable::run, mDefaultListener));
+ }
+
+ @Test
+ public void testAddDuplicateThresholds() {
+ mReceivedResults = new CountDownLatch(2);
+ mDefaultListener = new Listener(mReceivedResults);
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+ windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds,
+ Runnable::run, mDefaultListener);
+
+ Consumer<Boolean> mNewListener = new Listener(mReceivedResults);
+
+ windowManager.registerTrustedPresentationListener(
+ mActivity.getWindow().getDecorView().getWindowToken(), mThresholds,
+ Runnable::run, mNewListener);
+ assertResults(List.of(true, true));
+ }
+
+ private void waitForViewAttach(View view) {
+ final CountDownLatch viewAttached = new CountDownLatch(1);
+ view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(@NonNull View v) {
+ viewAttached.countDown();
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(@NonNull View v) {
+
+ }
+ });
+ try {
+ viewAttached.await(2000, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (!wait(viewAttached, 2000 /* waitTimeMs */)) {
+ fail("Couldn't attach view=" + view);
+ }
+ }
+
+ @Test
+ public void testAddListenerToScvh() {
+ WindowManager windowManager = mActivity.getSystemService(WindowManager.class);
+
+ var embeddedView = new View(mActivity);
+ mActivityRule.getScenario().onActivity(activity -> {
+ var attachedSurfaceControl =
+ mActivity.getWindow().getDecorView().getRootSurfaceControl();
+ var scvh = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
+ attachedSurfaceControl.getHostToken());
+ mSurfacePackage = scvh.getSurfacePackage();
+ scvh.setView(embeddedView, mActivity.getWindow().getDecorView().getWidth(),
+ mActivity.getWindow().getDecorView().getHeight());
+ attachedSurfaceControl.buildReparentTransaction(
+ mSurfacePackage.getSurfaceControl());
+ });
+
+ waitForViewAttach(embeddedView);
+ windowManager.registerTrustedPresentationListener(embeddedView.getWindowToken(),
+ mThresholds,
+ Runnable::run, mDefaultListener);
+
+ assertResults(List.of(true));
+ }
+
+ private boolean wait(CountDownLatch latch, long waitTimeMs) {
+ while (true) {
+ long now = SystemClock.uptimeMillis();
+ try {
+ return latch.await(waitTimeMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ long elapsedTime = SystemClock.uptimeMillis() - now;
+ waitTimeMs = Math.max(0, waitTimeMs - elapsedTime);
+ }
+ }
+
+ }
+
+ @GuardedBy("mResultsLock")
+ private void assertResults(List<Boolean> results) {
+ if (!wait(mReceivedResults, WAIT_TIME_MS)) {
+ try {
+ CtsWindowInfoUtils.dumpWindowsOnScreen(TAG, "test " + mName.getMethodName());
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Couldn't dump windows", e);
+ }
+ Assert.fail("Timed out waiting for results mReceivedResults.count="
+ + mReceivedResults.getCount() + "mReceivedResults=" + mReceivedResults);
+ }
+
+ // Make sure we received the results
+ assertEquals(results.toArray(), mResults.toArray());
+ }
+
+ public static class TestActivity extends Activity {
+ }
+}
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index ddec8fa..a487799 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -27,3 +27,16 @@
platform_apis: true,
test_suites: ["device-tests"],
}
+
+android_ravenwood_test {
+ name: "InternalTestsRavenwood",
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.test.rules",
+ "platform-test-annotations",
+ ],
+ srcs: [
+ "src/com/android/internal/util/ParcellingTests.java",
+ ],
+ auto_gen_config: true,
+}
diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS
index aa87958..90e1bed 100644
--- a/tests/NetworkSecurityConfigTest/OWNERS
+++ b/tests/NetworkSecurityConfigTest/OWNERS
@@ -1 +1,2 @@
include /services/core/java/com/android/server/net/OWNERS
+include /core/java/android/security/net/OWNERS
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 412aa9b..275a0e2 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -92,10 +92,6 @@
srcs: [
"compile/IdAssigner.cpp",
"compile/InlineXmlFormatParser.cpp",
- "compile/NinePatch.cpp",
- "compile/Png.cpp",
- "compile/PngChunkFilter.cpp",
- "compile/PngCrunch.cpp",
"compile/PseudolocaleGenerator.cpp",
"compile/Pseudolocalizer.cpp",
"compile/XmlIdCollector.cpp",
@@ -112,9 +108,7 @@
"format/binary/XmlFlattener.cpp",
"format/proto/ProtoDeserialize.cpp",
"format/proto/ProtoSerialize.cpp",
- "io/BigBufferStream.cpp",
"io/File.cpp",
- "io/FileStream.cpp",
"io/FileSystem.cpp",
"io/StringStream.cpp",
"io/Util.cpp",
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 6b1fd9f..d6502d8 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -18,12 +18,12 @@
#include "ResourceValues.h"
#include "ValueVisitor.h"
+#include "androidfw/BigBufferStream.h"
#include "format/Archive.h"
#include "format/binary/TableFlattener.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "format/proto/ProtoSerialize.h"
-#include "io/BigBufferStream.h"
#include "io/Util.h"
#include "xml/XmlDom.h"
@@ -48,7 +48,7 @@
}
// First try in proto format.
- std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream();
+ std::unique_ptr<android::InputStream> manifest_in = manifest_file->OpenInputStream();
if (manifest_in != nullptr) {
pb::XmlNode pb_node;
io::ProtoInputStreamReader proto_reader(manifest_in.get());
@@ -102,7 +102,7 @@
io::IFile* table_file = collection->FindFile(kProtoResourceTablePath);
if (table_file != nullptr) {
pb::ResourceTable pb_table;
- std::unique_ptr<io::InputStream> in = table_file->OpenInputStream();
+ std::unique_ptr<android::InputStream> in = table_file->OpenInputStream();
if (in == nullptr) {
diag->Error(android::DiagMessage(source) << "failed to open " << kProtoResourceTablePath);
return {};
@@ -129,7 +129,7 @@
return {};
}
- std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream();
+ std::unique_ptr<android::InputStream> manifest_in = manifest_file->OpenInputStream();
if (manifest_in == nullptr) {
diag->Error(android::DiagMessage(source) << "failed to open " << kAndroidManifestPath);
return {};
@@ -262,7 +262,7 @@
return false;
}
- io::BigBufferInputStream input_stream(&buffer);
+ android::BigBufferInputStream input_stream(&buffer);
if (!io::CopyInputStreamToArchive(context,
&input_stream,
path,
@@ -296,7 +296,7 @@
}
uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
- io::BigBufferInputStream manifest_buffer_in(&buffer);
+ android::BigBufferInputStream manifest_buffer_in(&buffer);
if (!io::CopyInputStreamToArchive(context, &manifest_buffer_in, path, compression_flags,
writer)) {
return false;
@@ -321,7 +321,7 @@
std::unique_ptr<xml::XmlResource> doc;
if (format_ == ApkFormat::kProto) {
- std::unique_ptr<io::InputStream> in = file->OpenInputStream();
+ std::unique_ptr<android::InputStream> in = file->OpenInputStream();
if (!in) {
diag->Error(android::DiagMessage() << "failed to open file");
return nullptr;
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index a0b4dab..b351d6e 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -27,6 +27,7 @@
#include "Diagnostics.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
+#include "androidfw/FileStream.h"
#include "androidfw/IDiagnostics.h"
#include "androidfw/StringPiece.h"
#include "cmd/ApkInfo.h"
@@ -37,7 +38,6 @@
#include "cmd/Dump.h"
#include "cmd/Link.h"
#include "cmd/Optimize.h"
-#include "io/FileStream.h"
#include "trace/TraceBuffer.h"
#include "util/Files.h"
#include "util/Util.h"
@@ -99,7 +99,7 @@
*/
class DaemonCommand : public Command {
public:
- explicit DaemonCommand(io::FileOutputStream* out, android::IDiagnostics* diagnostics)
+ explicit DaemonCommand(android::FileOutputStream* out, android::IDiagnostics* diagnostics)
: Command("daemon", "m"), out_(out), diagnostics_(diagnostics) {
SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
"command. The end of an invocation is signaled by providing an empty line.");
@@ -147,7 +147,7 @@
}
private:
- io::FileOutputStream* out_;
+ android::FileOutputStream* out_;
android::IDiagnostics* diagnostics_;
std::optional<std::string> trace_folder_;
};
@@ -167,7 +167,7 @@
// Use a smaller buffer so that there is less latency for printing to stdout.
constexpr size_t kStdOutBufferSize = 1024u;
- aapt::io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+ android::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
aapt::text::Printer printer(&fout);
aapt::StdErrDiagnostics diagnostics;
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 728ba8a..031dd5b 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -25,13 +25,16 @@
#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/utf8.h"
+#include "androidfw/BigBufferStream.h"
#include "androidfw/ConfigDescription.h"
+#include "androidfw/FileStream.h"
#include "androidfw/IDiagnostics.h"
+#include "androidfw/Image.h"
+#include "androidfw/Png.h"
#include "androidfw/StringPiece.h"
#include "cmd/Util.h"
#include "compile/IdAssigner.h"
#include "compile/InlineXmlFormatParser.h"
-#include "compile/Png.h"
#include "compile/PseudolocaleGenerator.h"
#include "compile/XmlIdCollector.h"
#include "format/Archive.h"
@@ -39,8 +42,6 @@
#include "format/proto/ProtoSerialize.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
-#include "io/BigBufferStream.h"
-#include "io/FileStream.h"
#include "io/FileSystem.h"
#include "io/StringStream.h"
#include "io/Util.h"
@@ -52,9 +53,9 @@
#include "xml/XmlDom.h"
#include "xml/XmlPullParser.h"
-using ::aapt::io::FileInputStream;
using ::aapt::text::Printer;
using ::android::ConfigDescription;
+using ::android::FileInputStream;
using ::android::StringPiece;
using ::android::base::SystemErrorCodeToString;
using ::google::protobuf::io::CopyingOutputStreamAdaptor;
@@ -241,7 +242,7 @@
}
if (options.generate_text_symbols_path) {
- io::FileOutputStream fout_text(options.generate_text_symbols_path.value());
+ android::FileOutputStream fout_text(options.generate_text_symbols_path.value());
if (fout_text.HadError()) {
context->GetDiagnostics()->Error(android::DiagMessage()
@@ -307,7 +308,7 @@
}
static bool WriteHeaderAndDataToWriter(StringPiece output_path, const ResourceFile& file,
- io::KnownSizeInputStream* in, IArchiveWriter* writer,
+ android::KnownSizeInputStream* in, IArchiveWriter* writer,
android::IDiagnostics* diag) {
TRACE_CALL();
// Start the entry so we can write the header.
@@ -448,7 +449,7 @@
}
if (options.generate_text_symbols_path) {
- io::FileOutputStream fout_text(options.generate_text_symbols_path.value());
+ android::FileOutputStream fout_text(options.generate_text_symbols_path.value());
if (fout_text.HadError()) {
context->GetDiagnostics()->Error(android::DiagMessage()
@@ -498,21 +499,22 @@
}
android::BigBuffer crunched_png_buffer(4096);
- io::BigBufferOutputStream crunched_png_buffer_out(&crunched_png_buffer);
+ android::BigBufferOutputStream crunched_png_buffer_out(&crunched_png_buffer);
// Ensure that we only keep the chunks we care about if we end up
// using the original PNG instead of the crunched one.
const StringPiece content(reinterpret_cast<const char*>(data->data()), data->size());
- PngChunkFilter png_chunk_filter(content);
- std::unique_ptr<Image> image = ReadPng(context, path_data.source, &png_chunk_filter);
+ android::PngChunkFilter png_chunk_filter(content);
+ android::SourcePathDiagnostics source_diag(path_data.source, context->GetDiagnostics());
+ auto image = android::ReadPng(&png_chunk_filter, &source_diag);
if (!image) {
return false;
}
- std::unique_ptr<NinePatch> nine_patch;
+ std::unique_ptr<android::NinePatch> nine_patch;
if (path_data.extension == "9.png") {
std::string err;
- nine_patch = NinePatch::Create(image->rows.get(), image->width, image->height, &err);
+ nine_patch = android::NinePatch::Create(image->rows.get(), image->width, image->height, &err);
if (!nine_patch) {
context->GetDiagnostics()->Error(android::DiagMessage() << err);
return false;
@@ -537,7 +539,8 @@
}
// Write the crunched PNG.
- if (!WritePng(context, image.get(), nine_patch.get(), &crunched_png_buffer_out, {})) {
+ if (!android::WritePng(image.get(), nine_patch.get(), &crunched_png_buffer_out, {},
+ &source_diag, context->IsVerbose())) {
return false;
}
@@ -557,7 +560,7 @@
png_chunk_filter.Rewind();
android::BigBuffer filtered_png_buffer(4096);
- io::BigBufferOutputStream filtered_png_buffer_out(&filtered_png_buffer);
+ android::BigBufferOutputStream filtered_png_buffer_out(&filtered_png_buffer);
io::Copy(&filtered_png_buffer_out, &png_chunk_filter);
buffer.AppendBuffer(std::move(filtered_png_buffer));
}
@@ -567,7 +570,7 @@
// This will help catch exotic cases where the new code may generate larger PNGs.
std::stringstream legacy_stream{std::string(content)};
android::BigBuffer legacy_buffer(4096);
- Png png(context->GetDiagnostics());
+ android::Png png(context->GetDiagnostics());
if (!png.process(path_data.source, &legacy_stream, &legacy_buffer, {})) {
return false;
}
@@ -578,7 +581,7 @@
}
}
- io::BigBufferInputStream buffer_in(&buffer);
+ android::BigBufferInputStream buffer_in(&buffer);
return WriteHeaderAndDataToWriter(output_path, res_file, &buffer_in, writer,
context->GetDiagnostics());
}
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 8880089..9337cb9 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -341,7 +341,7 @@
// Check resources.pb contains relative sources.
io::IFile* proto_file =
apk.get()->GetFileCollection()->FindFile("resources.pb");
- std::unique_ptr<io::InputStream> proto_stream = proto_file->OpenInputStream();
+ std::unique_ptr<android::InputStream> proto_stream = proto_file->OpenInputStream();
io::ProtoInputStreamReader proto_reader(proto_stream.get());
pb::ResourceTable pb_table;
proto_reader.ReadMessage(&pb_table);
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 387dcfe..c132792 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -24,13 +24,13 @@
#include "android-base/file.h"
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
+#include "androidfw/BigBufferStream.h"
#include "androidfw/StringPiece.h"
#include "cmd/Util.h"
#include "format/binary/TableFlattener.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "format/proto/ProtoSerialize.h"
-#include "io/BigBufferStream.h"
#include "io/Util.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
@@ -80,7 +80,7 @@
return false;
}
- io::BigBufferInputStream input_stream(&buffer);
+ android::BigBufferInputStream input_stream(&buffer);
return io::CopyInputStreamToArchive(context_, &input_stream, path, compression_flags, writer);
}
@@ -91,14 +91,14 @@
return false;
}
- io::BigBufferInputStream input_stream(&buffer);
+ android::BigBufferInputStream input_stream(&buffer);
return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath,
ArchiveEntry::kAlign, writer);
}
bool SerializeFile(FileReference* file, IArchiveWriter* writer) override {
if (file->type == ResourceFile::Type::kProtoXml) {
- unique_ptr<io::InputStream> in = file->file->OpenInputStream();
+ unique_ptr<android::InputStream> in = file->file->OpenInputStream();
if (in == nullptr) {
context_->GetDiagnostics()->Error(android::DiagMessage(source_)
<< "failed to open file " << *file->path);
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index 864af06..6fa9ecb 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -19,19 +19,18 @@
#include <cinttypes>
#include <vector>
-#include "android-base/stringprintf.h"
-#include "androidfw/ConfigDescription.h"
-#include "androidfw/StringPiece.h"
-
#include "Debug.h"
#include "Diagnostics.h"
#include "LoadedApk.h"
#include "Util.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/ConfigDescription.h"
+#include "androidfw/FileStream.h"
+#include "androidfw/StringPiece.h"
#include "format/Container.h"
#include "format/binary/BinaryResourceParser.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
-#include "io/FileStream.h"
#include "io/ZipArchive.h"
#include "process/IResourceTableConsumer.h"
#include "text/Printer.h"
@@ -145,7 +144,7 @@
bool error = false;
for (auto container : args) {
- io::FileInputStream input(container);
+ android::FileInputStream input(container);
if (input.HadError()) {
context.GetDiagnostics()->Error(android::DiagMessage(container)
<< "failed to open file: " << input.GetError());
diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h
index 76d33d7..119a59b 100644
--- a/tools/aapt2/cmd/Dump.h
+++ b/tools/aapt2/cmd/Dump.h
@@ -17,7 +17,7 @@
#ifndef AAPT2_DUMP_H
#define AAPT2_DUMP_H
-#include <io/FileStream.h>
+#include <androidfw/FileStream.h>
#include <io/ZipArchive.h>
#include "Command.h"
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index c638873..9ca546f 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -35,6 +35,8 @@
#include "android-base/expected.h"
#include "android-base/file.h"
#include "android-base/stringprintf.h"
+#include "androidfw/BigBufferStream.h"
+#include "androidfw/FileStream.h"
#include "androidfw/IDiagnostics.h"
#include "androidfw/Locale.h"
#include "androidfw/StringPiece.h"
@@ -48,8 +50,6 @@
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "format/proto/ProtoSerialize.h"
-#include "io/BigBufferStream.h"
-#include "io/FileStream.h"
#include "io/FileSystem.h"
#include "io/Util.h"
#include "io/ZipArchive.h"
@@ -73,8 +73,8 @@
#include "util/Files.h"
#include "xml/XmlDom.h"
-using ::aapt::io::FileInputStream;
using ::android::ConfigDescription;
+using ::android::FileInputStream;
using ::android::StringPiece;
using ::android::base::expected;
using ::android::base::StringPrintf;
@@ -263,7 +263,7 @@
return false;
}
- io::BigBufferInputStream input_stream(&buffer);
+ android::BigBufferInputStream input_stream(&buffer);
return io::CopyInputStreamToArchive(context, &input_stream, path, ArchiveEntry::kCompress,
writer);
} break;
@@ -284,7 +284,7 @@
static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path,
android::IDiagnostics* diag) {
TRACE_CALL();
- FileInputStream fin(path);
+ android::FileInputStream fin(path);
if (fin.HadError()) {
diag->Error(android::DiagMessage(path) << "failed to load XML file: " << fin.GetError());
return {};
@@ -687,7 +687,7 @@
static bool WriteStableIdMapToPath(android::IDiagnostics* diag,
const std::unordered_map<ResourceName, ResourceId>& id_map,
const std::string& id_map_path) {
- io::FileOutputStream fout(id_map_path);
+ android::FileOutputStream fout(id_map_path);
if (fout.HadError()) {
diag->Error(android::DiagMessage(id_map_path) << "failed to open: " << fout.GetError());
return false;
@@ -1197,7 +1197,7 @@
return false;
}
- io::BigBufferInputStream input_stream(&buffer);
+ android::BigBufferInputStream input_stream(&buffer);
return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath,
ArchiveEntry::kAlign, writer);
} break;
@@ -1221,7 +1221,7 @@
}
std::string out_path;
- std::unique_ptr<io::FileOutputStream> fout;
+ std::unique_ptr<android::FileOutputStream> fout;
if (options_.generate_java_class_path) {
out_path = options_.generate_java_class_path.value();
file::AppendPath(&out_path, file::PackageToPath(out_package));
@@ -1233,7 +1233,7 @@
file::AppendPath(&out_path, "R.java");
- fout = util::make_unique<io::FileOutputStream>(out_path);
+ fout = util::make_unique<android::FileOutputStream>(out_path);
if (fout->HadError()) {
context_->GetDiagnostics()->Error(android::DiagMessage()
<< "failed writing to '" << out_path
@@ -1242,9 +1242,9 @@
}
}
- std::unique_ptr<io::FileOutputStream> fout_text;
+ std::unique_ptr<android::FileOutputStream> fout_text;
if (out_text_symbols_path) {
- fout_text = util::make_unique<io::FileOutputStream>(out_text_symbols_path.value());
+ fout_text = util::make_unique<android::FileOutputStream>(out_text_symbols_path.value());
if (fout_text->HadError()) {
context_->GetDiagnostics()->Error(android::DiagMessage()
<< "failed writing to '" << out_text_symbols_path.value()
@@ -1386,7 +1386,7 @@
file::AppendPath(&out_path, "Manifest.java");
- io::FileOutputStream fout(out_path);
+ android::FileOutputStream fout(out_path);
if (fout.HadError()) {
context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to open '" << out_path
<< "': " << fout.GetError());
@@ -1412,7 +1412,7 @@
}
const std::string& out_path = out.value();
- io::FileOutputStream fout(out_path);
+ android::FileOutputStream fout(out_path);
if (fout.HadError()) {
context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to open '" << out_path
<< "': " << fout.GetError());
@@ -1601,7 +1601,7 @@
}
}
- std::unique_ptr<io::InputStream> input_stream = file->OpenInputStream();
+ std::unique_ptr<android::InputStream> input_stream = file->OpenInputStream();
if (input_stream == nullptr) {
context_->GetDiagnostics()->Error(android::DiagMessage(src) << "failed to open file");
return false;
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index f045dad..762441e 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -30,6 +30,7 @@
#include "ValueVisitor.h"
#include "android-base/file.h"
#include "android-base/stringprintf.h"
+#include "androidfw/BigBufferStream.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/IDiagnostics.h"
#include "androidfw/ResourceTypes.h"
@@ -39,7 +40,6 @@
#include "filter/AbiFilter.h"
#include "format/binary/TableFlattener.h"
#include "format/binary/XmlFlattener.h"
-#include "io/BigBufferStream.h"
#include "io/Util.h"
#include "optimize/MultiApkGenerator.h"
#include "optimize/Obfuscator.h"
@@ -249,7 +249,7 @@
return false;
}
- io::BigBufferInputStream manifest_buffer_in(&manifest_buffer);
+ android::BigBufferInputStream manifest_buffer_in(&manifest_buffer);
if (!io::CopyInputStreamToArchive(context_, &manifest_buffer_in, "AndroidManifest.xml",
ArchiveEntry::kCompress, writer)) {
return false;
@@ -297,7 +297,7 @@
return false;
}
- io::BigBufferInputStream table_buffer_in(&table_buffer);
+ android::BigBufferInputStream table_buffer_in(&table_buffer);
return io::CopyInputStreamToArchive(context_, &table_buffer_in, "resources.arsc",
ArchiveEntry::kAlign, writer);
}
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index a2b4818..a596229 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -29,8 +29,8 @@
#include "SdkConstants.h"
#include "ValueVisitor.h"
#include "androidfw/ConfigDescription.h"
+#include "androidfw/FileStream.h"
#include "io/File.h"
-#include "io/FileStream.h"
#include "process/IResourceTableConsumer.h"
#include "xml/XmlDom.h"
diff --git a/tools/aapt2/format/Archive.cpp b/tools/aapt2/format/Archive.cpp
index e9a93d8..91768a0 100644
--- a/tools/aapt2/format/Archive.cpp
+++ b/tools/aapt2/format/Archive.cpp
@@ -91,7 +91,7 @@
return true;
}
- bool WriteFile(StringPiece path, uint32_t flags, io::InputStream* in) override {
+ bool WriteFile(StringPiece path, uint32_t flags, android::InputStream* in) override {
if (!StartEntry(path, flags)) {
return false;
}
@@ -182,7 +182,7 @@
return true;
}
- bool WriteFile(StringPiece path, uint32_t flags, io::InputStream* in) override {
+ bool WriteFile(StringPiece path, uint32_t flags, android::InputStream* in) override {
while (true) {
if (!StartEntry(path, flags)) {
return false;
diff --git a/tools/aapt2/format/Archive.h b/tools/aapt2/format/Archive.h
index 6cde753..3c3d0ab 100644
--- a/tools/aapt2/format/Archive.h
+++ b/tools/aapt2/format/Archive.h
@@ -24,9 +24,9 @@
#include "androidfw/BigBuffer.h"
#include "androidfw/IDiagnostics.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
-#include "io/Io.h"
#include "util/Files.h"
namespace aapt {
@@ -46,7 +46,7 @@
public:
virtual ~IArchiveWriter() = default;
- virtual bool WriteFile(android::StringPiece path, uint32_t flags, io::InputStream* in) = 0;
+ virtual bool WriteFile(android::StringPiece path, uint32_t flags, android::InputStream* in) = 0;
// Starts a new entry and allows caller to write bytes to it sequentially.
// Only use StartEntry if code you do not control needs to write to a CopyingOutputStream.
diff --git a/tools/aapt2/format/Archive_test.cpp b/tools/aapt2/format/Archive_test.cpp
index fd50af9..df105f8 100644
--- a/tools/aapt2/format/Archive_test.cpp
+++ b/tools/aapt2/format/Archive_test.cpp
@@ -95,7 +95,7 @@
void VerifyZipFile(const std::string& output_path, const std::string& file, const uint8_t array[]) {
std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(output_path, nullptr);
- std::unique_ptr<io::InputStream> stream = zip->FindFile(file)->OpenInputStream();
+ std::unique_ptr<android::InputStream> stream = zip->FindFile(file)->OpenInputStream();
std::vector<uint8_t> buffer;
const void* data;
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index 1ff6c49..cb4a225 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -94,7 +94,7 @@
}
bool ContainerWriter::AddResFileEntry(const pb::internal::CompiledFile& file,
- io::KnownSizeInputStream* in) {
+ android::KnownSizeInputStream* in) {
if (current_entry_count_ >= total_entry_count_) {
error_ = "too many entries being serialized";
return false;
@@ -264,7 +264,7 @@
return reader_->GetError();
}
-ContainerReader::ContainerReader(io::InputStream* in)
+ContainerReader::ContainerReader(android::InputStream* in)
: in_(in),
adaptor_(in),
coded_in_(&adaptor_),
diff --git a/tools/aapt2/format/Container.h b/tools/aapt2/format/Container.h
index 121c592..c5d5676 100644
--- a/tools/aapt2/format/Container.h
+++ b/tools/aapt2/format/Container.h
@@ -22,9 +22,9 @@
#include "Resources.pb.h"
#include "ResourcesInternal.pb.h"
#include "androidfw/BigBuffer.h"
+#include "androidfw/Streams.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream.h"
-#include "io/Io.h"
#include "io/Util.h"
namespace aapt {
@@ -39,7 +39,7 @@
explicit ContainerWriter(::google::protobuf::io::ZeroCopyOutputStream* out, size_t entry_count);
bool AddResTableEntry(const pb::ResourceTable& table);
- bool AddResFileEntry(const pb::internal::CompiledFile& file, io::KnownSizeInputStream* in);
+ bool AddResFileEntry(const pb::internal::CompiledFile& file, android::KnownSizeInputStream* in);
bool HadError() const;
std::string GetError() const;
@@ -79,7 +79,7 @@
class ContainerReader {
public:
- explicit ContainerReader(io::InputStream* in);
+ explicit ContainerReader(android::InputStream* in);
ContainerReaderEntry* Next();
@@ -91,7 +91,7 @@
friend class ContainerReaderEntry;
- io::InputStream* in_;
+ android::InputStream* in_;
io::ZeroCopyInputAdaptor adaptor_;
::google::protobuf::io::CodedInputStream coded_in_;
size_t total_entry_count_;
diff --git a/tools/aapt2/io/Data.h b/tools/aapt2/io/Data.h
index db91a77..29f523a 100644
--- a/tools/aapt2/io/Data.h
+++ b/tools/aapt2/io/Data.h
@@ -20,15 +20,14 @@
#include <memory>
#include "android-base/macros.h"
+#include "androidfw/Streams.h"
#include "utils/FileMap.h"
-#include "io/Io.h"
-
namespace aapt {
namespace io {
// Interface for a block of contiguous memory. An instance of this interface owns the data.
-class IData : public KnownSizeInputStream {
+class IData : public android::KnownSizeInputStream {
public:
virtual ~IData() = default;
diff --git a/tools/aapt2/io/File.cpp b/tools/aapt2/io/File.cpp
index b4f1ff3..4dfdb5b 100644
--- a/tools/aapt2/io/File.cpp
+++ b/tools/aapt2/io/File.cpp
@@ -39,7 +39,7 @@
return {};
}
-std::unique_ptr<io::InputStream> FileSegment::OpenInputStream() {
+std::unique_ptr<android::InputStream> FileSegment::OpenInputStream() {
return OpenAsData();
}
diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h
index 673d1b7..248756b 100644
--- a/tools/aapt2/io/File.h
+++ b/tools/aapt2/io/File.h
@@ -43,7 +43,7 @@
// Returns nullptr on failure.
virtual std::unique_ptr<IData> OpenAsData() = 0;
- virtual std::unique_ptr<io::InputStream> OpenInputStream() = 0;
+ virtual std::unique_ptr<android::InputStream> OpenInputStream() = 0;
// Returns the source of this file. This is for presentation to the user and
// may not be a valid file system path (for example, it may contain a '@' sign to separate
@@ -78,7 +78,7 @@
: file_(file), offset_(offset), len_(len) {}
std::unique_ptr<IData> OpenAsData() override;
- std::unique_ptr<io::InputStream> OpenInputStream() override;
+ std::unique_ptr<android::InputStream> OpenInputStream() override;
const android::Source& GetSource() const override {
return file_->GetSource();
diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp
index 6a692e4..03fabcc 100644
--- a/tools/aapt2/io/FileSystem.cpp
+++ b/tools/aapt2/io/FileSystem.cpp
@@ -22,9 +22,9 @@
#include <sys/stat.h>
#include "android-base/errors.h"
+#include "androidfw/FileStream.h"
#include "androidfw/Source.h"
#include "androidfw/StringPiece.h"
-#include "io/FileStream.h"
#include "util/Files.h"
#include "util/Util.h"
#include "utils/FileMap.h"
@@ -49,8 +49,8 @@
return {};
}
-std::unique_ptr<io::InputStream> RegularFile::OpenInputStream() {
- return util::make_unique<FileInputStream>(source_.path);
+std::unique_ptr<android::InputStream> RegularFile::OpenInputStream() {
+ return util::make_unique<android::FileInputStream>(source_.path);
}
const android::Source& RegularFile::GetSource() const {
diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h
index f975196..d6ecfeb 100644
--- a/tools/aapt2/io/FileSystem.h
+++ b/tools/aapt2/io/FileSystem.h
@@ -30,7 +30,7 @@
explicit RegularFile(const android::Source& source);
std::unique_ptr<IData> OpenAsData() override;
- std::unique_ptr<io::InputStream> OpenInputStream() override;
+ std::unique_ptr<android::InputStream> OpenInputStream() override;
const android::Source& GetSource() const override;
bool GetModificationTime(struct tm* buf) const override;
diff --git a/tools/aapt2/io/StringStream.cpp b/tools/aapt2/io/StringStream.cpp
index 9c49788..bb3911b 100644
--- a/tools/aapt2/io/StringStream.cpp
+++ b/tools/aapt2/io/StringStream.cpp
@@ -51,6 +51,23 @@
return str_.size();
}
+bool StringInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
+ if (byte_count == 0) {
+ return true;
+ }
+ if (offset < 0) {
+ return false;
+ }
+ if (offset > std::numeric_limits<off64_t>::max() - byte_count) {
+ return false;
+ }
+ if (offset + byte_count > str_.size()) {
+ return false;
+ }
+ memcpy(data, str_.data() + offset, byte_count);
+ return true;
+}
+
StringOutputStream::StringOutputStream(std::string* str, size_t buffer_capacity)
: str_(str),
buffer_capacity_(buffer_capacity),
diff --git a/tools/aapt2/io/StringStream.h b/tools/aapt2/io/StringStream.h
index f7bdecca..7e1abe5 100644
--- a/tools/aapt2/io/StringStream.h
+++ b/tools/aapt2/io/StringStream.h
@@ -17,17 +17,16 @@
#ifndef AAPT_IO_STRINGSTREAM_H
#define AAPT_IO_STRINGSTREAM_H
-#include "io/Io.h"
-
#include <memory>
#include "android-base/macros.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
namespace aapt {
namespace io {
-class StringInputStream : public KnownSizeInputStream {
+class StringInputStream : public android::KnownSizeInputStream {
public:
explicit StringInputStream(android::StringPiece str);
@@ -47,6 +46,8 @@
size_t TotalSize() const override;
+ bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(StringInputStream);
@@ -54,7 +55,7 @@
size_t offset_;
};
-class StringOutputStream : public OutputStream {
+class StringOutputStream : public android::OutputStream {
public:
explicit StringOutputStream(std::string* str, size_t buffer_capacity = 4096u);
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
index 79d8d52..9616e47 100644
--- a/tools/aapt2/io/Util.cpp
+++ b/tools/aapt2/io/Util.cpp
@@ -26,8 +26,9 @@
namespace aapt {
namespace io {
-bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, std::string_view out_path,
- uint32_t compression_flags, IArchiveWriter* writer) {
+bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in,
+ std::string_view out_path, uint32_t compression_flags,
+ IArchiveWriter* writer) {
TRACE_CALL();
if (context->IsVerbose()) {
context->GetDiagnostics()->Note(android::DiagMessage()
@@ -91,7 +92,7 @@
return false;
}
-bool Copy(OutputStream* out, InputStream* in) {
+bool Copy(android::OutputStream* out, android::InputStream* in) {
TRACE_CALL();
const void* in_buffer;
size_t in_len;
@@ -110,7 +111,7 @@
return !in->HadError();
}
-bool Copy(OutputStream* out, StringPiece in) {
+bool Copy(android::OutputStream* out, StringPiece in) {
const char* in_buffer = in.data();
size_t in_len = in.size();
while (in_len != 0) {
@@ -129,7 +130,7 @@
return true;
}
-bool Copy(ZeroCopyOutputStream* out, InputStream* in) {
+bool Copy(ZeroCopyOutputStream* out, android::InputStream* in) {
OutputStreamAdaptor adaptor(out);
return Copy(&adaptor, in);
}
diff --git a/tools/aapt2/io/Util.h b/tools/aapt2/io/Util.h
index 685f522..25aa8f8 100644
--- a/tools/aapt2/io/Util.h
+++ b/tools/aapt2/io/Util.h
@@ -19,18 +19,19 @@
#include <string_view>
+#include "androidfw/Streams.h"
#include "format/Archive.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/message.h"
#include "io/File.h"
-#include "io/Io.h"
#include "process/IResourceTableConsumer.h"
namespace aapt {
namespace io {
-bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, std::string_view out_path,
- uint32_t compression_flags, IArchiveWriter* writer);
+bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in,
+ std::string_view out_path, uint32_t compression_flags,
+ IArchiveWriter* writer);
bool CopyFileToArchive(IAaptContext* context, IFile* file, std::string_view out_path,
uint32_t compression_flags, IArchiveWriter* writer);
@@ -44,11 +45,11 @@
// Copies the data from in to out. Returns false if there was an error.
// If there was an error, check the individual streams' HadError/GetError methods.
-bool Copy(OutputStream* out, InputStream* in);
-bool Copy(OutputStream* out, android::StringPiece in);
-bool Copy(::google::protobuf::io::ZeroCopyOutputStream* out, InputStream* in);
+bool Copy(android::OutputStream* out, android::InputStream* in);
+bool Copy(android::OutputStream* out, android::StringPiece in);
+bool Copy(::google::protobuf::io::ZeroCopyOutputStream* out, android::InputStream* in);
-class OutputStreamAdaptor : public io::OutputStream {
+class OutputStreamAdaptor : public android::OutputStream {
public:
explicit OutputStreamAdaptor(::google::protobuf::io::ZeroCopyOutputStream* out) : out_(out) {
}
@@ -84,7 +85,7 @@
class ZeroCopyInputAdaptor : public ::google::protobuf::io::ZeroCopyInputStream {
public:
- explicit ZeroCopyInputAdaptor(io::InputStream* in) : in_(in) {
+ explicit ZeroCopyInputAdaptor(android::InputStream* in) : in_(in) {
}
bool Next(const void** data, int* size) override {
@@ -119,12 +120,13 @@
private:
DISALLOW_COPY_AND_ASSIGN(ZeroCopyInputAdaptor);
- io::InputStream* in_;
+ android::InputStream* in_;
};
class ProtoInputStreamReader {
public:
- explicit ProtoInputStreamReader(io::InputStream* in) : in_(in) { }
+ explicit ProtoInputStreamReader(android::InputStream* in) : in_(in) {
+ }
/** Deserializes a Message proto from the current position in the input stream.*/
template <typename T> bool ReadMessage(T *message) {
@@ -135,7 +137,7 @@
}
private:
- io::InputStream* in_;
+ android::InputStream* in_;
};
} // namespace io
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index cb5bbe9..e44d61e 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -63,7 +63,7 @@
}
}
-std::unique_ptr<io::InputStream> ZipFile::OpenInputStream() {
+std::unique_ptr<android::InputStream> ZipFile::OpenInputStream() {
return OpenAsData();
}
diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h
index ac125d0..a53c4a2 100644
--- a/tools/aapt2/io/ZipArchive.h
+++ b/tools/aapt2/io/ZipArchive.h
@@ -35,7 +35,7 @@
ZipFile(::ZipArchiveHandle handle, const ::ZipEntry& entry, const android::Source& source);
std::unique_ptr<IData> OpenAsData() override;
- std::unique_ptr<io::InputStream> OpenInputStream() override;
+ std::unique_ptr<android::InputStream> OpenInputStream() override;
const android::Source& GetSource() const override;
bool WasCompressed() override;
bool GetModificationTime(struct tm* buf) const override;
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index 98f3bd2..db7aa35 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -111,7 +111,7 @@
" */\n\n";
void ClassDefinition::WriteJavaFile(const ClassDefinition* def, StringPiece package, bool final,
- bool strip_api_annotations, io::OutputStream* out) {
+ bool strip_api_annotations, android::OutputStream* out) {
Printer printer(out);
printer.Print(sWarningHeader).Print("package ").Print(package).Println(";");
printer.Println();
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index 63c9982..84e3f33 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -241,7 +241,7 @@
class ClassDefinition : public ClassMember {
public:
static void WriteJavaFile(const ClassDefinition* def, android::StringPiece package, bool final,
- bool strip_api_annotations, io::OutputStream* out);
+ bool strip_api_annotations, android::OutputStream* out);
ClassDefinition(android::StringPiece name, ClassQualifier qualifier, bool createIfEmpty)
: name_(name), qualifier_(qualifier), create_if_empty_(createIfEmpty) {
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 7665d0e..58f6564 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -37,8 +37,8 @@
#include "java/ClassDefinition.h"
#include "process/SymbolTable.h"
-using ::aapt::io::OutputStream;
using ::aapt::text::Printer;
+using ::android::OutputStream;
using ::android::StringPiece;
using ::android::base::StringPrintf;
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 234df04..9909eec 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -19,11 +19,10 @@
#include <string>
-#include "androidfw/StringPiece.h"
-
#include "ResourceTable.h"
#include "ResourceValues.h"
-#include "io/Io.h"
+#include "androidfw/Streams.h"
+#include "androidfw/StringPiece.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
#include "text/Printer.h"
@@ -70,12 +69,12 @@
// All symbols technically belong to a single package, but linked libraries will
// have their names mangled, denoting that they came from a different package.
// We need to generate these symbols in a separate file. Returns true on success.
- bool Generate(android::StringPiece package_name_to_generate, io::OutputStream* out,
- io::OutputStream* out_r_txt = nullptr);
+ bool Generate(android::StringPiece package_name_to_generate, android::OutputStream* out,
+ android::OutputStream* out_r_txt = nullptr);
bool Generate(android::StringPiece package_name_to_generate,
- android::StringPiece output_package_name, io::OutputStream* out,
- io::OutputStream* out_r_txt = nullptr);
+ android::StringPiece output_package_name, android::OutputStream* out,
+ android::OutputStream* out_r_txt = nullptr);
const std::string& GetError() const;
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 80a46d5..aef48fc 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -29,8 +29,8 @@
#include "util/Util.h"
#include "xml/XmlDom.h"
-using ::aapt::io::OutputStream;
using ::aapt::text::Printer;
+using ::android::OutputStream;
namespace aapt {
namespace proguard {
diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index 267f7ed..876ef48 100644
--- a/tools/aapt2/java/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
@@ -26,8 +26,8 @@
#include "ResourceTable.h"
#include "ValueVisitor.h"
#include "androidfw/Source.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
-#include "io/Io.h"
#include "process/IResourceTableConsumer.h"
#include "xml/XmlDom.h"
@@ -69,7 +69,7 @@
}
private:
- friend void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out, bool minimal_keep,
+ friend void WriteKeepSet(const KeepSet& keep_set, android::OutputStream* out, bool minimal_keep,
bool no_location_reference);
friend bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
@@ -89,7 +89,7 @@
bool CollectResourceReferences(IAaptContext* context, ResourceTable* table, KeepSet* keep_set);
-void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out, bool minimal_keep,
+void WriteKeepSet(const KeepSet& keep_set, android::OutputStream* out, bool minimal_keep,
bool no_location_reference);
bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index e48668c..0437980 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -90,7 +90,7 @@
return {};
}
- std::unique_ptr<io::InputStream> OpenInputStream() override {
+ std::unique_ptr<android::InputStream> OpenInputStream() override {
return OpenAsData();
}
diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp
index 428372f..b91abe5 100644
--- a/tools/aapt2/test/Fixture.cpp
+++ b/tools/aapt2/test/Fixture.cpp
@@ -20,6 +20,7 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/utf8.h>
+#include <androidfw/FileStream.h>
#include <androidfw/StringPiece.h>
#include <dirent.h>
#include <gmock/gmock.h>
@@ -28,7 +29,6 @@
#include "Diagnostics.h"
#include "cmd/Compile.h"
#include "cmd/Link.h"
-#include "io/FileStream.h"
#include "util/Files.h"
using testing::Eq;
diff --git a/tools/aapt2/text/Printer.cpp b/tools/aapt2/text/Printer.cpp
index 8e491ac..c2fa8cc 100644
--- a/tools/aapt2/text/Printer.cpp
+++ b/tools/aapt2/text/Printer.cpp
@@ -20,7 +20,7 @@
#include "io/Util.h"
-using ::aapt::io::OutputStream;
+using ::android::OutputStream;
using ::android::StringPiece;
namespace aapt {
diff --git a/tools/aapt2/text/Printer.h b/tools/aapt2/text/Printer.h
index f7ad98b..44f0fc5 100644
--- a/tools/aapt2/text/Printer.h
+++ b/tools/aapt2/text/Printer.h
@@ -18,17 +18,16 @@
#define AAPT_TEXT_PRINTER_H
#include "android-base/macros.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
-#include "io/Io.h"
-
namespace aapt {
namespace text {
// An indenting Printer that helps write formatted text to the OutputStream.
class Printer {
public:
- explicit Printer(::aapt::io::OutputStream* out) : out_(out) {
+ explicit Printer(android::OutputStream* out) : out_(out) {
}
Printer& Print(android::StringPiece str);
@@ -41,7 +40,7 @@
private:
DISALLOW_COPY_AND_ASSIGN(Printer);
- ::aapt::io::OutputStream* out_;
+ android::OutputStream* out_;
int indent_level_ = 0;
bool needs_indent_ = false;
bool error_ = false;
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 8dea8ea..49807db 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -30,7 +30,7 @@
#include "XmlPullParser.h"
#include "util/Util.h"
-using ::aapt::io::InputStream;
+using ::android::InputStream;
using ::android::StringPiece;
using ::android::StringPiece16;
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index c253b0a..9668b6a6 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -24,8 +24,8 @@
#include "Resource.h"
#include "ResourceValues.h"
#include "androidfw/IDiagnostics.h"
+#include "androidfw/Streams.h"
#include "androidfw/StringPiece.h"
-#include "io/Io.h"
#include "util/Util.h"
#include "xml/XmlUtil.h"
@@ -152,7 +152,7 @@
};
// Inflates an XML DOM from an InputStream, logging errors to the logger.
-std::unique_ptr<XmlResource> Inflate(io::InputStream* in, android::IDiagnostics* diag,
+std::unique_ptr<XmlResource> Inflate(android::InputStream* in, android::IDiagnostics* diag,
const android::Source& source);
// Inflates an XML DOM from a binary ResXMLTree.
diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp
index d79446b..203832d 100644
--- a/tools/aapt2/xml/XmlPullParser.cpp
+++ b/tools/aapt2/xml/XmlPullParser.cpp
@@ -21,7 +21,7 @@
#include "xml/XmlPullParser.h"
#include "xml/XmlUtil.h"
-using ::aapt::io::InputStream;
+using ::android::InputStream;
using ::android::StringPiece;
namespace aapt {
diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h
index fe4cd01..655e6dc 100644
--- a/tools/aapt2/xml/XmlPullParser.h
+++ b/tools/aapt2/xml/XmlPullParser.h
@@ -27,11 +27,10 @@
#include <string>
#include <vector>
-#include "android-base/macros.h"
-#include "androidfw/StringPiece.h"
-
#include "Resource.h"
-#include "io/Io.h"
+#include "android-base/macros.h"
+#include "androidfw/Streams.h"
+#include "androidfw/StringPiece.h"
#include "process/IResourceTableConsumer.h"
#include "xml/XmlUtil.h"
@@ -66,7 +65,7 @@
static bool SkipCurrentElement(XmlPullParser* parser);
static bool IsGoodEvent(Event event);
- explicit XmlPullParser(io::InputStream* in);
+ explicit XmlPullParser(android::InputStream* in);
~XmlPullParser();
/**
@@ -179,7 +178,7 @@
std::vector<Attribute> attributes;
};
- io::InputStream* in_;
+ android::InputStream* in_;
XML_Parser parser_;
std::queue<EventData> event_queue_;
std::string error_;
diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING
index 192b6f2..eca258c 100644
--- a/tools/hoststubgen/TEST_MAPPING
+++ b/tools/hoststubgen/TEST_MAPPING
@@ -1,11 +1,13 @@
{
- "presubmit": [
- { "name": "tiny-framework-dump-test" },
- { "name": "hoststubgentest" },
- { "name": "hoststubgen-invoke-test" }
-
- // As a smoke test.
- // TODO: Enable it once the infra knows how to run it.
- // { "name": "CtsUtilTestCasesRavenwood" }
- ]
+ "presubmit": [
+ { "name": "tiny-framework-dump-test" },
+ { "name": "hoststubgentest" },
+ { "name": "hoststubgen-invoke-test" }
+ ],
+ "ravenwood-presubmit": [
+ {
+ "name": "CtsUtilTestCasesRavenwood",
+ "host": true
+ }
+ ]
}
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
index d415dc5..0e2e158 100644
--- a/tools/hoststubgen/hoststubgen/Android.bp
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -284,6 +284,7 @@
java_host_for_device {
name: "hoststubgen-helper-libcore-runtime.ravenwood",
+ defaults: ["hoststubgen-for-prototype-only-java"],
libs: [
"hoststubgen-helper-libcore-runtime",
],
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
index 2255345..3bcabcb 100644
--- a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
@@ -15,9 +15,6 @@
*/
package com.android.hoststubgen.nativesubstitution;
-import android.os.IBinder;
-
-import java.io.FileDescriptor;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -143,12 +140,6 @@
public static void nativeMarkSensitive(long nativePtr) {
getInstance(nativePtr).mSensitive = true;
}
- public static void nativeMarkForBinder(long nativePtr, IBinder binder) {
- throw new RuntimeException("Not implemented yet");
- }
- public static boolean nativeIsForRpc(long nativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
public static int nativeDataSize(long nativePtr) {
return getInstance(nativePtr).mSize;
}
@@ -236,9 +227,6 @@
public static int nativeWriteDouble(long nativePtr, double val) {
return nativeWriteLong(nativePtr, Double.doubleToLongBits(val));
}
- public static void nativeSignalExceptionForError(int error) {
- throw new RuntimeException("Not implemented yet");
- }
private static int align4(int val) {
return ((val + 3) / 4) * 4;
@@ -256,12 +244,6 @@
// Just reuse String8
nativeWriteString8(nativePtr, val);
}
- public static void nativeWriteStrongBinder(long nativePtr, IBinder val) {
- throw new RuntimeException("Not implemented yet");
- }
- public static void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val) {
- throw new RuntimeException("Not implemented yet");
- }
public static byte[] nativeCreateByteArray(long nativePtr) {
return nativeReadBlob(nativePtr);
@@ -348,12 +330,6 @@
public static String nativeReadString16(long nativePtr) {
return nativeReadString8(nativePtr);
}
- public static IBinder nativeReadStrongBinder(long nativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
- public static FileDescriptor nativeReadFileDescriptor(long nativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
public static byte[] nativeMarshall(long nativePtr) {
var p = getInstance(nativePtr);
@@ -367,13 +343,6 @@
p.mPos += length;
p.updateSize();
}
- public static int nativeCompareData(long thisNativePtr, long otherNativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
- public static boolean nativeCompareDataInRange(
- long ptrA, int offsetA, long ptrB, int offsetB, int length) {
- throw new RuntimeException("Not implemented yet");
- }
public static void nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int srcOffset, int length) {
var dst = getInstance(thisNativePtr);
@@ -397,28 +366,4 @@
// Assume false for now, because we don't support writing FDs yet.
return false;
}
- public static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) {
- throw new RuntimeException("Not implemented yet");
- }
- public static void nativeEnforceInterface(long nativePtr, String interfaceName) {
- throw new RuntimeException("Not implemented yet");
- }
-
- public static boolean nativeReplaceCallingWorkSourceUid(
- long nativePtr, int workSourceUid) {
- throw new RuntimeException("Not implemented yet");
- }
- public static int nativeReadCallingWorkSourceUid(long nativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
-
- public static long nativeGetOpenAshmemSize(long nativePtr) {
- throw new RuntimeException("Not implemented yet");
- }
- public static long getGlobalAllocSize() {
- throw new RuntimeException("Not implemented yet");
- }
- public static long getGlobalAllocCount() {
- throw new RuntimeException("Not implemented yet");
- }
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
similarity index 73%
copy from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
copy to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
index 7ada961..2cc500f 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
@@ -15,6 +15,9 @@
*/
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;
@@ -22,11 +25,11 @@
import java.lang.annotation.Target;
/**
- * Annotation added to all "stub" classes generated by HostStubGen.
+ * Annotation injected to all classes/methods/fields that are kept in the "impl" jar.
*/
-@Target({TYPE})
+@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedKeepClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class);
+public @interface HostStubGenKeptInImpl {
+ String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenKeptInImpl.class);
String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
similarity index 65%
copy from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
copy to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
index 7ada961..12b9875 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
@@ -15,6 +15,9 @@
*/
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;
@@ -22,11 +25,14 @@
import java.lang.annotation.Target;
/**
- * Annotation added to all "stub" classes generated by HostStubGen.
+ * 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})
+@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedKeepClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class);
+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/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
similarity index 76%
rename from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
rename to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
index 7ada961..cb50404 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
@@ -15,18 +15,20 @@
*/
package com.android.hoststubgen.hosthelper;
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Annotation added to all "stub" classes generated by HostStubGen.
+ * Annotation injected to all methods processed as "ignore".
+ *
+ * (This annotation is only added in the impl jar, but not the stub jar)
*/
-@Target({TYPE})
+@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedKeepClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class);
+public @interface HostStubGenProcessedAsIgnore {
+ String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedAsIgnore.class);
String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
similarity index 63%
copy from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
copy to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
index 7ada961..cfa4896 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
@@ -15,6 +15,9 @@
*/
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;
@@ -22,11 +25,14 @@
import java.lang.annotation.Target;
/**
- * Annotation added to all "stub" classes generated by HostStubGen.
+ * 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})
+@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedKeepClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class);
+public @interface HostStubGenProcessedAsSubstitute {
+ String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(
+ HostStubGenProcessedAsSubstitute.class);
String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
similarity index 75%
copy from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
copy to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
index 7ada961..0d2da11 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
@@ -15,18 +15,20 @@
*/
package com.android.hoststubgen.hosthelper;
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Annotation added to all "stub" classes generated by HostStubGen.
+ * 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({TYPE})
+@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedKeepClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedKeepClass.class);
+public @interface HostStubGenProcessedAsThrow {
+ String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedAsThrow.class);
String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
deleted file mode 100644
index e598da0a..0000000
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
+++ /dev/null
@@ -1,32 +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.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation added to all "stub" classes generated by HostStubGen.
- */
-@Target({TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenProcessedStubClass {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedStubClass.class);
- String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
-}
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 c770b9c..7c6aa25 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
@@ -23,8 +23,6 @@
import javax.annotation.concurrent.GuardedBy;
-import org.junit.AssumptionViolatedException;
-
/**
* Utilities used in the host side test environment.
*/
@@ -128,7 +126,7 @@
}
}
// All processed classes have this annotation.
- var allowed = clazz.getAnnotation(HostStubGenProcessedKeepClass.class) != null;
+ var allowed = clazz.getAnnotation(HostStubGenKeptInImpl.class) != null;
// Java classes should be able to access any methods. (via callbacks, etc.)
if (!allowed) {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
index 207ba52..910bf59 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -46,3 +46,7 @@
*/
class InvalidAnnotationException(message: String) : Exception(message), UserErrorException
+/**
+ * We use this for general "user" errors.
+ */
+class HostStubGenUserErrorException(message: String) : Exception(message), UserErrorException
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 4e0cd09..97e09b8 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -128,7 +128,7 @@
}
val end = System.currentTimeMillis()
- log.v("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
+ log.i("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
return allClasses
}
@@ -158,7 +158,7 @@
// 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
// the class-wide policy, if any. (if not, we'll fall back to the above filter.)
- filter = ClassWidePolicyPropagatingFilter(filter)
+ filter = ClassWidePolicyPropagatingFilter(allClasses, filter)
// Inject default hooks from options.
filter = DefaultHookInjectingFilter(
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
index 9df0489..6b01d48 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -15,10 +15,10 @@
*/
package com.android.hoststubgen
-class HostStubGenErrors {
- fun onErrorFound(message: String) {
- // For now, we just throw as soon as any error is found, but eventually we should keep
+open class HostStubGenErrors {
+ open fun onErrorFound(message: String) {
+ // TODO: For now, we just throw as soon as any error is found, but eventually we should keep
// all errors and print them at the end.
- throw RuntimeException(message)
+ throw HostStubGenUserErrorException(message)
}
}
\ No newline at end of file
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 d7aa0af..0579c2b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -17,6 +17,8 @@
import com.android.hoststubgen.ClassParseException
import com.android.hoststubgen.HostStubGenInternalException
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
@@ -108,7 +110,7 @@
* Otherwise, return null.
*/
fun getDirectOuterClassName(className: String): String? {
- val pos = className.indexOf('$')
+ val pos = className.lastIndexOf('$')
if (pos < 0) {
return null
}
@@ -194,6 +196,29 @@
}
}
+enum class Visibility {
+ PRIVATE,
+ PACKAGE_PRIVATE,
+ PROTECTED,
+ PUBLIC;
+
+ companion object {
+ fun fromAccess(access: Int): Visibility {
+ if ((access and Opcodes.ACC_PUBLIC) != 0) {
+ return PUBLIC
+ }
+ if ((access and Opcodes.ACC_PROTECTED) != 0) {
+ return PROTECTED
+ }
+ if ((access and Opcodes.ACC_PRIVATE) != 0) {
+ return PRIVATE
+ }
+
+ return PACKAGE_PRIVATE
+ }
+ }
+}
+
fun ClassNode.isEnum(): Boolean {
return (this.access and Opcodes.ACC_ENUM) != 0
}
@@ -210,6 +235,10 @@
return (this.access and Opcodes.ACC_SYNTHETIC) != 0
}
+fun MethodNode.isStatic(): Boolean {
+ return (this.access and Opcodes.ACC_STATIC) != 0
+}
+
fun FieldNode.isEnum(): Boolean {
return (this.access and Opcodes.ACC_ENUM) != 0
}
@@ -218,6 +247,19 @@
return (this.access and Opcodes.ACC_SYNTHETIC) != 0
}
+fun ClassNode.getVisibility(): Visibility {
+ return Visibility.fromAccess(this.access)
+}
+
+fun MethodNode.getVisibility(): Visibility {
+ return Visibility.fromAccess(this.access)
+}
+
+fun FieldNode.getVisibility(): Visibility {
+ return Visibility.fromAccess(this.access)
+}
+
+
/*
Dump of the members of TinyFrameworkEnumSimple:
@@ -283,3 +325,36 @@
}
return false
}
+
+/**
+ * Class to help handle [ClassVisitor], [MethodVisitor] and [FieldVisitor] in a unified way.
+ */
+abstract class UnifiedVisitor {
+ abstract fun visitAnnotation(descriptor: String, visible: Boolean)
+
+ companion object {
+ fun on(target: ClassVisitor): UnifiedVisitor {
+ return object : UnifiedVisitor() {
+ override fun visitAnnotation(descriptor: String, visible: Boolean) {
+ target.visitAnnotation(descriptor, visible)
+ }
+ }
+ }
+
+ fun on(target: MethodVisitor): UnifiedVisitor {
+ return object : UnifiedVisitor() {
+ override fun visitAnnotation(descriptor: String, visible: Boolean) {
+ target.visitAnnotation(descriptor, visible)
+ }
+ }
+ }
+
+ fun on(target: FieldVisitor): UnifiedVisitor {
+ return object : UnifiedVisitor() {
+ override fun visitAnnotation(descriptor: String, visible: Boolean) {
+ target.visitAnnotation(descriptor, visible)
+ }
+ }
+ }
+ }
+}
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 6aac3d8..47790b1 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -15,6 +15,7 @@
*/
package com.android.hoststubgen.filters
+import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.getDirectOuterClassName
/**
@@ -22,22 +23,38 @@
* (obtained from [outermostFilter]) to the fields and methods.
*/
class ClassWidePolicyPropagatingFilter(
- fallback: OutputFilter,
+ private val classes: ClassNodes,
+ fallback: OutputFilter,
) : DelegatingFilter(fallback) {
private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
var currentClass = className
- while (true) {
- outermostFilter.getPolicyForClass(className).let { policy ->
- if (policy.policy.isClassWidePolicy) {
- val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy
- return p.withReason(policy.reason).wrapReason("class-wide in $currentClass")
- }
- // If the class's policy is remove, then remove it.
- if (policy.policy == FilterPolicy.Remove) {
- return FilterPolicy.Remove.withReason("class-wide in $currentClass")
+ // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy
+ // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A.
+ while (true) {
+ // Sometimes a class name has a `$` in it but not as a nest class name separator --
+ // e.g. class name like "MyClass$$". In this case, `MyClass$` may not actually be
+ // a class name.
+ // So before getting the class policy on a nonexistent class, which may cause an
+ // incorrect result, we make sure if className actually exists.
+ if (classes.hasClass(className)) {
+ outermostFilter.getPolicyForClass(className).let { policy ->
+ if (policy.policy.isClassWidePolicy) {
+ val p = if (resolve) {
+ policy.policy.resolveClassWidePolicy()
+ } else {
+ policy.policy
+ }
+
+ return p.withReason(policy.reason)
+ .wrapReason("class-wide in $currentClass")
+ }
+ // If the class's policy is remove, then remove it.
+ if (policy.policy == FilterPolicy.Remove) {
+ return FilterPolicy.Remove.withReason("class-wide in $currentClass")
+ }
}
}
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 96e4a3f..21cfd4b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -18,14 +18,15 @@
import com.android.hoststubgen.HostStubGenErrors
import com.android.hoststubgen.LogLevel
import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.UnifiedVisitor
import com.android.hoststubgen.asm.getPackageNameFromClassName
import com.android.hoststubgen.asm.resolveClassName
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.HostStubGenProcessedKeepClass
-import com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+import com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+import com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
import com.android.hoststubgen.log
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.FieldVisitor
@@ -64,6 +65,18 @@
*/
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,
@@ -100,12 +113,7 @@
nativeSubstitutionClass = fullClassName
}
// Inject annotations to generated classes.
- if (classPolicy.policy.needsInStub) {
- visitAnnotation(HostStubGenProcessedStubClass.CLASS_DESCRIPTOR, true)
- }
- if (classPolicy.policy.needsInImpl) {
- visitAnnotation(HostStubGenProcessedKeepClass.CLASS_DESCRIPTOR, true)
- }
+ injectInStubAndKeepAnnotations(classPolicy.policy, UnifiedVisitor.on(this))
}
override fun visitEnd() {
@@ -148,7 +156,11 @@
}
log.v("Emitting field: %s %s %s", name, descriptor, policy)
- return super.visitField(access, name, descriptor, signature, value)
+ val ret = super.visitField(access, name, descriptor, signature, value)
+
+ injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+
+ return ret
}
}
@@ -166,7 +178,9 @@
log.d("visitMethod: %s%s [%x] [%s] Policy: %s", name, descriptor, access, signature, p)
log.withIndent {
- // If it's a substitute-to method, then skip.
+ // If it's a substitute-from method, then skip (== remove).
+ // 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) {
log.d("Skipping %s%s %s", name, descriptor, policy)
@@ -179,9 +193,19 @@
// Maybe rename the method.
val newName: String
- val substituteTo = filter.getRenameTo(currentClassName, name, descriptor)
- if (substituteTo != null) {
- newName = substituteTo
+ val renameTo = filter.getRenameTo(currentClassName, name, descriptor)
+ if (renameTo != null) {
+ newName = renameTo
+
+ // It's confusing, but here, `newName` is the original method name
+ // (the one with the @substitute/replace annotation).
+ // `name` is the name of the method we're currently visiting, so it's usually a
+ // "...$ravewnwood" name.
+ if (!checkSubstitutionMethodCompatibility(
+ classes, currentClassName, newName, name, descriptor, options.errors)) {
+ return null
+ }
+
log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
newName, policy)
} else {
@@ -191,12 +215,19 @@
// Let subclass update the flag.
// But note, we only use it when calling the super's method,
- // but not for visitMethodInner(), beucase when subclass wants to change access,
+ // but not for visitMethodInner(), because when subclass wants to change access,
// it can do so inside visitMethodInner().
val newAccess = updateAccessFlags(access, name, descriptor)
- return visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
- super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+ val ret = visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+ renameTo != null,
+ super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+
+ ret?.let {
+ injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+ }
+
+ return ret
}
}
@@ -215,6 +246,7 @@
signature: String?,
exceptions: Array<String>?,
policy: FilterPolicyWithReason,
+ substituted: Boolean,
superVisitor: MethodVisitor?,
): MethodVisitor?
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/Helper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/Helper.kt
new file mode 100644
index 0000000..9d66c32
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/Helper.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.getVisibility
+import com.android.hoststubgen.asm.isStatic
+
+/**
+ * Make sure substitution from and to methods have matching definition.
+ * (static-ness, visibility.)
+ */
+fun checkSubstitutionMethodCompatibility(
+ classes: ClassNodes,
+ className: String,
+ fromMethodName: String, // the one with the annotation
+ toMethodName: String, // the one with either a "_host" or "$ravenwood" prefix. (typically)
+ descriptor: String,
+ errors: HostStubGenErrors,
+): Boolean {
+ val from = classes.findMethod(className, fromMethodName, descriptor)
+ if (from == null) {
+ errors.onErrorFound(
+ "Substitution-from method not found: $className.$fromMethodName$descriptor")
+ return false
+ }
+ val to = classes.findMethod(className, toMethodName, descriptor)
+ if (to == null) {
+ // This shouldn't happen, because the visitor visited this method...
+ errors.onErrorFound(
+ "Substitution-to method not found: $className.$toMethodName$descriptor")
+ return false
+ }
+
+ if (from.isStatic() != to.isStatic()) {
+ errors.onErrorFound(
+ "Substitution method must have matching static-ness: " +
+ "$className.$fromMethodName$descriptor")
+ return false
+ }
+ if (from.getVisibility().ordinal > to.getVisibility().ordinal) {
+ errors.onErrorFound(
+ "Substitution method cannot have smaller visibility than original: " +
+ "$className.$fromMethodName$descriptor")
+ return false
+ }
+
+ return true
+}
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 88db15b..416b782 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -25,6 +25,9 @@
import com.android.hoststubgen.filters.FilterPolicy
import com.android.hoststubgen.filters.FilterPolicyWithReason
import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
import com.android.hoststubgen.hosthelper.HostTestUtils
import com.android.hoststubgen.log
import org.objectweb.asm.ClassVisitor
@@ -135,6 +138,7 @@
signature: String?,
exceptions: Array<String>?,
policy: FilterPolicyWithReason,
+ substituted: Boolean,
superVisitor: MethodVisitor?,
): MethodVisitor? {
// Inject method log, if needed.
@@ -182,23 +186,37 @@
)
}
+ fun MethodVisitor.withAnnotation(descriptor: String): MethodVisitor {
+ this.visitAnnotation(descriptor, true)
+ return this
+ }
+
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)
+ }
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 (policy.policy == FilterPolicy.Throw) {
- log.v("Making method throw...")
- return ThrowingMethodAdapter(
- access, name, descriptor, signature, exceptions, innerVisitor)
+ if (willThrow) {
+ return innerVisitor
}
+
if (policy.policy == FilterPolicy.Ignore) {
when (Type.getReturnType(descriptor)) {
Type.VOID_TYPE -> {
log.v("Making method ignored...")
return IgnoreMethodAdapter(
access, name, descriptor, signature, exceptions, innerVisitor)
+ .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
}
else -> {
throw RuntimeException("Ignored policy only allowed for void methods")
@@ -206,6 +224,9 @@
}
}
}
+ if (substituted) {
+ innerVisitor?.withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
+ }
return innerVisitor
}
@@ -294,13 +315,13 @@
next: MethodVisitor?
) : MethodVisitor(OPCODE_VERSION, next) {
override fun visitCode() {
- super.visitCode()
-
throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
" native method, where visitCode() shouldn't be called.")
}
override fun visitEnd() {
+ super.visitCode()
+
var targetDescriptor = descriptor
var argOffset = 0
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
index 37e2a88..fc20f28 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
@@ -45,6 +45,7 @@
signature: String?,
exceptions: Array<String>?,
policy: FilterPolicyWithReason,
+ substituted: Boolean,
superVisitor: MethodVisitor?,
): MethodVisitor? {
return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
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 3956893..70f56ae 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
@@ -1817,7 +1817,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: 8, attributes: 2
+ interfaces: 0, fields: 1, methods: 10, attributes: 2
int value;
descriptor: I
flags: (0x0000)
@@ -1904,6 +1904,24 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
0 6 1 arg I
+
+ public static native void nativeStillNotSupported();
+ descriptor: ()V
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public static void nativeStillNotSupported_should_be_like_this();
+ 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:
}
SourceFile: "TinyFrameworkNative.java"
RuntimeInvisibleAnnotations:
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
index 9349355..b0db483 100644
--- 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
@@ -17,6 +17,11 @@
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
@@ -28,6 +33,11 @@
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
@@ -35,9 +45,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -58,6 +68,11 @@
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
@@ -69,6 +84,11 @@
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
@@ -76,9 +96,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -96,9 +116,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -121,6 +141,11 @@
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
@@ -132,6 +157,11 @@
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
@@ -141,9 +171,9 @@
SourceFile: "TinyFrameworkCallerCheck.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -164,6 +194,11 @@
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
@@ -175,6 +210,11 @@
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
@@ -186,15 +226,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -212,6 +257,11 @@
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
@@ -226,6 +276,11 @@
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
@@ -240,6 +295,11 @@
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
@@ -254,6 +314,11 @@
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
@@ -265,6 +330,11 @@
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;
@@ -276,6 +346,11 @@
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
@@ -283,9 +358,9 @@
SourceFile: "TinyFrameworkClassAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -305,14 +380,29 @@
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.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int remove;
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.TinyFrameworkClassClassWideAnnotations();
descriptor: ()V
@@ -324,6 +414,11 @@
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
@@ -335,6 +430,11 @@
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 addOneInner(int);
descriptor: (I)I
@@ -346,6 +446,11 @@
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 toBeRemoved(java.lang.String);
descriptor: (Ljava/lang/String;)V
@@ -357,6 +462,11 @@
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
@@ -368,6 +478,11 @@
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
@@ -379,6 +494,11 @@
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 unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -390,6 +510,11 @@
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;
@@ -401,13 +526,18 @@
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: "TinyFrameworkClassClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -424,6 +554,11 @@
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
@@ -435,6 +570,11 @@
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
@@ -447,6 +587,11 @@
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
@@ -458,13 +603,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -480,6 +630,11 @@
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
@@ -487,6 +642,11 @@
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
@@ -495,9 +655,9 @@
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -513,6 +673,11 @@
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
@@ -520,6 +685,11 @@
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
@@ -528,9 +698,9 @@
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
@@ -552,6 +722,11 @@
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
@@ -559,6 +734,11 @@
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
@@ -566,6 +746,11 @@
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
@@ -573,6 +758,11 @@
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;
@@ -584,6 +774,11 @@
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;
@@ -595,6 +790,11 @@
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 com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -607,6 +807,11 @@
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
@@ -621,6 +826,11 @@
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
@@ -635,6 +845,11 @@
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
@@ -649,6 +864,11 @@
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
@@ -660,14 +880,19 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -683,6 +908,11 @@
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
@@ -690,6 +920,11 @@
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
@@ -697,6 +932,11 @@
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;
@@ -708,6 +948,11 @@
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;
@@ -719,6 +964,11 @@
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 com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -731,6 +981,11 @@
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
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -742,6 +997,11 @@
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
@@ -753,14 +1013,19 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -783,6 +1048,11 @@
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
@@ -794,13 +1064,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -816,6 +1091,11 @@
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
@@ -827,6 +1107,11 @@
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
@@ -838,6 +1123,11 @@
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
@@ -849,6 +1139,11 @@
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
@@ -860,6 +1155,11 @@
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;
@@ -871,13 +1171,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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
@@ -891,6 +1196,11 @@
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
@@ -899,6 +1209,11 @@
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
@@ -913,6 +1228,11 @@
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
@@ -928,6 +1248,11 @@
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
@@ -943,6 +1268,11 @@
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
@@ -957,6 +1287,11 @@
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;
@@ -968,6 +1303,11 @@
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;
@@ -979,6 +1319,11 @@
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;
@@ -990,6 +1335,11 @@
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
@@ -997,9 +1347,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1019,6 +1369,11 @@
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
@@ -1027,6 +1382,11 @@
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
@@ -1041,6 +1401,11 @@
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
@@ -1056,6 +1421,11 @@
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
@@ -1071,6 +1441,11 @@
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
@@ -1085,6 +1460,11 @@
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;
@@ -1096,6 +1476,11 @@
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;
@@ -1107,6 +1492,11 @@
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;
@@ -1118,6 +1508,11 @@
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
@@ -1125,9 +1520,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1143,10 +1538,15 @@
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: 8, attributes: 3
+ interfaces: 0, fields: 1, methods: 9, 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
@@ -1158,10 +1558,20 @@
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
@@ -1173,10 +1583,20 @@
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
@@ -1188,6 +1608,11 @@
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
@@ -1199,10 +1624,20 @@
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
@@ -1214,13 +1649,34 @@
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
}
SourceFile: "TinyFrameworkNative.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1240,6 +1696,11 @@
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
@@ -1251,15 +1712,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -1273,10 +1739,20 @@
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
@@ -1288,15 +1764,20 @@
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 #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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1313,6 +1794,11 @@
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
@@ -1324,6 +1810,11 @@
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;
@@ -1336,6 +1827,11 @@
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
@@ -1343,9 +1839,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1369,6 +1865,11 @@
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
@@ -1376,9 +1877,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -1393,11 +1894,21 @@
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
@@ -1409,6 +1920,11 @@
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;
@@ -1421,6 +1937,11 @@
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;
@@ -1433,6 +1954,11 @@
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
@@ -1444,6 +1970,11 @@
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
@@ -1458,9 +1989,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1493,6 +2024,11 @@
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
@@ -1504,13 +2040,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1533,6 +2074,11 @@
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
@@ -1544,13 +2090,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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-impl-dump.txt
index 4f8c408e..112f69e 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-impl-dump.txt
@@ -10,11 +10,14 @@
public abstract java.lang.String value();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -36,7 +39,7 @@
SourceFile: "HostSideTestKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -57,11 +60,14 @@
public abstract java.lang.String value();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestNativeSubstitutionClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -83,7 +89,7 @@
SourceFile: "HostSideTestRemove.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -105,7 +111,7 @@
SourceFile: "HostSideTestStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -126,11 +132,14 @@
public abstract java.lang.String suffix();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestSubstitute.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -152,7 +161,7 @@
SourceFile: "HostSideTestThrow.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -174,7 +183,7 @@
SourceFile: "HostSideTestWholeClassKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -196,7 +205,7 @@
SourceFile: "HostSideTestWholeClassStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -226,6 +235,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int addTwo(int);
descriptor: (I)I
@@ -240,6 +254,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 a I
+ 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
@@ -247,9 +266,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -272,6 +291,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int addOne(int);
descriptor: (I)I
@@ -286,6 +310,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 a I
+ 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
@@ -293,9 +322,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -313,9 +342,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -340,6 +369,11 @@
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
@@ -355,6 +389,9 @@
x: iconst_1
x: ireturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -367,6 +404,11 @@
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
@@ -376,9 +418,9 @@
SourceFile: "TinyFrameworkCallerCheck.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -401,6 +443,11 @@
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
@@ -410,6 +457,11 @@
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
@@ -419,15 +471,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -445,6 +502,11 @@
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
@@ -452,6 +514,9 @@
public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -484,6 +549,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -502,6 +572,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
0 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
@@ -526,6 +601,9 @@
Start Length Slot Name Signature
15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
15 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -544,6 +622,13 @@
Start Length Slot Name Signature
0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
0 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -558,6 +643,13 @@
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -576,6 +668,11 @@
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
@@ -592,6 +689,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -599,9 +701,9 @@
SourceFile: "TinyFrameworkClassAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -621,14 +723,29 @@
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.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int remove;
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.TinyFrameworkClassClassWideAnnotations();
descriptor: ()V
@@ -648,6 +765,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addOne(int);
descriptor: (I)I
@@ -663,6 +785,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
0 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
@@ -678,6 +805,11 @@
Start Length Slot Name Signature
0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
0 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public void toBeRemoved(java.lang.String);
descriptor: (Ljava/lang/String;)V
@@ -693,6 +825,11 @@
Start Length Slot Name Signature
0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
0 8 1 foo Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addTwo(int);
descriptor: (I)I
@@ -708,6 +845,13 @@
Start Length Slot Name Signature
0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
0 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -722,6 +866,13 @@
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -734,6 +885,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String visibleButUsesUnsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -747,13 +903,18 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -770,6 +931,11 @@
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
@@ -783,6 +949,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static void onClassLoaded(java.lang.Class<?>);
descriptor: (Ljava/lang/Class;)V
@@ -802,6 +973,11 @@
Start Length Slot Name Signature
0 11 0 clazz Ljava/lang/Class<*>;
Signature: #x // (Ljava/lang/Class<*>;)V
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -814,13 +990,18 @@
x: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -836,6 +1017,11 @@
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
@@ -843,6 +1029,11 @@
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
@@ -851,9 +1042,9 @@
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -869,6 +1060,11 @@
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
@@ -876,6 +1072,11 @@
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
@@ -896,13 +1097,16 @@
x: putstatic #x // Field sObject:Ljava/lang/Object;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
@@ -924,6 +1128,11 @@
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
@@ -931,6 +1140,11 @@
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
@@ -938,6 +1152,11 @@
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
@@ -945,6 +1164,9 @@
private final java.lang.String mLongName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -952,6 +1174,9 @@
private final java.lang.String mShortName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -959,6 +1184,11 @@
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;
@@ -970,6 +1200,11 @@
x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;"
x: areturn
LineNumberTable:
+ 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;
@@ -985,6 +1220,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 name Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -1009,6 +1249,11 @@
0 18 3 longName Ljava/lang/String;
0 18 4 shortName Ljava/lang/String;
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
@@ -1025,6 +1270,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1041,6 +1291,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1066,6 +1321,11 @@
x: aastore
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1100,14 +1360,19 @@
x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1123,6 +1388,11 @@
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
@@ -1130,6 +1400,11 @@
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
@@ -1137,6 +1412,11 @@
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;
@@ -1148,6 +1428,11 @@
x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;"
x: areturn
LineNumberTable:
+ 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;
@@ -1163,6 +1448,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 name Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -1179,6 +1469,11 @@
Start Length Slot Name Signature
0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
Signature: #x // ()V
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1197,6 +1492,11 @@
x: aastore
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1219,14 +1519,19 @@
x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1251,6 +1556,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int testException();
descriptor: ()I
@@ -1279,13 +1589,18 @@
LocalVariableTable:
Start Length Slot Name Signature
11 11 0 e Ljava/lang/Exception;
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1301,10 +1616,18 @@
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
private static {};
descriptor: ()V
@@ -1334,6 +1657,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addOne(int);
descriptor: (I)I
@@ -1349,6 +1677,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
0 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
@@ -1370,6 +1703,9 @@
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
public int addTwo(int);
descriptor: (I)I
@@ -1385,6 +1721,13 @@
Start Length Slot Name Signature
0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
0 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -1399,6 +1742,13 @@
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -1417,6 +1767,11 @@
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;
@@ -1430,13 +1785,18 @@
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
}
SourceFile: "TinyFrameworkForTextPolicy.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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
@@ -1450,6 +1810,11 @@
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
@@ -1458,6 +1823,11 @@
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
@@ -1477,6 +1847,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1493,6 +1868,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
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
@@ -1506,6 +1886,11 @@
x: areturn
LineNumberTable:
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
@@ -1519,6 +1904,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1529,6 +1919,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1539,6 +1934,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1549,6 +1949,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1559,6 +1964,9 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ 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
@@ -1566,9 +1974,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1609,6 +2017,11 @@
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
@@ -1617,6 +2030,11 @@
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
@@ -1636,6 +2054,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1652,6 +2075,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
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
@@ -1665,6 +2093,11 @@
x: areturn
LineNumberTable:
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
@@ -1678,6 +2111,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1688,6 +2126,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1698,6 +2141,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1708,6 +2156,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1718,6 +2171,9 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ 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
@@ -1725,9 +2181,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1764,10 +2220,15 @@
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: 8, attributes: 3
+ 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
@@ -1781,6 +2242,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -1790,6 +2256,13 @@
x: iload_0
x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
x: ireturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -1803,6 +2276,11 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -1813,6 +2291,13 @@
x: lload_2
x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
x: lreturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -1828,6 +2313,11 @@
Start Length Slot Name Signature
0 6 0 arg1 J
0 6 2 arg2 J
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public void setValue(int);
descriptor: (I)V
@@ -1843,6 +2333,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
0 6 1 v I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int nativeNonStaticAddToValue(int);
descriptor: (I)I
@@ -1853,6 +2348,13 @@
x: iload_1
x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
x: ireturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -1868,13 +2370,62 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
0 6 1 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+ 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
+ x: athrow
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public static void nativeStillNotSupported_should_be_like_this();
+ 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:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1909,6 +2460,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -1929,6 +2483,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 4 0 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -1950,6 +2507,9 @@
Start Length Slot Name Signature
15 4 0 arg1 J
15 4 2 arg2 J
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
@@ -1972,11 +2532,14 @@
Start Length Slot Name Signature
15 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
15 7 1 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkNative_host.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -1992,6 +2555,9 @@
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.HostStubGenKeptInImpl
com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -2009,6 +2575,9 @@
Start Length Slot Name Signature
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2028,6 +2597,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2047,6 +2619,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -2055,7 +2630,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2078,6 +2653,9 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2097,6 +2675,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2116,6 +2697,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -2124,7 +2708,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2138,6 +2722,9 @@
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.HostStubGenKeptInImpl
com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -2155,6 +2742,9 @@
Start Length Slot Name Signature
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2174,6 +2764,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2193,6 +2786,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -2201,7 +2797,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2224,6 +2820,9 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2243,6 +2842,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2262,6 +2864,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -2270,7 +2875,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2284,6 +2889,11 @@
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
@@ -2301,15 +2911,20 @@
Start Length Slot Name Signature
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
0 10 1 x I
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -2323,10 +2938,20 @@
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
@@ -2347,15 +2972,20 @@
Start Length Slot Name Signature
0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
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
}
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -2381,6 +3011,9 @@
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2400,6 +3033,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2419,6 +3055,9 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ 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
@@ -2428,7 +3067,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -2442,6 +3081,11 @@
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
@@ -2458,6 +3102,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -2470,6 +3119,11 @@
x: areturn
LineNumberTable:
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
@@ -2477,9 +3131,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -2507,6 +3161,11 @@
Start Length Slot Name Signature
0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
0 6 1 x I
+ 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
@@ -2514,9 +3173,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -2531,11 +3190,21 @@
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
@@ -2555,6 +3224,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -2571,6 +3245,11 @@
Start Length Slot Name Signature
0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
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;
@@ -2583,6 +3262,11 @@
x: areturn
LineNumberTable:
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
@@ -2595,6 +3279,11 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ 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
@@ -2609,9 +3298,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -2646,6 +3335,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int foo(int);
descriptor: (I)I
@@ -2662,13 +3356,18 @@
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 value I
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -2684,6 +3383,9 @@
private final int mValue;
descriptor: I
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public com.supported.UnsupportedClass(int);
descriptor: (I)V
@@ -2707,6 +3409,9 @@
Start Length Slot Name Signature
15 10 0 this Lcom/supported/UnsupportedClass;
15 10 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int getValue();
descriptor: ()I
@@ -2726,11 +3431,14 @@
LocalVariableTable:
Start Length Slot Name Signature
15 5 0 this Lcom/supported/UnsupportedClass;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -2760,6 +3468,11 @@
Start Length Slot Name Signature
0 14 0 this Lcom/unsupported/UnsupportedClass;
0 14 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int getValue();
descriptor: ()I
@@ -2775,13 +3488,18 @@
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/unsupported/UnsupportedClass;
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
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
index 9349355..b0db483 100644
--- 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
@@ -17,6 +17,11 @@
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
@@ -28,6 +33,11 @@
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
@@ -35,9 +45,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -58,6 +68,11 @@
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
@@ -69,6 +84,11 @@
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
@@ -76,9 +96,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -96,9 +116,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -121,6 +141,11 @@
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
@@ -132,6 +157,11 @@
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
@@ -141,9 +171,9 @@
SourceFile: "TinyFrameworkCallerCheck.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -164,6 +194,11 @@
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
@@ -175,6 +210,11 @@
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
@@ -186,15 +226,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -212,6 +257,11 @@
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
@@ -226,6 +276,11 @@
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
@@ -240,6 +295,11 @@
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
@@ -254,6 +314,11 @@
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
@@ -265,6 +330,11 @@
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;
@@ -276,6 +346,11 @@
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
@@ -283,9 +358,9 @@
SourceFile: "TinyFrameworkClassAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -305,14 +380,29 @@
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.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int remove;
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.TinyFrameworkClassClassWideAnnotations();
descriptor: ()V
@@ -324,6 +414,11 @@
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
@@ -335,6 +430,11 @@
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 addOneInner(int);
descriptor: (I)I
@@ -346,6 +446,11 @@
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 toBeRemoved(java.lang.String);
descriptor: (Ljava/lang/String;)V
@@ -357,6 +462,11 @@
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
@@ -368,6 +478,11 @@
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
@@ -379,6 +494,11 @@
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 unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -390,6 +510,11 @@
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;
@@ -401,13 +526,18 @@
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: "TinyFrameworkClassClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -424,6 +554,11 @@
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
@@ -435,6 +570,11 @@
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
@@ -447,6 +587,11 @@
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
@@ -458,13 +603,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -480,6 +630,11 @@
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
@@ -487,6 +642,11 @@
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
@@ -495,9 +655,9 @@
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -513,6 +673,11 @@
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
@@ -520,6 +685,11 @@
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
@@ -528,9 +698,9 @@
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
@@ -552,6 +722,11 @@
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
@@ -559,6 +734,11 @@
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
@@ -566,6 +746,11 @@
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
@@ -573,6 +758,11 @@
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;
@@ -584,6 +774,11 @@
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;
@@ -595,6 +790,11 @@
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 com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -607,6 +807,11 @@
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
@@ -621,6 +826,11 @@
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
@@ -635,6 +845,11 @@
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
@@ -649,6 +864,11 @@
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
@@ -660,14 +880,19 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -683,6 +908,11 @@
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
@@ -690,6 +920,11 @@
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
@@ -697,6 +932,11 @@
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;
@@ -708,6 +948,11 @@
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;
@@ -719,6 +964,11 @@
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 com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -731,6 +981,11 @@
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
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -742,6 +997,11 @@
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
@@ -753,14 +1013,19 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -783,6 +1048,11 @@
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
@@ -794,13 +1064,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -816,6 +1091,11 @@
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
@@ -827,6 +1107,11 @@
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
@@ -838,6 +1123,11 @@
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
@@ -849,6 +1139,11 @@
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
@@ -860,6 +1155,11 @@
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;
@@ -871,13 +1171,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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
@@ -891,6 +1196,11 @@
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
@@ -899,6 +1209,11 @@
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
@@ -913,6 +1228,11 @@
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
@@ -928,6 +1248,11 @@
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
@@ -943,6 +1268,11 @@
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
@@ -957,6 +1287,11 @@
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;
@@ -968,6 +1303,11 @@
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;
@@ -979,6 +1319,11 @@
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;
@@ -990,6 +1335,11 @@
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
@@ -997,9 +1347,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1019,6 +1369,11 @@
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
@@ -1027,6 +1382,11 @@
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
@@ -1041,6 +1401,11 @@
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
@@ -1056,6 +1421,11 @@
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
@@ -1071,6 +1441,11 @@
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
@@ -1085,6 +1460,11 @@
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;
@@ -1096,6 +1476,11 @@
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;
@@ -1107,6 +1492,11 @@
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;
@@ -1118,6 +1508,11 @@
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
@@ -1125,9 +1520,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1143,10 +1538,15 @@
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: 8, attributes: 3
+ interfaces: 0, fields: 1, methods: 9, 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
@@ -1158,10 +1558,20 @@
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
@@ -1173,10 +1583,20 @@
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
@@ -1188,6 +1608,11 @@
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
@@ -1199,10 +1624,20 @@
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
@@ -1214,13 +1649,34 @@
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
}
SourceFile: "TinyFrameworkNative.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1240,6 +1696,11 @@
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
@@ -1251,15 +1712,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -1273,10 +1739,20 @@
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
@@ -1288,15 +1764,20 @@
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 #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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1313,6 +1794,11 @@
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
@@ -1324,6 +1810,11 @@
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;
@@ -1336,6 +1827,11 @@
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
@@ -1343,9 +1839,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1369,6 +1865,11 @@
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
@@ -1376,9 +1877,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -1393,11 +1894,21 @@
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
@@ -1409,6 +1920,11 @@
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;
@@ -1421,6 +1937,11 @@
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;
@@ -1433,6 +1954,11 @@
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
@@ -1444,6 +1970,11 @@
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
@@ -1458,9 +1989,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1493,6 +2024,11 @@
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
@@ -1504,13 +2040,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1533,6 +2074,11 @@
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
@@ -1544,13 +2090,18 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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-impl-dump.txt
index 5ff3cde..2357844 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-impl-dump.txt
@@ -20,11 +20,14 @@
public abstract java.lang.String value();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -55,7 +58,7 @@
SourceFile: "HostSideTestKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -86,11 +89,14 @@
public abstract java.lang.String value();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestNativeSubstitutionClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -121,7 +127,7 @@
SourceFile: "HostSideTestRemove.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -152,7 +158,7 @@
SourceFile: "HostSideTestStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
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]
@@ -183,11 +189,14 @@
public abstract java.lang.String suffix();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "HostSideTestSubstitute.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -218,7 +227,7 @@
SourceFile: "HostSideTestThrow.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -249,7 +258,7 @@
SourceFile: "HostSideTestWholeClassKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -280,7 +289,7 @@
SourceFile: "HostSideTestWholeClassStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -325,6 +334,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int addTwo(int);
descriptor: (I)I
@@ -344,6 +358,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 4 0 a I
+ 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
@@ -351,9 +370,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -391,6 +410,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int addOne(int);
descriptor: (I)I
@@ -410,6 +434,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 4 0 a I
+ 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
@@ -417,9 +446,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -446,9 +475,9 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -488,6 +517,11 @@
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
@@ -508,6 +542,9 @@
x: iconst_1
x: ireturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -525,6 +562,11 @@
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
@@ -534,9 +576,9 @@
SourceFile: "TinyFrameworkCallerCheck.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -574,6 +616,11 @@
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
@@ -588,6 +635,11 @@
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
@@ -602,15 +654,20 @@
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -628,6 +685,11 @@
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
@@ -635,6 +697,9 @@
public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -675,6 +740,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -698,6 +768,11 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
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
@@ -727,6 +802,9 @@
Start Length Slot Name Signature
26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
26 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -750,6 +828,13 @@
Start Length Slot Name Signature
11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
11 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -769,6 +854,13 @@
LocalVariableTable:
Start Length Slot Name Signature
11 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -792,6 +884,11 @@
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
@@ -813,6 +910,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -820,9 +922,9 @@
SourceFile: "TinyFrameworkClassAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -842,14 +944,29 @@
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.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int remove;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -884,6 +1001,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addOne(int);
descriptor: (I)I
@@ -904,6 +1026,11 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
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
@@ -924,6 +1051,11 @@
Start Length Slot Name Signature
11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
11 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public void toBeRemoved(java.lang.String);
descriptor: (Ljava/lang/String;)V
@@ -944,6 +1076,11 @@
Start Length Slot Name Signature
11 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
11 8 1 foo Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addTwo(int);
descriptor: (I)I
@@ -964,6 +1101,13 @@
Start Length Slot Name Signature
11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
11 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -983,6 +1127,13 @@
LocalVariableTable:
Start Length Slot Name Signature
11 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -1000,6 +1151,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String visibleButUsesUnsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -1018,13 +1174,18 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1041,6 +1202,11 @@
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
@@ -1059,6 +1225,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static void onClassLoaded(java.lang.Class<?>);
descriptor: (Ljava/lang/Class;)V
@@ -1083,6 +1254,11 @@
Start Length Slot Name Signature
11 11 0 clazz Ljava/lang/Class<*>;
Signature: #x // (Ljava/lang/Class<*>;)V
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1103,13 +1279,18 @@
x: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1125,6 +1306,11 @@
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
@@ -1132,6 +1318,11 @@
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
@@ -1140,9 +1331,9 @@
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1158,6 +1349,11 @@
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
@@ -1165,6 +1361,11 @@
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
@@ -1193,13 +1394,16 @@
x: putstatic #x // Field sObject:Ljava/lang/Object;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
@@ -1221,6 +1425,11 @@
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
@@ -1228,6 +1437,11 @@
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
@@ -1235,6 +1449,11 @@
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
@@ -1242,6 +1461,9 @@
private final java.lang.String mLongName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1249,6 +1471,9 @@
private final java.lang.String mShortName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1256,6 +1481,11 @@
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;
@@ -1272,6 +1502,11 @@
x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;"
x: areturn
LineNumberTable:
+ 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;
@@ -1292,6 +1527,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 10 0 name Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -1321,6 +1561,11 @@
11 18 3 longName Ljava/lang/String;
11 18 4 shortName Ljava/lang/String;
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
@@ -1342,6 +1587,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1363,6 +1613,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1393,6 +1648,11 @@
x: aastore
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1435,14 +1695,19 @@
x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1458,6 +1723,11 @@
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
@@ -1465,6 +1735,11 @@
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
@@ -1472,6 +1747,11 @@
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;
@@ -1488,6 +1768,11 @@
x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;"
x: areturn
LineNumberTable:
+ 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;
@@ -1508,6 +1793,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 10 0 name Ljava/lang/String;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -1529,6 +1819,11 @@
Start Length Slot Name Signature
11 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
Signature: #x // ()V
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1552,6 +1847,11 @@
x: aastore
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -1582,14 +1882,19 @@
x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
x: return
LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1629,6 +1934,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int testException();
descriptor: ()I
@@ -1662,13 +1972,18 @@
LocalVariableTable:
Start Length Slot Name Signature
22 11 0 e Ljava/lang/Exception;
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -1684,10 +1999,18 @@
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
private static {};
descriptor: ()V
@@ -1725,6 +2048,11 @@
LocalVariableTable:
Start Length Slot Name Signature
11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addOne(int);
descriptor: (I)I
@@ -1745,6 +2073,11 @@
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
@@ -1771,6 +2104,9 @@
Start Length Slot Name Signature
26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
26 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int addTwo(int);
descriptor: (I)I
@@ -1791,6 +2127,13 @@
Start Length Slot Name Signature
11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
11 4 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddThree(int);
descriptor: (I)I
@@ -1810,6 +2153,13 @@
LocalVariableTable:
Start Length Slot Name Signature
11 4 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -1833,6 +2183,11 @@
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;
@@ -1851,13 +2206,18 @@
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
}
SourceFile: "TinyFrameworkForTextPolicy.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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
@@ -1871,6 +2231,11 @@
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
@@ -1879,6 +2244,11 @@
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
@@ -1903,6 +2273,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -1924,6 +2299,11 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
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
@@ -1942,6 +2322,11 @@
x: areturn
LineNumberTable:
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
@@ -1960,6 +2345,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1975,6 +2365,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -1990,6 +2385,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -2005,6 +2405,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -2023,6 +2428,9 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ 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
@@ -2030,9 +2438,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -2073,6 +2481,11 @@
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
@@ -2081,6 +2494,11 @@
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
@@ -2105,6 +2523,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -2126,6 +2549,11 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
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
@@ -2144,6 +2572,11 @@
x: areturn
LineNumberTable:
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
@@ -2162,6 +2595,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -2177,6 +2615,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -2192,6 +2635,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ 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;
@@ -2207,6 +2655,11 @@
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
static {};
descriptor: ()V
@@ -2225,6 +2678,9 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ RuntimeVisibleAnnotations:
+ 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
@@ -2232,9 +2688,9 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
@@ -2271,10 +2727,15 @@
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: 9, attributes: 3
+ interfaces: 0, fields: 1, methods: 11, attributes: 3
int value;
descriptor: I
flags: (0x0000)
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -2303,15 +2764,32 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int nativeAddTwo(int);
descriptor: (I)I
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
- stack=1, locals=1, args_size=1
- x: iload_0
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
- x: ireturn
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ x: ldc #x // String nativeAddTwo
+ 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: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ x: ireturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -2330,16 +2808,33 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
- x: lload_0
- x: lload_2
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
- x: lreturn
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ x: ldc #x // String nativeLongPlus
+ 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: lload_0
+ x: lload_2
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ x: lreturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -2360,6 +2855,11 @@
Start Length Slot Name Signature
11 6 0 arg1 J
11 6 2 arg2 J
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public void setValue(int);
descriptor: (I)V
@@ -2380,16 +2880,33 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
11 6 1 v I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int nativeNonStaticAddToValue(int);
descriptor: (I)I
flags: (0x0001) ACC_PUBLIC
Code:
- stack=2, locals=2, args_size=2
- x: aload_0
- x: iload_1
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
- x: ireturn
+ stack=4, locals=2, args_size=2
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ x: ldc #x // String nativeNonStaticAddToValue
+ 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: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
+ x: ireturn
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ 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
@@ -2410,13 +2927,72 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
11 6 1 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+ public static void nativeStillNotSupported();
+ 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
+ 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: athrow
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ 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 ()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: athrow
+ LineNumberTable:
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -2466,6 +3042,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -2491,6 +3070,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 4 0 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -2517,6 +3099,9 @@
Start Length Slot Name Signature
26 4 0 arg1 J
26 4 2 arg2 J
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
@@ -2544,11 +3129,14 @@
Start Length Slot Name Signature
26 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
26 7 1 arg I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkNative_host.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -2564,6 +3152,9 @@
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.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -2596,6 +3187,9 @@
Start Length Slot Name Signature
11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2620,6 +3214,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2644,6 +3241,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -2652,7 +3252,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2690,6 +3290,9 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2714,6 +3317,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2738,6 +3344,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -2746,7 +3355,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2760,6 +3369,9 @@
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.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -2792,6 +3404,9 @@
Start Length Slot Name Signature
11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2816,6 +3431,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2840,6 +3458,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -2848,7 +3469,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2886,6 +3507,9 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2910,6 +3534,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -2934,6 +3561,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -2942,7 +3572,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -2956,6 +3586,11 @@
public int value;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -2988,15 +3623,20 @@
Start Length Slot Name Signature
11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
11 10 1 x I
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -3010,10 +3650,20 @@
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
private static {};
descriptor: ()V
@@ -3049,15 +3699,20 @@
Start Length Slot Name Signature
11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
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
}
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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -3098,6 +3753,9 @@
LocalVariableTable:
Start Length Slot Name Signature
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -3122,6 +3780,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -3146,6 +3807,9 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ RuntimeVisibleAnnotations:
+ 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
@@ -3155,7 +3819,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -3169,6 +3833,11 @@
public int value;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -3200,6 +3869,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -3217,6 +3891,11 @@
x: areturn
LineNumberTable:
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
@@ -3224,9 +3903,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -3269,6 +3948,11 @@
Start Length Slot Name Signature
11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
11 6 1 x I
+ 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
@@ -3276,9 +3960,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 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"
@@ -3293,11 +3977,21 @@
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
@@ -3322,6 +4016,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -3343,6 +4042,11 @@
Start Length Slot Name Signature
11 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
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;
@@ -3360,6 +4064,11 @@
x: areturn
LineNumberTable:
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
@@ -3380,6 +4089,11 @@
x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
+ 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
@@ -3394,9 +4108,9 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -3446,6 +4160,11 @@
LocalVariableTable:
Start Length Slot Name Signature
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
public static int foo(int);
descriptor: (I)I
@@ -3467,13 +4186,18 @@
LocalVariableTable:
Start Length Slot Name Signature
11 12 0 value I
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
@@ -3489,6 +4213,9 @@
private final int mValue;
descriptor: I
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
private static {};
descriptor: ()V
@@ -3527,6 +4254,9 @@
Start Length Slot Name Signature
26 10 0 this Lcom/supported/UnsupportedClass;
26 10 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int getValue();
descriptor: ()I
@@ -3551,11 +4281,14 @@
LocalVariableTable:
Start Length Slot Name Signature
26 5 0 this Lcom/supported/UnsupportedClass;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -3600,6 +4333,11 @@
Start Length Slot Name Signature
11 14 0 this Lcom/unsupported/UnsupportedClass;
11 14 1 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
public int getValue();
descriptor: ()I
@@ -3620,13 +4358,18 @@
LocalVariableTable:
Start Length Slot Name Signature
11 10 0 this Lcom/unsupported/UnsupportedClass;
+ 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.HostStubGenProcessedStubClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
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 e7b5d9f..5a5e22d 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
@@ -16,6 +16,7 @@
package com.android.hoststubgen.test.tinyframework;
import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestThrow;
import android.hosttest.annotation.HostSideTestWholeClassStub;
@HostSideTestWholeClassStub
@@ -44,4 +45,11 @@
public int nativeNonStaticAddToValue_should_be_like_this(int arg) {
return TinyFrameworkNative_host.nativeNonStaticAddToValue(this, arg);
}
+
+ @HostSideTestThrow
+ public static native void nativeStillNotSupported();
+
+ public static void nativeStillNotSupported_should_be_like_this() {
+ throw new RuntimeException();
+ }
}
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 d350105..fc6b862 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,6 +17,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
import com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.SubClass;
import org.junit.Rule;
@@ -158,6 +160,32 @@
assertThat(instance.nativeNonStaticAddToValue(3)).isEqualTo(8);
}
+
+ @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.
+
+ final var clazz = TinyFrameworkNative.class;
+ final var method = clazz.getMethod("nativeStillNotSupported");
+
+ try {
+ method.invoke(null);
+
+ fail("java.lang.reflect.InvocationTargetException expected");
+
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ var inner = e.getCause();
+ assertThat(inner.getMessage()).contains("not supported on the host side");
+ }
+ }
+
@Test
public void testExitLog() {
thrown.expect(RuntimeException.class);
diff --git a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/asm/AsmUtilsTest.kt b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/asm/AsmUtilsTest.kt
new file mode 100644
index 0000000..6b46c84
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/asm/AsmUtilsTest.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.asm
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.objectweb.asm.Opcodes.ACC_PRIVATE
+import org.objectweb.asm.Opcodes.ACC_PROTECTED
+import org.objectweb.asm.Opcodes.ACC_PUBLIC
+import org.objectweb.asm.Opcodes.ACC_STATIC
+
+class AsmUtilsTest {
+ private fun checkGetDirectOuterClassName(input: String, expected: String?) {
+ assertThat(getDirectOuterClassName(input)).isEqualTo(expected)
+ }
+
+ @Test
+ fun testGetDirectOuterClassName() {
+ checkGetDirectOuterClassName("a", null)
+ checkGetDirectOuterClassName("a\$x", "a")
+ checkGetDirectOuterClassName("a.b.c\$x", "a.b.c")
+ checkGetDirectOuterClassName("a.b.c\$x\$y", "a.b.c\$x")
+ }
+
+ @Test
+ fun testVisibility() {
+ fun test(access: Int, expected: Visibility) {
+ assertThat(Visibility.fromAccess(access)).isEqualTo(expected)
+ }
+
+ test(ACC_PUBLIC or ACC_STATIC, Visibility.PUBLIC)
+ test(ACC_PRIVATE or ACC_STATIC, Visibility.PRIVATE)
+ test(ACC_PROTECTED or ACC_STATIC, Visibility.PROTECTED)
+ test(ACC_STATIC, Visibility.PACKAGE_PRIVATE)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/visitors/HelperTest.kt b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/visitors/HelperTest.kt
new file mode 100644
index 0000000..0ea90ed
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/visitors/HelperTest.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.MethodNode
+
+class HelperTest {
+ @Test
+ fun testCheckSubstitutionMethodCompatibility() {
+ val errors = object : HostStubGenErrors() {
+ override fun onErrorFound(message: String) {
+ // Don't throw
+ }
+ }
+
+ val cn = ClassNode().apply {
+ name = "ClassName"
+ methods = ArrayList()
+ }
+
+ val descriptor = "()V"
+
+ val staticPublic = MethodNode().apply {
+ name = "staticPublic"
+ access = Opcodes.ACC_STATIC or Opcodes.ACC_PUBLIC
+ desc = descriptor
+ cn.methods.add(this)
+ }
+
+ val staticPrivate = MethodNode().apply {
+ name = "staticPrivate"
+ access = Opcodes.ACC_STATIC or Opcodes.ACC_PRIVATE
+ desc = descriptor
+ cn.methods.add(this)
+ }
+
+ val nonStaticPublic = MethodNode().apply {
+ name = "nonStaticPublic"
+ access = Opcodes.ACC_PUBLIC
+ desc = descriptor
+ cn.methods.add(this)
+ }
+
+ val nonStaticPProtected = MethodNode().apply {
+ name = "nonStaticPProtected"
+ access = 0
+ desc = descriptor
+ cn.methods.add(this)
+ }
+
+ val classes = ClassNodes().apply {
+ addClass(cn)
+ }
+
+ fun check(from: MethodNode?, to: MethodNode?, expected: Boolean) {
+ assertThat(checkSubstitutionMethodCompatibility(
+ classes,
+ cn.name,
+ (from?.name ?: "**nonexistentmethodname**"),
+ (to?.name ?: "**nonexistentmethodname**"),
+ descriptor,
+ errors,
+ )).isEqualTo(expected)
+ }
+
+ check(staticPublic, staticPublic, true)
+ check(staticPrivate, staticPrivate, true)
+ check(nonStaticPublic, nonStaticPublic, true)
+ check(nonStaticPProtected, nonStaticPProtected, true)
+
+ check(staticPublic, null, false)
+ check(null, staticPublic, false)
+
+ check(staticPublic, nonStaticPublic, false)
+ check(nonStaticPublic, staticPublic, false)
+
+ check(staticPublic, staticPrivate, false)
+ check(staticPrivate, staticPublic, true)
+
+ check(nonStaticPublic, nonStaticPProtected, false)
+ check(nonStaticPProtected, nonStaticPublic, true)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh
index 4ea501e..222c874 100755
--- a/tools/hoststubgen/scripts/run-all-tests.sh
+++ b/tools/hoststubgen/scripts/run-all-tests.sh
@@ -18,11 +18,14 @@
# Move to the top directory of hoststubgen
cd ..
+ATEST_ARGS="--host"
+
# These tests are known to pass.
READY_TEST_MODULES=(
HostStubGenTest-framework-all-test-host-test
hoststubgen-test-tiny-test
CtsUtilTestCasesRavenwood
+ CtsOsTestCasesRavenwood # This one uses native sustitution, so let's run it too.
)
MUST_BUILD_MODULES=(
@@ -34,7 +37,7 @@
run m "${MUST_BUILD_MODULES[@]}"
# Run the hoststubgen unittests / etc
-run atest hoststubgentest hoststubgen-invoke-test
+run atest $ATEST_ARGS hoststubgentest hoststubgen-invoke-test
# Next, run the golden check. This should always pass too.
# The following scripts _should_ pass too, but they depend on the internal paths to soong generated
@@ -44,13 +47,13 @@
run ./hoststubgen/test-framework/run-test-without-atest.sh
run ./hoststubgen/test-tiny-framework/run-test-manually.sh
-run atest tiny-framework-dump-test
+run atest $ATEST_ARGS tiny-framework-dump-test
run ./scripts/build-framework-hostside-jars-and-extract.sh
# This script is already broken on goog/master
# run ./scripts/build-framework-hostside-jars-without-genrules.sh
# These tests should all pass.
-run atest ${READY_TEST_MODULES[*]}
+run atest $ATEST_ARGS ${READY_TEST_MODULES[*]}
-echo ""${0##*/}" finished, with no failures. Ready to submit!"
\ No newline at end of file
+echo ""${0##*/}" finished, with no failures. Ready to submit!"