diff options
1422 files changed, 33822 insertions, 12858 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 14658e5d9e4f..20471682dd2e 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -910,6 +910,8 @@ java_aconfig_library { aconfig_declarations { name: "android.service.notification.flags-aconfig", package: "android.service.notification", + exportable: true, + container: "system", srcs: ["core/java/android/service/notification/flags.aconfig"], } @@ -919,6 +921,18 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +java_aconfig_library { + name: "android.service.notification.flags-aconfig-export-java", + aconfig_declarations: "android.service.notification.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], + mode: "exported", + min_sdk_version: "30", + apex_available: [ + "//apex_available:platform", + "com.android.extservices", + ], +} + // Smartspace aconfig_declarations { name: "android.app.smartspace.flags-aconfig", diff --git a/Android.bp b/Android.bp index 870df5a5723e..5ada10d19f5d 100644 --- a/Android.bp +++ b/Android.bp @@ -386,7 +386,7 @@ java_defaults { // TODO(b/120066492): remove gps_debug and protolog.conf.json when the build // system propagates "required" properly. "gps_debug.conf", - "protolog.conf.json.gz", + "core.protolog.pb", "framework-res", // any install dependencies should go into framework-minus-apex-install-dependencies // rather than here to avoid bloating incremental build time @@ -508,7 +508,6 @@ java_library { lint: { baseline_filename: "lint-baseline.xml", }, - // For jarjar repackaging jarjar_prefix: "com.android.internal.hidden_from_bootclasspath", } diff --git a/INPUT_OWNERS b/INPUT_OWNERS index 44b2f3805495..06ead06fc13a 100644 --- a/INPUT_OWNERS +++ b/INPUT_OWNERS @@ -1,4 +1,6 @@ # Bug component: 136048 +arpitks@google.com +asmitapoddar@google.com hcutts@google.com joseprio@google.com michaelwr@google.com @@ -32,6 +32,7 @@ per-file **.bp,**.mk = hansson@google.com, joeo@google.com, lamontjones@google.c per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS +per-file INPUT_OWNERS = file:/INPUT_OWNERS per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS per-file SQLITE_OWNERS = file:/SQLITE_OWNERS diff --git a/Ravenwood.bp b/Ravenwood.bp index 2df6d5811d44..4e360759c137 100644 --- a/Ravenwood.bp +++ b/Ravenwood.bp @@ -197,6 +197,9 @@ android_ravenwood_libgroup { "mockito-ravenwood-prebuilt", "inline-mockito-ravenwood-prebuilt", ], + jni_libs: [ + "libandroid_runtime", + ], } android_ravenwood_libgroup { diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp index 8b55e071e715..558629537253 100644 --- a/apex/jobscheduler/service/Android.bp +++ b/apex/jobscheduler/service/Android.bp @@ -28,6 +28,7 @@ java_library { static_libs: [ "modules-utils-fastxmlserializer", + "service-jobscheduler-alarm.flags-aconfig-java", "service-jobscheduler-job.flags-aconfig-java", ], diff --git a/apex/jobscheduler/service/aconfig/Android.bp b/apex/jobscheduler/service/aconfig/Android.bp index 3ba7aa201d27..4db39dc1976b 100644 --- a/apex/jobscheduler/service/aconfig/Android.bp +++ b/apex/jobscheduler/service/aconfig/Android.bp @@ -27,3 +27,15 @@ java_aconfig_library { aconfig_declarations: "service-job.flags-aconfig", visibility: ["//frameworks/base:__subpackages__"], } + +// Alarm +aconfig_declarations { + name: "alarm_flags", + package: "com.android.server.alarm", + srcs: ["alarm.aconfig"], +} + +java_aconfig_library { + name: "service-jobscheduler-alarm.flags-aconfig-java", + aconfig_declarations: "alarm_flags", +} diff --git a/apex/jobscheduler/service/aconfig/alarm.aconfig b/apex/jobscheduler/service/aconfig/alarm.aconfig new file mode 100644 index 000000000000..3b9b4e70b310 --- /dev/null +++ b/apex/jobscheduler/service/aconfig/alarm.aconfig @@ -0,0 +1,11 @@ +package: "com.android.server.alarm" + +flag { + name: "use_frozen_state_to_drop_listener_alarms" + namespace: "backstage_power" + description: "Use frozen state callback to drop listener alarms for cached apps" + bug: "324470945" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 696c3178a4f4..4832ea624bd7 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -893,8 +893,9 @@ public class DeviceIdleController extends SystemService } // Fall through when quick doze is not requested. - if (!mIsOffBody) { - // Quick doze was not requested and device is on body so turn the device active. + if (!mIsOffBody && !mForceIdle) { + // Quick doze wasn't requested, doze wasn't forced and device is on body + // so turn the device active. mActiveReason = ACTIVE_REASON_ONBODY; becomeActiveLocked("on_body", Process.myUid()); } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 39de0af3c8d0..e728a2c55765 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -16,6 +16,7 @@ package com.android.server.alarm; +import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; @@ -75,6 +76,7 @@ import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.app.Activity; +import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AlarmManager; @@ -103,6 +105,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -145,6 +148,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.LocalLog; @@ -293,6 +297,7 @@ public class AlarmManagerService extends SystemService { private final Injector mInjector; int mBroadcastRefCount = 0; + boolean mUseFrozenStateToDropListenerAlarms; MetricsHelper mMetricsHelper; PowerManager.WakeLock mWakeLock; SparseIntArray mAlarmsPerUid = new SparseIntArray(); @@ -1856,15 +1861,47 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); + mHandler = new AlarmHandler(); + mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithFgsForAlarmClock.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false); mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); + mMetricsHelper = new MetricsHelper(getContext(), mLock); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); + mUseFrozenStateToDropListenerAlarms = Flags.useFrozenStateToDropListenerAlarms(); + if (mUseFrozenStateToDropListenerAlarms) { + final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> { + final int size = frozenStates.length; + if (uids.length != size) { + Slog.wtf(TAG, "Got different length arrays in frozen state callback!" + + " uids.length: " + uids.length + " frozenStates.length: " + size); + // Cannot process received data in any meaningful way. + return; + } + final IntArray affectedUids = new IntArray(); + for (int i = 0; i < size; i++) { + if (frozenStates[i] != UID_FROZEN_STATE_FROZEN) { + continue; + } + if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, + uids[i])) { + continue; + } + affectedUids.add(uids[i]); + } + if (affectedUids.size() > 0) { + removeExactListenerAlarms(affectedUids.toArray()); + } + }; + final ActivityManager am = getContext().getSystemService(ActivityManager.class); + am.registerUidFrozenStateChangedCallback(new HandlerExecutor(mHandler), callback); + } + mListenerDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { @@ -1880,7 +1917,6 @@ public class AlarmManagerService extends SystemService { }; synchronized (mLock) { - mHandler = new AlarmHandler(); mConstants = new Constants(mHandler); mAlarmStore = new LazyAlarmStore(); @@ -1960,6 +1996,21 @@ public class AlarmManagerService extends SystemService { publishBinderService(Context.ALARM_SERVICE, mService); } + private void removeExactListenerAlarms(int... whichUids) { + synchronized (mLock) { + removeAlarmsInternalLocked(a -> { + if (!ArrayUtils.contains(whichUids, a.uid) || a.listener == null + || a.windowLength != 0) { + return false; + } + Slog.w(TAG, "Alarm " + a.listenerTag + " being removed for " + + UserHandle.formatUid(a.uid) + ":" + a.packageName + + " because the app got frozen"); + return true; + }, REMOVE_REASON_LISTENER_CACHED); + } + } + void refreshExactAlarmCandidates() { final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages( Manifest.permission.SCHEDULE_EXACT_ALARM); @@ -3074,6 +3125,14 @@ public class AlarmManagerService extends SystemService { mConstants.dump(pw); pw.println(); + pw.println("Feature Flags:"); + pw.increaseIndent(); + pw.print(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS, + mUseFrozenStateToDropListenerAlarms); + pw.decreaseIndent(); + pw.println(); + pw.println(); + if (mConstants.USE_TARE_POLICY == EconomyManager.ENABLED_MODE_ON) { pw.println("TARE details:"); pw.increaseIndent(); @@ -4959,18 +5018,7 @@ public class AlarmManagerService extends SystemService { break; case REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED: uid = (Integer) msg.obj; - synchronized (mLock) { - removeAlarmsInternalLocked(a -> { - if (a.uid != uid || a.listener == null || a.windowLength != 0) { - return false; - } - // TODO (b/265195908): Change to .w once we have some data on breakages. - Slog.wtf(TAG, "Alarm " + a.listenerTag + " being removed for " - + UserHandle.formatUid(a.uid) + ":" + a.packageName - + " because the app went into cached state"); - return true; - }, REMOVE_REASON_LISTENER_CACHED); - } + removeExactListenerAlarms(uid); break; default: // nope, just ignore it @@ -5322,6 +5370,10 @@ public class AlarmManagerService extends SystemService { @Override public void handleUidCachedChanged(int uid, boolean cached) { + if (mUseFrozenStateToDropListenerAlarms) { + // Use ActivityManager#UidFrozenStateChangedCallback instead. + return; + } if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) { return; } 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 aec464d0e820..e96d07f44b34 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 @@ -55,6 +55,7 @@ import android.util.SparseArray; import android.util.SparseArrayMap; import android.util.SparseIntArray; import android.util.SparseLongArray; +import android.util.SparseSetArray; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -158,19 +159,6 @@ public final class FlexibilityController extends StateController { @GuardedBy("mLock") private final SparseLongArray mLastSeenConstraintTimesElapsed = new SparseLongArray(); - private DeviceIdleInternal mDeviceIdleInternal; - private final ArraySet<String> mPowerAllowlistedApps = new ArraySet<>(); - - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - switch (intent.getAction()) { - case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: - mHandler.post(FlexibilityController.this::updatePowerAllowlistCache); - break; - } - } - }; @VisibleForTesting @GuardedBy("mLock") final FlexibilityTracker mFlexibilityTracker; @@ -182,6 +170,7 @@ public final class FlexibilityController extends StateController { private final FcHandler mHandler; @VisibleForTesting final PrefetchController mPrefetchController; + private final SpecialAppTracker mSpecialAppTracker; /** * Stores the beginning of prefetch jobs lifecycle per app as a maximum of @@ -355,16 +344,16 @@ public final class FlexibilityController extends StateController { mPercentsToDropConstraints = FcConfig.DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; mPrefetchController = prefetchController; + mSpecialAppTracker = new SpecialAppTracker(); if (mFlexibilityEnabled) { - registerBroadcastReceiver(); + mSpecialAppTracker.startTracking(); } } @Override public void onSystemServicesReady() { - mDeviceIdleInternal = LocalServices.getService(DeviceIdleInternal.class); - mHandler.post(FlexibilityController.this::updatePowerAllowlistCache); + mSpecialAppTracker.onSystemServicesReady(); } @Override @@ -453,6 +442,7 @@ public final class FlexibilityController extends StateController { final int userId = UserHandle.getUserId(uid); mPrefetchLifeCycleStart.delete(userId, packageName); mJobScoreTrackers.delete(uid, packageName); + mSpecialAppTracker.onAppRemoved(userId, packageName); for (int i = mJobsToCheck.size() - 1; i >= 0; --i) { final JobStatus js = mJobsToCheck.valueAt(i); if ((js.getSourceUid() == uid && js.getSourcePackageName().equals(packageName)) @@ -466,6 +456,7 @@ public final class FlexibilityController extends StateController { @GuardedBy("mLock") public void onUserRemovedLocked(int userId) { mPrefetchLifeCycleStart.delete(userId); + mSpecialAppTracker.onUserRemoved(userId); for (int u = mJobScoreTrackers.numMaps() - 1; u >= 0; --u) { final int uid = mJobScoreTrackers.keyAt(u); if (UserHandle.getUserId(uid) == userId) { @@ -496,9 +487,10 @@ public final class FlexibilityController extends StateController { // Only exclude DEFAULT+ priority jobs for BFGS+ apps || (mService.getUidBias(js.getSourceUid()) >= JobInfo.BIAS_BOUND_FOREGROUND_SERVICE && js.getEffectivePriority() >= PRIORITY_DEFAULT) - // For apps in the power allowlist, automatically exclude DEFAULT+ priority jobs. + // For special/privileged apps, automatically exclude DEFAULT+ priority jobs. || (js.getEffectivePriority() >= PRIORITY_DEFAULT - && mPowerAllowlistedApps.contains(js.getSourcePackageName())) + && mSpecialAppTracker.isSpecialApp( + js.getSourceUserId(), js.getSourcePackageName())) || hasEnoughSatisfiedConstraintsLocked(js) || mService.isCurrentlyRunningLocked(js); } @@ -827,39 +819,6 @@ public final class FlexibilityController extends StateController { mFcConfig.processConstantLocked(properties, key); } - private void registerBroadcastReceiver() { - IntentFilter filter = new IntentFilter(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); - mContext.registerReceiver(mBroadcastReceiver, filter); - } - - private void unregisterBroadcastReceiver() { - mContext.unregisterReceiver(mBroadcastReceiver); - } - - private void updatePowerAllowlistCache() { - if (mDeviceIdleInternal == null) { - return; - } - - // Don't call out to DeviceIdleController with the lock held. - final String[] allowlistedPkgs = mDeviceIdleInternal.getFullPowerWhitelistExceptIdle(); - final ArraySet<String> changedPkgs = new ArraySet<>(); - synchronized (mLock) { - changedPkgs.addAll(mPowerAllowlistedApps); - mPowerAllowlistedApps.clear(); - for (final String pkgName : allowlistedPkgs) { - mPowerAllowlistedApps.add(pkgName); - if (changedPkgs.contains(pkgName)) { - changedPkgs.remove(pkgName); - } else { - changedPkgs.add(pkgName); - } - } - mPackagesToCheck.addAll(changedPkgs); - mHandler.sendEmptyMessage(MSG_CHECK_PACKAGES); - } - } - @VisibleForTesting class FlexibilityTracker { final ArrayList<ArraySet<JobStatus>> mTrackedJobs; @@ -1343,12 +1302,12 @@ public final class FlexibilityController extends StateController { mFlexibilityEnabled = true; mPrefetchController .registerPrefetchChangedListener(mPrefetchChangedListener); - registerBroadcastReceiver(); + mSpecialAppTracker.startTracking(); } else { mFlexibilityEnabled = false; mPrefetchController .unRegisterPrefetchChangedListener(mPrefetchChangedListener); - unregisterBroadcastReceiver(); + mSpecialAppTracker.stopTracking(); } } break; @@ -1653,6 +1612,176 @@ public final class FlexibilityController extends StateController { return mFcConfig; } + private class SpecialAppTracker { + /** + * Lock for objects inside this class. This should never be held when attempting to acquire + * {@link #mLock}. It is fine to acquire this if already holding {@link #mLock}. + */ + private final Object mSatLock = new Object(); + + private DeviceIdleInternal mDeviceIdleInternal; + + /** Set of all apps that have been deemed special, keyed by user ID. */ + private final SparseSetArray<String> mSpecialApps = new SparseSetArray<>(); + @GuardedBy("mSatLock") + private final ArraySet<String> mPowerAllowlistedApps = new ArraySet<>(); + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: + mHandler.post(SpecialAppTracker.this::updatePowerAllowlistCache); + break; + } + } + }; + + public boolean isSpecialApp(final int userId, @NonNull String packageName) { + synchronized (mSatLock) { + if (mSpecialApps.contains(UserHandle.USER_ALL, packageName)) { + return true; + } + if (mSpecialApps.contains(userId, packageName)) { + return true; + } + } + return false; + } + + private boolean isSpecialAppInternal(final int userId, @NonNull String packageName) { + synchronized (mSatLock) { + if (mPowerAllowlistedApps.contains(packageName)) { + return true; + } + } + return false; + } + + private void onAppRemoved(final int userId, String packageName) { + synchronized (mSatLock) { + // Don't touch the USER_ALL set here. If the app is completely removed from the + // device, any list that affects USER_ALL should update and this would eventually + // be updated with those lists no longer containing the app. + mSpecialApps.remove(userId, packageName); + } + } + + private void onSystemServicesReady() { + mDeviceIdleInternal = LocalServices.getService(DeviceIdleInternal.class); + + synchronized (mLock) { + if (mFlexibilityEnabled) { + mHandler.post(SpecialAppTracker.this::updatePowerAllowlistCache); + } + } + } + + private void onUserRemoved(final int userId) { + synchronized (mSatLock) { + mSpecialApps.remove(userId); + } + } + + private void startTracking() { + IntentFilter filter = new IntentFilter( + PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + mContext.registerReceiver(mBroadcastReceiver, filter); + + updatePowerAllowlistCache(); + } + + private void stopTracking() { + mContext.unregisterReceiver(mBroadcastReceiver); + + synchronized (mSatLock) { + mPowerAllowlistedApps.clear(); + mSpecialApps.clear(); + } + } + + /** + * Update the processed special app set for the specified user ID, only looking at the + * specified set of apps. This method must <b>NEVER</b> be called while holding + * {@link #mSatLock}. + */ + private void updateSpecialAppSetUnlocked(final int userId, @NonNull ArraySet<String> pkgs) { + // This method may need to acquire mLock, so ensure that mSatLock isn't held to avoid + // lock inversion. + if (Thread.holdsLock(mSatLock)) { + throw new IllegalStateException("Must never hold local mSatLock"); + } + if (pkgs.size() == 0) { + return; + } + final ArraySet<String> changedPkgs = new ArraySet<>(); + + synchronized (mSatLock) { + for (int i = pkgs.size() - 1; i >= 0; --i) { + final String pkgName = pkgs.valueAt(i); + if (isSpecialAppInternal(userId, pkgName)) { + if (mSpecialApps.add(userId, pkgName)) { + changedPkgs.add(pkgName); + } + } else if (mSpecialApps.remove(userId, pkgName)) { + changedPkgs.add(pkgName); + } + } + } + + if (changedPkgs.size() > 0) { + synchronized (mLock) { + mPackagesToCheck.addAll(changedPkgs); + mHandler.sendEmptyMessage(MSG_CHECK_PACKAGES); + } + } + } + + private void updatePowerAllowlistCache() { + if (mDeviceIdleInternal == null) { + return; + } + + // Don't call out to DeviceIdleController with the lock held. + final String[] allowlistedPkgs = mDeviceIdleInternal.getFullPowerWhitelistExceptIdle(); + final ArraySet<String> changedPkgs = new ArraySet<>(); + synchronized (mSatLock) { + changedPkgs.addAll(mPowerAllowlistedApps); + mPowerAllowlistedApps.clear(); + for (String pkgName : allowlistedPkgs) { + mPowerAllowlistedApps.add(pkgName); + if (!changedPkgs.remove(pkgName)) { + // The package wasn't in the previous set of allowlisted apps. Add it + // since its state has changed. + changedPkgs.add(pkgName); + } + } + } + + // The full allowlist is currently user-agnostic, so use USER_ALL for these packages. + updateSpecialAppSetUnlocked(UserHandle.USER_ALL, changedPkgs); + } + + public void dump(@NonNull IndentingPrintWriter pw) { + pw.println("Special apps:"); + pw.increaseIndent(); + + synchronized (mSatLock) { + for (int u = 0; u < mSpecialApps.size(); ++u) { + pw.print(mSpecialApps.keyAt(u)); + pw.print(": "); + pw.println(mSpecialApps.valuesAt(u)); + } + + pw.println(); + pw.print("Power allowlisted packages: "); + pw.println(mPowerAllowlistedApps); + } + + pw.decreaseIndent(); + } + } + @Override @GuardedBy("mLock") public void dumpConstants(IndentingPrintWriter pw) { @@ -1690,8 +1819,7 @@ public final class FlexibilityController extends StateController { pw.decreaseIndent(); pw.println(); - pw.print("Power allowlisted packages: "); - pw.println(mPowerAllowlistedApps); + mSpecialAppTracker.dump(pw); pw.println(); mFlexibilityTracker.dump(pw, predicate, nowElapsed); diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index d79131ca5d7c..3b16cab06bab 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -183,6 +183,8 @@ public class Am extends BaseCommand { instrument.disableTestApiChecks = false; } else if (opt.equals("--no-isolated-storage")) { instrument.disableIsolatedStorage = true; + } else if (opt.equals("--no-logcat")) { + instrument.captureLogcat = false; } else if (opt.equals("--user")) { instrument.userId = parseUserArg(nextArgRequired()); } else if (opt.equals("--abi")) { diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java index e60593e8b633..e0d949e04a92 100644 --- a/cmds/am/src/com/android/commands/am/Instrument.java +++ b/cmds/am/src/com/android/commands/am/Instrument.java @@ -85,6 +85,7 @@ public class Instrument { public String profileFile = null; public boolean wait = false; public boolean rawMode = false; + public boolean captureLogcat = true; boolean protoStd = false; // write proto to stdout boolean protoFile = false; // write proto to a file String logPath = null; @@ -266,16 +267,18 @@ public class Instrument { proto.write(InstrumentationData.TestStatus.RESULT_CODE, resultCode); writeBundle(proto, InstrumentationData.TestStatus.RESULTS, results); - if (resultCode == STATUS_TEST_STARTED) { - // Logcat -T takes wall clock time (!?) - mTestStartMs = System.currentTimeMillis(); - } else { - if (mTestStartMs > 0) { - proto.write(InstrumentationData.TestStatus.LOGCAT, readLogcat(mTestStartMs)); + if (captureLogcat) { + if (resultCode == STATUS_TEST_STARTED) { + // Logcat -T takes wall clock time (!?) + mTestStartMs = System.currentTimeMillis(); + } else { + if (mTestStartMs > 0) { + proto.write(InstrumentationData.TestStatus.LOGCAT, + readLogcat(mTestStartMs)); + } + mTestStartMs = 0; } - mTestStartMs = 0; } - proto.end(testStatusToken); outputProto(proto); diff --git a/core/api/current.txt b/core/api/current.txt index e8eace1c51c8..386396c67c71 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10733,6 +10733,7 @@ package android.content { field public static final String DROPBOX_SERVICE = "dropbox"; field public static final String EUICC_SERVICE = "euicc"; field public static final String FILE_INTEGRITY_SERVICE = "file_integrity"; + field public static final String FINGERPRINT_SERVICE = "fingerprint"; field public static final String GAME_SERVICE = "game"; field public static final String GRAMMATICAL_INFLECTION_SERVICE = "grammatical_inflection"; field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; @@ -18053,6 +18054,24 @@ package android.graphics.pdf { method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } + public final class PdfRenderer implements java.lang.AutoCloseable { + ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException; + method public void close(); + method public int getPageCount(); + method public android.graphics.pdf.PdfRenderer.Page openPage(int); + method public boolean shouldScaleForPrinting(); + } + + public final class PdfRenderer.Page implements java.lang.AutoCloseable { + method public void close(); + method public int getHeight(); + method public int getIndex(); + method public int getWidth(); + method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int); + field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 + field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 + } + } package android.graphics.text { @@ -20363,6 +20382,54 @@ package android.hardware.display { } +package android.hardware.fingerprint { + + @Deprecated public class FingerprintManager { + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.USE_BIOMETRIC, android.Manifest.permission.USE_FINGERPRINT}) public void authenticate(@Nullable android.hardware.fingerprint.FingerprintManager.CryptoObject, @Nullable android.os.CancellationSignal, int, @NonNull android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, @Nullable android.os.Handler); + method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints(); + method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected(); + field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 + field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3 + field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2 + field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 + field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 + field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 + field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 + field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc + field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 + field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 + field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9 + field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb + field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 + field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 + field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa + field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 + } + + @Deprecated public abstract static class FingerprintManager.AuthenticationCallback { + ctor @Deprecated public FingerprintManager.AuthenticationCallback(); + method @Deprecated public void onAuthenticationError(int, CharSequence); + method @Deprecated public void onAuthenticationFailed(); + method @Deprecated public void onAuthenticationHelp(int, CharSequence); + method @Deprecated public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintManager.AuthenticationResult); + } + + @Deprecated public static class FingerprintManager.AuthenticationResult { + method @Deprecated public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject(); + } + + @Deprecated public static final class FingerprintManager.CryptoObject { + ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull java.security.Signature); + ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Cipher); + ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Mac); + method @Deprecated public javax.crypto.Cipher getCipher(); + method @Deprecated public javax.crypto.Mac getMac(); + method @Deprecated public java.security.Signature getSignature(); + } + +} + package android.hardware.input { public final class HostUsiVersion implements android.os.Parcelable { @@ -56279,7 +56346,7 @@ package android.view.inputmethod { method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View); method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String); method @FlaggedApi("android.view.inputmethod.use_zero_jank_proxy") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); - method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int); + method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent); method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]); method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo(); diff --git a/core/api/removed.txt b/core/api/removed.txt index c61f16333fe8..3c7c0d6e6ea1 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -35,7 +35,6 @@ package android.content { method @Deprecated @Nullable public String getFeatureId(); method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int); method public abstract java.io.File getSharedPreferencesPath(String); - field public static final String FINGERPRINT_SERVICE = "fingerprint"; } public class ContextWrapper extends android.content.Context { @@ -146,54 +145,6 @@ package android.hardware { } -package android.hardware.fingerprint { - - @Deprecated public class FingerprintManager { - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.USE_BIOMETRIC, android.Manifest.permission.USE_FINGERPRINT}) public void authenticate(@Nullable android.hardware.fingerprint.FingerprintManager.CryptoObject, @Nullable android.os.CancellationSignal, int, @NonNull android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, @Nullable android.os.Handler); - method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints(); - method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected(); - field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 - field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3 - field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2 - field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 - field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 - field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 - field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 - field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc - field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 - field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 - field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9 - field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb - field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 - field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 - field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 - field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa - field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 - } - - @Deprecated public abstract static class FingerprintManager.AuthenticationCallback { - ctor public FingerprintManager.AuthenticationCallback(); - method public void onAuthenticationError(int, CharSequence); - method public void onAuthenticationFailed(); - method public void onAuthenticationHelp(int, CharSequence); - method public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintManager.AuthenticationResult); - } - - @Deprecated public static class FingerprintManager.AuthenticationResult { - method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject(); - } - - @Deprecated public static final class FingerprintManager.CryptoObject { - ctor public FingerprintManager.CryptoObject(@NonNull java.security.Signature); - ctor public FingerprintManager.CryptoObject(@NonNull javax.crypto.Cipher); - ctor public FingerprintManager.CryptoObject(@NonNull javax.crypto.Mac); - method public javax.crypto.Cipher getCipher(); - method public javax.crypto.Mac getMac(); - method public java.security.Signature getSignature(); - } - -} - package android.media { public final class AudioFormat implements android.os.Parcelable { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 627b70355f50..dfd915b75572 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -327,7 +327,7 @@ package android { field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE"; field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER"; field public static final String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER"; - field @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; + field @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION"; field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM"; field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER"; @@ -1146,7 +1146,6 @@ package android.app { public static final class StatusBarManager.DisableInfo implements android.os.Parcelable { method public boolean areAllComponentsEnabled(); method public int describeContents(); - method public boolean isBackDisabled(); method public boolean isNavigateToHomeDisabled(); method public boolean isNotificationPeekingDisabled(); method public boolean isRecentsDisabled(); @@ -3339,9 +3338,9 @@ package android.app.wearable { public class WearableSensingManager { method @FlaggedApi("android.app.wearable.enable_data_request_observer_api") @Nullable public static android.app.wearable.WearableSensingDataRequest getDataRequestFromIntent(@NonNull android.content.Intent); + method @FlaggedApi("android.app.wearable.enable_provide_wearable_connection_api") @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void provideConnection(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void provideData(@NonNull android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void provideDataStream(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @FlaggedApi("android.app.wearable.enable_provide_wearable_connection_api") @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void provideWearableConnection(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("android.app.wearable.enable_data_request_observer_api") @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void registerDataRequestObserver(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("android.app.wearable.enable_hotword_wearable_sensing_api") @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void startHotwordRecognition(@Nullable android.content.ComponentName, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("android.app.wearable.enable_hotword_wearable_sensing_api") @RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) public void stopHotwordRecognition(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); @@ -7199,15 +7198,15 @@ package android.media { @FlaggedApi("android.media.audiopolicy.enable_fade_manager_configuration") public final class FadeManagerConfiguration implements android.os.Parcelable { method public int describeContents(); method @NonNull public java.util.List<android.media.AudioAttributes> getAudioAttributesWithVolumeShaperConfigs(); - method public static long getDefaultFadeInDurationMillis(); - method public static long getDefaultFadeOutDurationMillis(); - method public long getFadeInDelayForOffenders(); - method public long getFadeInDurationForAudioAttributes(@NonNull android.media.AudioAttributes); - method public long getFadeInDurationForUsage(int); + method @IntRange(from=1) public static long getDefaultFadeInDurationMillis(); + method @IntRange(from=1) public static long getDefaultFadeOutDurationMillis(); + method @IntRange(from=0) public long getFadeInDelayForOffenders(); + method @IntRange(from=0) public long getFadeInDurationForAudioAttributes(@NonNull android.media.AudioAttributes); + method @IntRange(from=0) public long getFadeInDurationForUsage(int); method @Nullable public android.media.VolumeShaper.Configuration getFadeInVolumeShaperConfigForAudioAttributes(@NonNull android.media.AudioAttributes); method @Nullable public android.media.VolumeShaper.Configuration getFadeInVolumeShaperConfigForUsage(int); - method public long getFadeOutDurationForAudioAttributes(@NonNull android.media.AudioAttributes); - method public long getFadeOutDurationForUsage(int); + method @IntRange(from=0) public long getFadeOutDurationForAudioAttributes(@NonNull android.media.AudioAttributes); + method @IntRange(from=0) public long getFadeOutDurationForUsage(int); method @Nullable public android.media.VolumeShaper.Configuration getFadeOutVolumeShaperConfigForAudioAttributes(@NonNull android.media.AudioAttributes); method @Nullable public android.media.VolumeShaper.Configuration getFadeOutVolumeShaperConfigForUsage(int); method public int getFadeState(); @@ -7233,7 +7232,7 @@ package android.media { public static final class FadeManagerConfiguration.Builder { ctor public FadeManagerConfiguration.Builder(); - ctor public FadeManagerConfiguration.Builder(long, long); + ctor public FadeManagerConfiguration.Builder(@IntRange(from=1) long, @IntRange(from=1) long); ctor public FadeManagerConfiguration.Builder(@NonNull android.media.FadeManagerConfiguration); method @NonNull public android.media.FadeManagerConfiguration.Builder addFadeableUsage(int); method @NonNull public android.media.FadeManagerConfiguration.Builder addUnfadeableAudioAttributes(@NonNull android.media.AudioAttributes); @@ -7244,13 +7243,13 @@ package android.media { method @NonNull public android.media.FadeManagerConfiguration.Builder clearUnfadeableAudioAttributes(); method @NonNull public android.media.FadeManagerConfiguration.Builder clearUnfadeableContentTypes(); method @NonNull public android.media.FadeManagerConfiguration.Builder clearUnfadeableUids(); - method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDelayForOffenders(long); - method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDurationForAudioAttributes(@NonNull android.media.AudioAttributes, long); - method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDurationForUsage(int, long); + method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDelayForOffenders(@IntRange(from=0) long); + method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDurationForAudioAttributes(@NonNull android.media.AudioAttributes, @IntRange(from=0) long); + method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInDurationForUsage(int, @IntRange(from=0) long); method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInVolumeShaperConfigForAudioAttributes(@NonNull android.media.AudioAttributes, @Nullable android.media.VolumeShaper.Configuration); method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeInVolumeShaperConfigForUsage(int, @Nullable android.media.VolumeShaper.Configuration); - method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutDurationForAudioAttributes(@NonNull android.media.AudioAttributes, long); - method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutDurationForUsage(int, long); + method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutDurationForAudioAttributes(@NonNull android.media.AudioAttributes, @IntRange(from=0) long); + method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutDurationForUsage(int, @IntRange(from=0) long); method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutVolumeShaperConfigForAudioAttributes(@NonNull android.media.AudioAttributes, @Nullable android.media.VolumeShaper.Configuration); method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeOutVolumeShaperConfigForUsage(int, @Nullable android.media.VolumeShaper.Configuration); method @NonNull public android.media.FadeManagerConfiguration.Builder setFadeState(int); @@ -10422,8 +10421,7 @@ package android.nfc.cardemulation { @FlaggedApi("android.nfc.enable_nfc_mainline") public final class ApduServiceInfo implements android.os.Parcelable { ctor @FlaggedApi("android.nfc.enable_nfc_mainline") public ApduServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo, boolean) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilter(@NonNull String); - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilterToAutoTransact(@NonNull String); + method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilter(@NonNull String, boolean); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean defaultToObserveMode(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public int describeContents(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dump(@NonNull android.os.ParcelFileDescriptor, @NonNull java.io.PrintWriter, @NonNull String[]); @@ -11531,7 +11529,7 @@ package android.permission { public final class PermissionManager { method public int checkDeviceIdentifierAccess(@Nullable String, @Nullable String, @Nullable String, int, int); - method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public static int checkPermission(@NonNull String, @NonNull String, @NonNull String, int); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public int checkPermission(@NonNull String, @NonNull String, @NonNull String); method @RequiresPermission(value=android.Manifest.permission.UPDATE_APP_OPS_STATS, conditional=true) public int checkPermissionForDataDelivery(@NonNull String, @NonNull android.content.AttributionSource, @Nullable String); method @RequiresPermission(value=android.Manifest.permission.UPDATE_APP_OPS_STATS, conditional=true) public int checkPermissionForDataDeliveryFromDataSource(@NonNull String, @NonNull android.content.AttributionSource, @Nullable String); method public int checkPermissionForPreflight(@NonNull String, @NonNull android.content.AttributionSource); @@ -13765,7 +13763,7 @@ package android.service.wearable { method @FlaggedApi("android.app.wearable.enable_data_request_observer_api") @BinderThread public void onDataRequestObserverUnregistered(int, @NonNull String, @NonNull android.service.wearable.WearableSensingDataRequester, @NonNull java.util.function.Consumer<java.lang.Integer>); method @BinderThread public abstract void onDataStreamProvided(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @BinderThread public abstract void onQueryServiceStatus(@NonNull java.util.Set<java.lang.Integer>, @NonNull String, @NonNull java.util.function.Consumer<android.service.ambientcontext.AmbientContextDetectionServiceStatus>); - method @FlaggedApi("android.app.wearable.enable_provide_wearable_connection_api") @BinderThread public void onSecureWearableConnectionProvided(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @FlaggedApi("android.app.wearable.enable_provide_wearable_connection_api") @BinderThread public void onSecureConnectionProvided(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @BinderThread public abstract void onStartDetection(@NonNull android.app.ambientcontext.AmbientContextEventRequest, @NonNull String, @NonNull java.util.function.Consumer<android.service.ambientcontext.AmbientContextDetectionServiceStatus>, @NonNull java.util.function.Consumer<android.service.ambientcontext.AmbientContextDetectionResult>); method @FlaggedApi("android.app.wearable.enable_hotword_wearable_sensing_api") @BinderThread public void onStartHotwordRecognition(@NonNull java.util.function.Consumer<android.service.voice.HotwordAudioStream>, @NonNull java.util.function.Consumer<java.lang.Integer>); method public abstract void onStopDetection(@NonNull String); @@ -13946,12 +13944,24 @@ package android.telecom { } public final class DisconnectCause implements android.os.Parcelable { - ctor @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") public DisconnectCause(int, @NonNull CharSequence, @NonNull CharSequence, @NonNull String, int, int, int, @Nullable android.telephony.ims.ImsReasonInfo); method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @Nullable public android.telephony.ims.ImsReasonInfo getImsReasonInfo(); method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") public int getTelephonyDisconnectCause(); method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") public int getTelephonyPreciseDisconnectCause(); } + @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") public static final class DisconnectCause.Builder { + ctor public DisconnectCause.Builder(); + method @NonNull public android.telecom.DisconnectCause build(); + method @NonNull public android.telecom.DisconnectCause.Builder setCode(int); + method @NonNull public android.telecom.DisconnectCause.Builder setDescription(@Nullable CharSequence); + method @NonNull public android.telecom.DisconnectCause.Builder setImsReasonInfo(@Nullable android.telephony.ims.ImsReasonInfo); + method @NonNull public android.telecom.DisconnectCause.Builder setLabel(@Nullable CharSequence); + method @NonNull public android.telecom.DisconnectCause.Builder setReason(@NonNull String); + method @NonNull public android.telecom.DisconnectCause.Builder setTelephonyDisconnectCause(int); + method @NonNull public android.telecom.DisconnectCause.Builder setTelephonyPreciseDisconnectCause(int); + method @NonNull public android.telecom.DisconnectCause.Builder setTone(int); + } + public abstract class InCallService extends android.app.Service { method @Deprecated public android.telecom.Phone getPhone(); method @Deprecated public void onPhoneCreated(android.telecom.Phone); @@ -14192,7 +14202,8 @@ package android.telecom { method @Deprecated public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage(); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall(); - method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @RequiresPermission(allOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isInSelfManagedCall(@NonNull String, @NonNull android.os.UserHandle, boolean); + method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @RequiresPermission(allOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isInSelfManagedCall(@NonNull String, @NonNull android.os.UserHandle); + method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @RequiresPermission(allOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isInSelfManagedCall(@NonNull String, boolean); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle); field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e1e9d09f46fd..cdf232cd71ee 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1711,6 +1711,15 @@ package android.hardware.display { } +package android.hardware.fingerprint { + + @Deprecated public class FingerprintManager { + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties(); + } + +} + package android.hardware.hdmi { public final class HdmiControlServiceWrapper { diff --git a/core/api/test-removed.txt b/core/api/test-removed.txt index 2e44176f342e..d802177e249b 100644 --- a/core/api/test-removed.txt +++ b/core/api/test-removed.txt @@ -1,10 +1 @@ // Signature format: 2.0 -package android.hardware.fingerprint { - - @Deprecated public class FingerprintManager { - method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int); - method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties(); - } - -} - diff --git a/core/java/Android.bp b/core/java/Android.bp index eba500dd32b4..ab1c9a4ef48d 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -126,6 +126,7 @@ filegroup { srcs: [ "android/os/IExternalVibrationController.aidl", "android/os/IExternalVibratorService.aidl", + "android/os/ExternalVibrationScale.aidl", ], } @@ -527,14 +528,10 @@ filegroup { ], } -// common protolog sources without classes that rely on Android SDK -filegroup { - name: "protolog-common-no-android-src", +java_library { + name: "protolog-group", srcs: [ - ":protolog-common-src", - ], - exclude_srcs: [ - "com/android/internal/protolog/common/ProtoLog.java", + "com/android/internal/protolog/common/IProtoLogGroup.java", ], } @@ -547,13 +544,20 @@ filegroup { ], } +filegroup { + name: "protolog-impl", + srcs: [ + "com/android/internal/protolog/ProtoLogImpl.java", + ], +} + java_library { name: "protolog-lib", platform_apis: true, srcs: [ "com/android/internal/protolog/ProtoLogImpl.java", "com/android/internal/protolog/ProtoLogViewerConfigReader.java", - ":protolog-common-src", + ":perfetto_trace_javastream_protos", ], } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 251f82320ae5..57c67be7e625 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1002,6 +1002,9 @@ public class Activity extends ContextThemeWrapper new ActivityManager.TaskDescription(); private int mLastTaskDescriptionHashCode; + @ActivityInfo.ScreenOrientation + private int mLastRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSET; + protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused}; @SuppressWarnings("unused") @@ -7530,11 +7533,15 @@ public class Activity extends ContextThemeWrapper * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. */ public void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) { + if (requestedOrientation == mLastRequestedOrientation) { + return; + } if (mParent == null) { ActivityClient.getInstance().setRequestedOrientation(mToken, requestedOrientation); } else { mParent.setRequestedOrientation(requestedOrientation); } + mLastRequestedOrientation = requestedOrientation; } /** @@ -7548,6 +7555,9 @@ public class Activity extends ContextThemeWrapper */ @ActivityInfo.ScreenOrientation public int getRequestedOrientation() { + if (mLastRequestedOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSET) { + return mLastRequestedOrientation; + } if (mParent == null) { return ActivityClient.getInstance().getRequestedOrientation(mToken); } else { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ae556c91ab6d..074f7e993eb4 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -211,6 +211,7 @@ import android.view.contentcapture.IContentCaptureOptionsCallback; import android.view.translation.TranslationSpec; import android.view.translation.UiTranslationSpec; import android.webkit.WebView; +import android.window.ActivityWindowInfo; import android.window.ITaskFragmentOrganizer; import android.window.SizeConfigurationBuckets; import android.window.SplashScreen; @@ -603,6 +604,9 @@ public final class ActivityThread extends ClientTransactionHandler boolean hideForNow; Configuration createdConfig; Configuration overrideConfig; + @NonNull + private ActivityWindowInfo mActivityWindowInfo; + // Used for consolidating configs before sending on to Activity. private final Configuration tmpConfig = new Configuration(); // Callback used for updating activity override config and camera compat control state. @@ -670,7 +674,8 @@ public final class ActivityThread extends ClientTransactionHandler List<ReferrerIntent> pendingNewIntents, SceneTransitionInfo sceneTransitionInfo, boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client, IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble, - IBinder taskFragmentToken, IBinder initialCallerInfoAccessToken) { + IBinder taskFragmentToken, IBinder initialCallerInfoAccessToken, + ActivityWindowInfo activityWindowInfo) { this.token = token; this.assistToken = assistToken; this.shareableActivityToken = shareableActivityToken; @@ -691,6 +696,7 @@ public final class ActivityThread extends ClientTransactionHandler mSceneTransitionInfo = sceneTransitionInfo; mLaunchedFromBubble = launchedFromBubble; mTaskFragmentToken = taskFragmentToken; + mActivityWindowInfo = activityWindowInfo; init(); } @@ -779,6 +785,11 @@ public final class ActivityThread extends ClientTransactionHandler return activity != null && activity.mVisibleFromServer; } + @NonNull + public ActivityWindowInfo getActivityWindowInfo() { + return mActivityWindowInfo; + } + public String toString() { ComponentName componentName = intent != null ? intent.getComponent() : null; return "ActivityRecord{" @@ -5987,9 +5998,11 @@ public final class ActivityThread extends ClientTransactionHandler } @Override - public ActivityClientRecord prepareRelaunchActivity(IBinder token, - List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, - int configChanges, MergedConfiguration config, boolean preserveWindow) { + public ActivityClientRecord prepareRelaunchActivity(@NonNull IBinder token, + @Nullable List<ResultInfo> pendingResults, + @Nullable List<ReferrerIntent> pendingNewIntents, int configChanges, + @NonNull MergedConfiguration config, boolean preserveWindow, + @NonNull ActivityWindowInfo activityWindowInfo) { ActivityClientRecord target = null; boolean scheduleRelaunch = false; @@ -6030,14 +6043,15 @@ public final class ActivityThread extends ClientTransactionHandler target.createdConfig = config.getGlobalConfiguration(); target.overrideConfig = config.getOverrideConfiguration(); target.pendingConfigChanges |= configChanges; + target.mActivityWindowInfo = activityWindowInfo; } return scheduleRelaunch ? target : null; } @Override - public void handleRelaunchActivity(ActivityClientRecord tmp, - PendingTransactionActions pendingActions) { + public void handleRelaunchActivity(@NonNull ActivityClientRecord tmp, + @NonNull PendingTransactionActions pendingActions) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -6117,7 +6131,8 @@ public final class ActivityThread extends ClientTransactionHandler r.activity.mChangingConfigurations = true; handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents, - pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity"); + pendingActions, tmp.startsNotResumed, tmp.overrideConfig, tmp.mActivityWindowInfo, + "handleRelaunchActivity"); } void scheduleRelaunchActivity(IBinder token) { @@ -6172,7 +6187,8 @@ public final class ActivityThread extends ClientTransactionHandler r.overrideConfig); final ActivityRelaunchItem activityRelaunchItem = ActivityRelaunchItem.obtain( r.token, null /* pendingResults */, null /* pendingIntents */, - 0 /* configChanges */, mergedConfiguration, r.mPreserveWindow); + 0 /* configChanges */, mergedConfiguration, r.mPreserveWindow, + r.getActivityWindowInfo()); // Make sure to match the existing lifecycle state in the end of the transaction. final ActivityLifecycleItem lifecycleRequest = TransactionExecutorHelper.getLifecycleRequestForCurrentState(r); @@ -6183,10 +6199,12 @@ public final class ActivityThread extends ClientTransactionHandler executeTransaction(transaction); } - private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges, - List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents, - PendingTransactionActions pendingActions, boolean startsNotResumed, - Configuration overrideConfig, String reason) { + private void handleRelaunchActivityInner(@NonNull ActivityClientRecord r, int configChanges, + @Nullable List<ResultInfo> pendingResults, + @Nullable List<ReferrerIntent> pendingIntents, + @NonNull PendingTransactionActions pendingActions, boolean startsNotResumed, + @NonNull Configuration overrideConfig, @NonNull ActivityWindowInfo activityWindowInfo, + @NonNull String reason) { // Preserve last used intent, it may be set from Activity#setIntent(). final Intent customIntent = r.activity.mIntent; // Need to ensure state is saved. @@ -6219,6 +6237,7 @@ public final class ActivityThread extends ClientTransactionHandler } r.startsNotResumed = startsNotResumed; r.overrideConfig = overrideConfig; + r.mActivityWindowInfo = activityWindowInfo; handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent); } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 16c7753c7f46..39900a03e560 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -74,6 +74,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.permission.PermissionGroupUsage; import android.permission.PermissionUsageHelper; +import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; @@ -99,7 +100,6 @@ import com.android.internal.util.DataClass; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Parcelling; import com.android.internal.util.Preconditions; -import com.android.media.flags.Flags; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -2077,7 +2077,8 @@ public class AppOpsManager { * @hide */ @SystemApi - @FlaggedApi(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL) + @FlaggedApi(com.android.media.flags.Flags + .FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL) public static final String OPSTR_MEDIA_ROUTING_CONTROL = "android:media_routing_control"; /** @@ -2243,7 +2244,7 @@ public class AppOpsManager { * * @hide */ - @FlaggedApi(android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED) + @FlaggedApi(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED) @SystemApi public static final String OPSTR_ACCESS_RESTRICTED_SETTINGS = "android:access_restricted_settings"; @@ -3432,7 +3433,8 @@ public class AppOpsManager { } } - public static final @android.annotation.NonNull Creator<PackageOps> CREATOR = new Creator<PackageOps>() { + public static final @android.annotation.NonNull Creator<PackageOps> CREATOR = + new Creator<PackageOps>() { @Override public PackageOps createFromParcel(Parcel source) { return new PackageOps(source); } @@ -7410,7 +7412,7 @@ public class AppOpsManager { * @param userId User id of the app whose Op changed. * @param persistentDeviceId persistent device id whose Op changed. */ - @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) default void onOpChanged(@NonNull String op, @NonNull String packageName, int userId, @NonNull String persistentDeviceId) { if (Objects.equals(persistentDeviceId, @@ -7480,7 +7482,7 @@ public class AppOpsManager { * @param attributionFlags the attribution flags for this operation. * @param attributionChainId the unique id of the attribution chain this op is a part of. */ - @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) default void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { @@ -7534,7 +7536,7 @@ public class AppOpsManager { * @param flags The flags of this op * @param result The result of the note. */ - @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) default void onOpNoted(@NonNull String op, int uid, @NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId, @OpFlags int flags, @Mode int result) { @@ -8361,14 +8363,26 @@ public class AppOpsManager { String attributionTag, int virtualDeviceId, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { executor.execute(() -> { - if (callback instanceof OnOpActiveChangedInternalListener) { - ((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op, - uid, packageName, virtualDeviceId, active); - } - if (sAppOpInfos[op].name != null) { - callback.onOpActiveChanged(sAppOpInfos[op].name, uid, packageName, - attributionTag, virtualDeviceId, active, attributionFlags, - attributionChainId); + if (Flags.deviceAwarePermissionApisEnabled()) { + if (callback instanceof OnOpActiveChangedInternalListener) { + ((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op, + uid, packageName, virtualDeviceId, active); + } + if (sAppOpInfos[op].name != null) { + callback.onOpActiveChanged(sAppOpInfos[op].name, uid, packageName, + attributionTag, virtualDeviceId, active, attributionFlags, + attributionChainId); + } + } else { + if (callback instanceof OnOpActiveChangedInternalListener) { + ((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op, + uid, packageName, active); + } + if (sAppOpInfos[op].name != null) { + callback.onOpActiveChanged(sAppOpInfos[op].name, uid, packageName, + attributionTag, active, attributionFlags, + attributionChainId); + } } }); } @@ -8613,9 +8627,13 @@ public class AppOpsManager { try { executor.execute(() -> { if (sAppOpInfos[op].name != null) { - listener.onOpNoted(sAppOpInfos[op].name, uid, packageName, - attributionTag, virtualDeviceId, - flags, mode); + if (Flags.deviceAwarePermissionApisEnabled()) { + listener.onOpNoted(sAppOpInfos[op].name, uid, packageName, + attributionTag, virtualDeviceId, flags, mode); + } else { + listener.onOpNoted(sAppOpInfos[op].name, uid, packageName, + attributionTag, flags, mode); + } } }); } finally { diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java index f6373d690793..6ad03135ea02 100644 --- a/core/java/android/app/AutomaticZenRule.java +++ b/core/java/android/app/AutomaticZenRule.java @@ -377,6 +377,9 @@ public final class AutomaticZenRule implements Parcelable { * Sets the {@link ZenDeviceEffects} associated to this rule. Device effects specify changes to * the device behavior that should apply while the rule is active, but are not directly related * to suppressing notifications (for example: disabling always-on display). + * + * <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule}, + * a {@code null} value here means the previous set of effects is retained. */ @FlaggedApi(Flags.FLAG_MODES_API) public void setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) { @@ -749,6 +752,9 @@ public final class AutomaticZenRule implements Parcelable { /** * Sets the zen policy. + * + * <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule}, + * a {@code null} value here means the previous policy is retained. */ public @NonNull Builder setZenPolicy(@Nullable ZenPolicy policy) { mPolicy = policy; @@ -759,6 +765,9 @@ public final class AutomaticZenRule implements Parcelable { * Sets the {@link ZenDeviceEffects} associated to this rule. Device effects specify changes * to the device behavior that should apply while the rule is active, but are not directly * related to suppressing notifications (for example: disabling always-on display). + * + * <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule}, + * a {@code null} value here means the previous set of effects is retained. */ @NonNull public Builder setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) { diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index b30067491a84..4c92dee6ff17 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -30,6 +30,7 @@ import android.content.res.Configuration; import android.os.IBinder; import android.util.MergedConfiguration; import android.view.SurfaceControl; +import android.window.ActivityWindowInfo; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.WindowContext; import android.window.WindowContextInfo; @@ -232,12 +233,15 @@ public abstract class ClientTransactionHandler { * @param config New configuration applied to the activity. * @param preserveWindow Whether the activity should try to reuse the window it created, * including the decor view after the relaunch. + * @param activityWindowInfo Window information about the relaunched Activity. * @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during * relaunch, or {@code null} if relaunch cancelled. */ - public abstract ActivityClientRecord prepareRelaunchActivity(IBinder token, - List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, - int configChanges, MergedConfiguration config, boolean preserveWindow); + public abstract ActivityClientRecord prepareRelaunchActivity(@NonNull IBinder token, + @Nullable List<ResultInfo> pendingResults, + @Nullable List<ReferrerIntent> pendingNewIntents, int configChanges, + @NonNull MergedConfiguration config, boolean preserveWindow, + @NonNull ActivityWindowInfo activityWindowInfo); /** * Perform activity relaunch. @@ -245,7 +249,7 @@ public abstract class ClientTransactionHandler { * @param pendingActions Pending actions to be used on later stages of activity transaction. * */ public abstract void handleRelaunchActivity(@NonNull ActivityClientRecord r, - PendingTransactionActions pendingActions); + @NonNull PendingTransactionActions pendingActions); /** * Report that relaunch request was handled. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 26f85f723bd9..1129f9dbdfeb 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -7543,6 +7543,7 @@ public class Notification implements Parcelable /** * @hide */ + @SuppressWarnings("HiddenAbstractMethod") public abstract boolean areNotificationsVisiblyDifferent(Style other); /** diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index e6e46ddaa420..301fef877d6c 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -1448,7 +1448,6 @@ public class StatusBarManager { * * @hide */ - @SystemApi public boolean isBackDisabled() { return mBack; } @@ -1862,38 +1861,38 @@ public class StatusBarManager { }; @DataClass.Generated( - time = 1707345957771L, + time = 1708625947132L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/app/StatusBarManager.java", - inputSignatures = "private boolean mStatusBarExpansion\nprivate " - + "boolean mNavigateHome\nprivate boolean mNotificationPeeking\nprivate " - + "boolean mRecents\nprivate boolean mBack\nprivate boolean " - + "mSearch\nprivate boolean mSystemIcons\nprivate boolean mClock\nprivate" - + " boolean mNotificationIcons\nprivate boolean mRotationSuggestion\n" + inputSignatures = "private boolean mStatusBarExpansion\nprivate boolean " + + "mNavigateHome\nprivate boolean mNotificationPeeking\nprivate " + + "boolean mRecents\nprivate boolean mBack\nprivate boolean mSearch\n" + + "private boolean mSystemIcons\nprivate boolean mClock\nprivate " + + "boolean mNotificationIcons\nprivate boolean mRotationSuggestion\n" + "private boolean mNotificationTicker\npublic " + "@android.annotation.SystemApi boolean isStatusBarExpansionDisabled()\n" + "public void setStatusBarExpansionDisabled(boolean)\npublic " - + "@android.annotation.SystemApi boolean isNavigateToHomeDisabled()\n" - + "public void setNavigationHomeDisabled(boolean)\npublic " - + "@android.annotation.SystemApi boolean isNotificationPeekingDisabled()\n" - + "public void setNotificationPeekingDisabled(boolean)\npublic " + + "@android.annotation.SystemApi boolean isNavigateToHomeDisabled()\npublic" + + " void setNavigationHomeDisabled(boolean)\npublic " + + "@android.annotation.SystemApi boolean isNotificationPeekingDisabled()" + + "\npublic void setNotificationPeekingDisabled(boolean)\npublic " + "@android.annotation.SystemApi boolean isRecentsDisabled()\npublic " - + "void setRecentsDisabled(boolean)\npublic @android.annotation.SystemApi " - + "boolean isBackDisabled()\npublic void setBackDisabled(boolean)\npublic " + + "void setRecentsDisabled(boolean)\npublic boolean isBackDisabled()" + + "\npublic void setBackDisabled(boolean)\npublic " + "@android.annotation.SystemApi boolean isSearchDisabled()\npublic " + "void setSearchDisabled(boolean)\npublic boolean " - + "areSystemIconsDisabled()\npublic void setSystemIconsDisabled(boolean)" - + "\npublic boolean isClockDisabled()\npublic " - + "void setClockDisabled(boolean)\npublic " - + "boolean areNotificationIconsDisabled()\npublic " - + "void setNotificationIconsDisabled(boolean)\npublic boolean " + + "areSystemIconsDisabled()\npublic void setSystemIconsDisabled(boolean)\n" + + "public boolean isClockDisabled()\npublic " + + "void setClockDisabled(boolean)\npublic boolean " + + "areNotificationIconsDisabled()\npublic void " + + "setNotificationIconsDisabled(boolean)\npublic boolean " + "isNotificationTickerDisabled()\npublic void " + "setNotificationTickerDisabled(boolean)\npublic " + "@android.annotation.TestApi boolean isRotationSuggestionDisabled()\n" + "public void setRotationSuggestionDisabled(boolean)\npublic " - + "@android.annotation.SystemApi boolean areAllComponentsEnabled()\n" - + "public void setEnableAll()\npublic boolean areAllComponentsDisabled()" - + "\npublic void setDisableAll()\npublic @android.annotation.NonNull " + + "@android.annotation.SystemApi boolean areAllComponentsEnabled()\npublic" + + " void setEnableAll()\npublic boolean areAllComponentsDisabled()\n" + + "public void setDisableAll()\npublic @android.annotation.NonNull " + "@java.lang.Override java.lang.String toString()\npublic " + "android.util.Pair<java.lang.Integer,java.lang.Integer> toFlags()\n" + "class DisableInfo extends java.lang.Object implements " diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 83fb393da125..02d694436bfe 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -981,12 +981,12 @@ public class WallpaperManager { /** * <strong> Important note: </strong> * <ul> - * <li>Up to version S, this method requires the + * <li>Up to Android 12, this method requires the * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li> - * <li>Starting in T, directly accessing the wallpaper is not possible anymore, + * <li>Starting in Android 13, directly accessing the wallpaper is not possible anymore, * instead the default system wallpaper is returned - * (some versions of T may throw a {@code SecurityException}).</li> - * <li>From version U, this method should not be used + * (some versions of Android 13 may throw a {@code SecurityException}).</li> + * <li>From Android 14, this method should not be used * and will always throw a {@code SecurityException}.</li> * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions. </li> @@ -1265,12 +1265,12 @@ public class WallpaperManager { /** * <strong> Important note: </strong> * <ul> - * <li>Up to version S, this method requires the + * <li>Up to Android 12, this method requires the * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li> - * <li>Starting in T, directly accessing the wallpaper is not possible anymore, + * <li>Starting in Android 13, directly accessing the wallpaper is not possible anymore, * instead the default system wallpaper is returned - * (some versions of T may throw a {@code SecurityException}).</li> - * <li>From version U, this method should not be used + * (some versions of Android 13 may throw a {@code SecurityException}).</li> + * <li>From Android 14, this method should not be used * and will always throw a {@code SecurityException}.</li> * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions. </li> @@ -1318,12 +1318,12 @@ public class WallpaperManager { /** * <strong> Important note: </strong> * <ul> - * <li>Up to version S, this method requires the + * <li>Up to Android 12, this method requires the * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li> - * <li>Starting in T, directly accessing the wallpaper is not possible anymore, + * <li>Starting in Android 13, directly accessing the wallpaper is not possible anymore, * instead the default wallpaper is returned - * (some versions of T may throw a {@code SecurityException}).</li> - * <li>From version U, this method should not be used + * (some versions of Android 13 may throw a {@code SecurityException}).</li> + * <li>From Android 14, this method should not be used * and will always throw a {@code SecurityException}.</li> * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions. </li> @@ -1677,12 +1677,12 @@ public class WallpaperManager { /** * <strong> Important note: </strong> * <ul> - * <li>Up to version S, this method requires the + * <li>Up to Android 12, this method requires the * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li> - * <li>Starting in T, directly accessing the wallpaper is not possible anymore, + * <li>Starting in Android 13, directly accessing the wallpaper is not possible anymore, * instead the default system wallpaper is returned - * (some versions of T may throw a {@code SecurityException}).</li> - * <li>From version U, this method should not be used + * (some versions of Android 13 may throw a {@code SecurityException}).</li> + * <li>From Android 14, this method should not be used * and will always throw a {@code SecurityException}.</li> * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions. </li> @@ -1904,14 +1904,14 @@ public class WallpaperManager { * caller doesn't have the appropriate permissions, this returns {@code null}. * * <p> - * Before Android U, this method requires the + * For devices running Android 13 or earlier, this method requires the * {@link android.Manifest.permission#QUERY_ALL_PACKAGES} permission. * </p> * * <p> - * Starting from Android U, in order to use this, apps should declare a {@code <queries>} tag - * with the action {@code "android.service.wallpaper.WallpaperService"}. Otherwise, - * this method will return {@code null} if the caller doesn't otherwise have + * For devices running Android 14 or later, in order to use this, apps should declare a + * {@code <queries>} tag with the action {@code "android.service.wallpaper.WallpaperService"}. + * Otherwise, this method will return {@code null} if the caller doesn't otherwise have * <a href="{@docRoot}training/package-visibility">visibility</a> of the wallpaper package. * </p> */ diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java index 29f657ec6ba7..16cb4ecc4cca 100644 --- a/core/java/android/app/admin/DevicePolicyCache.java +++ b/core/java/android/app/admin/DevicePolicyCache.java @@ -15,6 +15,9 @@ */ package android.app.admin; +import static android.app.admin.DevicePolicyManager.CONTENT_PROTECTION_DISABLED; +import static android.app.admin.DevicePolicyManager.ContentProtectionPolicy; + import android.annotation.UserIdInt; import com.android.server.LocalServices; @@ -59,6 +62,12 @@ public abstract class DevicePolicyCache { public abstract int getPermissionPolicy(@UserIdInt int userHandle); /** + * Caches {@link DevicePolicyManager#getContentProtectionPolicy(android.content.ComponentName)} + * of the given user. + */ + public abstract @ContentProtectionPolicy int getContentProtectionPolicy(@UserIdInt int userId); + + /** * True if there is an admin on the device who can grant sensor permissions. */ public abstract boolean canAdminGrantSensorsPermissions(); @@ -92,6 +101,11 @@ public abstract class DevicePolicyCache { } @Override + public @ContentProtectionPolicy int getContentProtectionPolicy(@UserIdInt int userId) { + return CONTENT_PROTECTION_DISABLED; + } + + @Override public boolean canAdminGrantSensorsPermissions() { return false; } diff --git a/core/java/android/app/admin/PolicySizeVerifier.java b/core/java/android/app/admin/PolicySizeVerifier.java index d5e8ea4525f3..792ebc6ad297 100644 --- a/core/java/android/app/admin/PolicySizeVerifier.java +++ b/core/java/android/app/admin/PolicySizeVerifier.java @@ -88,6 +88,10 @@ public class PolicySizeVerifier { * Throw if Parcelable contains any string that's too long to be serialized. */ public static void enforceMaxParcelableFieldsLength(Parcelable parcelable) { + // TODO(b/326662716) rework to protect against infinite recursion. + if (true) { + return; + } Class<?> clazz = parcelable.getClass(); Field[] fields = clazz.getDeclaredFields(); diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig index cbd8e5b2ec3e..10954aba955c 100644 --- a/core/java/android/app/admin/flags/flags.aconfig +++ b/core/java/android/app/admin/flags/flags.aconfig @@ -117,6 +117,9 @@ flag { namespace: "enterprise" description: "Exempt the default sms app of the context user for suspension when calling setPersonalAppsSuspended" bug: "309183330" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 9fa73627de05..fb1b17bd23d4 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -10,6 +10,7 @@ import android.annotation.SystemApi; import android.app.Activity; import android.content.ComponentName; import android.content.Context; +import android.credentials.CredentialOption; import android.credentials.GetCredentialException; import android.credentials.GetCredentialRequest; import android.credentials.GetCredentialResponse; @@ -29,6 +30,7 @@ import android.os.PooledStringWriter; import android.os.RemoteException; import android.os.SystemClock; import android.service.autofill.FillRequest; +import android.service.credentials.CredentialProviderService; import android.text.InputType; import android.text.Spanned; import android.text.TextUtils; @@ -913,6 +915,7 @@ public class AssistStructure implements Parcelable { if ((flags&FLAGS_HAS_EXTRAS) != 0) { mExtras = in.readBundle(); } + mGetCredentialRequest = in.readTypedObject(GetCredentialRequest.CREATOR); } /** @@ -1149,6 +1152,7 @@ public class AssistStructure implements Parcelable { if ((flags&FLAGS_HAS_EXTRAS) != 0) { out.writeBundle(mExtras); } + out.writeTypedObject(mGetCredentialRequest, flags); return flags; } @@ -1287,11 +1291,7 @@ public class AssistStructure implements Parcelable { } /** - * - * @return - * * @hide - * */ @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) @Nullable @@ -2260,6 +2260,17 @@ public class AssistStructure implements Parcelable { @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) { mNode.mGetCredentialRequest = request; mNode.mGetCredentialCallback = callback; + for (CredentialOption option : request.getCredentialOptions()) { + ArrayList<AutofillId> ids = option.getCandidateQueryData() + .getParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class); + ids = ids != null ? ids : new ArrayList<>(); + if (!ids.contains(getAutofillId())) { + ids.add(getAutofillId()); + } + option.getCandidateQueryData() + .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids); + } } @Override @@ -2569,7 +2580,7 @@ public class AssistStructure implements Parcelable { } AutofillId autofillId = node.getAutofillId(); if (autofillId == null) { - Log.i(TAG, prefix + " NO autofill ID"); + Log.i(TAG, prefix + " No autofill ID"); } else { Log.i(TAG, prefix + " Autofill info: id= " + autofillId + ", type=" + node.getAutofillType() @@ -2584,7 +2595,7 @@ public class AssistStructure implements Parcelable { } GetCredentialRequest getCredentialRequest = node.getCredentialManagerRequest(); if (getCredentialRequest == null) { - Log.i(TAG, prefix + " NO Credential Manager Request"); + Log.i(TAG, prefix + " No Credential Manager Request"); } else { Log.i(TAG, prefix + " GetCredentialRequest: no. of options= " + getCredentialRequest.getCredentialOptions().size() diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java index cbb0ae784f82..6da871a74383 100644 --- a/core/java/android/app/servertransaction/ActivityRelaunchItem.java +++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java @@ -30,6 +30,7 @@ import android.os.Parcel; import android.os.Trace; import android.util.MergedConfiguration; import android.util.Slog; +import android.window.ActivityWindowInfo; import com.android.internal.content.ReferrerIntent; @@ -50,6 +51,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { private int mConfigChanges; private MergedConfiguration mConfig; private boolean mPreserveWindow; + private ActivityWindowInfo mActivityWindowInfo; /** * A record that was properly configured for relaunch. Execution will be cancelled if not @@ -64,7 +66,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { CompatibilityInfo.applyOverrideScaleIfNeeded(mConfig); } mActivityClientRecord = client.prepareRelaunchActivity(getActivityToken(), mPendingResults, - mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow); + mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow, mActivityWindowInfo); } @Override @@ -101,7 +103,8 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { public static ActivityRelaunchItem obtain(@NonNull IBinder activityToken, @Nullable List<ResultInfo> pendingResults, @Nullable List<ReferrerIntent> pendingNewIntents, int configChanges, - @NonNull MergedConfiguration config, boolean preserveWindow) { + @NonNull MergedConfiguration config, boolean preserveWindow, + @NonNull ActivityWindowInfo activityWindowInfo) { ActivityRelaunchItem instance = ObjectPool.obtain(ActivityRelaunchItem.class); if (instance == null) { instance = new ActivityRelaunchItem(); @@ -113,6 +116,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { instance.mConfigChanges = configChanges; instance.mConfig = new MergedConfiguration(config); instance.mPreserveWindow = preserveWindow; + instance.mActivityWindowInfo = new ActivityWindowInfo(activityWindowInfo); return instance; } @@ -126,6 +130,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { mConfig = null; mPreserveWindow = false; mActivityClientRecord = null; + mActivityWindowInfo = null; ObjectPool.recycle(this); } @@ -141,6 +146,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { dest.writeInt(mConfigChanges); dest.writeTypedObject(mConfig, flags); dest.writeBoolean(mPreserveWindow); + dest.writeTypedObject(mActivityWindowInfo, flags); } /** Read from Parcel. */ @@ -151,6 +157,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { mConfigChanges = in.readInt(); mConfig = in.readTypedObject(MergedConfiguration.CREATOR); mPreserveWindow = in.readBoolean(); + mActivityWindowInfo = in.readTypedObject(ActivityWindowInfo.CREATOR); } public static final @NonNull Creator<ActivityRelaunchItem> CREATOR = @@ -176,7 +183,8 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { return Objects.equals(mPendingResults, other.mPendingResults) && Objects.equals(mPendingNewIntents, other.mPendingNewIntents) && mConfigChanges == other.mConfigChanges && Objects.equals(mConfig, other.mConfig) - && mPreserveWindow == other.mPreserveWindow; + && mPreserveWindow == other.mPreserveWindow + && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo); } @Override @@ -188,6 +196,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { result = 31 * result + mConfigChanges; result = 31 * result + Objects.hashCode(mConfig); result = 31 * result + (mPreserveWindow ? 1 : 0); + result = 31 * result + Objects.hashCode(mActivityWindowInfo); return result; } @@ -198,6 +207,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { + ",pendingNewIntents=" + mPendingNewIntents + ",configChanges=" + mConfigChanges + ",config=" + mConfig - + ",preserveWindow" + mPreserveWindow + "}"; + + ",preserveWindow=" + mPreserveWindow + + ",activityWindowInfo=" + mActivityWindowInfo + "}"; } } diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 95f5ad0bd38f..f02cb212276b 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -42,6 +42,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.PersistableBundle; import android.os.Trace; +import android.window.ActivityWindowInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; @@ -81,6 +82,8 @@ public class LaunchActivityItem extends ClientTransactionItem { private boolean mLaunchedFromBubble; private IBinder mTaskFragmentToken; private IBinder mInitialCallerInfoAccessToken; + private ActivityWindowInfo mActivityWindowInfo; + /** * It is only non-null if the process is the first time to launch activity. It is only an * optimization for quick look up of the interface so the field is ignored for comparison. @@ -107,7 +110,7 @@ public class LaunchActivityItem extends ClientTransactionItem { mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mSceneTransitionInfo, mIsForward, mProfilerInfo, client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble, - mTaskFragmentToken, mInitialCallerInfoAccessToken); + mTaskFragmentToken, mInitialCallerInfoAccessToken, mActivityWindowInfo); client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -141,7 +144,8 @@ public class LaunchActivityItem extends ClientTransactionItem { boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken, @Nullable IActivityClientController activityClientController, @NonNull IBinder shareableActivityToken, boolean launchedFromBubble, - @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken) { + @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken, + @NonNull ActivityWindowInfo activityWindowInfo) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); @@ -156,7 +160,8 @@ public class LaunchActivityItem extends ClientTransactionItem { sceneTransitionInfo, isForward, profilerInfo != null ? new ProfilerInfo(profilerInfo) : null, assistToken, activityClientController, shareableActivityToken, - launchedFromBubble, taskFragmentToken, initialCallerInfoAccessToken); + launchedFromBubble, taskFragmentToken, initialCallerInfoAccessToken, + new ActivityWindowInfo(activityWindowInfo)); return instance; } @@ -171,7 +176,7 @@ public class LaunchActivityItem extends ClientTransactionItem { @Override public void recycle() { setValues(this, null, null, 0, null, null, null, 0, null, null, 0, null, null, null, null, - null, false, null, null, null, null, false, null, null); + null, false, null, null, null, null, false, null, null, null); ObjectPool.recycle(this); } @@ -203,6 +208,7 @@ public class LaunchActivityItem extends ClientTransactionItem { dest.writeBoolean(mLaunchedFromBubble); dest.writeStrongBinder(mTaskFragmentToken); dest.writeStrongBinder(mInitialCallerInfoAccessToken); + dest.writeTypedObject(mActivityWindowInfo, flags); } /** Read from Parcel. */ @@ -223,7 +229,8 @@ public class LaunchActivityItem extends ClientTransactionItem { in.readStrongBinder(), in.readBoolean(), in.readStrongBinder(), - in.readStrongBinder()); + in.readStrongBinder(), + in.readTypedObject(ActivityWindowInfo.CREATOR)); } public static final @NonNull Creator<LaunchActivityItem> CREATOR = new Creator<>() { @@ -264,7 +271,8 @@ public class LaunchActivityItem extends ClientTransactionItem { && Objects.equals(mShareableActivityToken, other.mShareableActivityToken) && Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken) && Objects.equals(mInitialCallerInfoAccessToken, - other.mInitialCallerInfoAccessToken); + other.mInitialCallerInfoAccessToken) + && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo); } @Override @@ -289,6 +297,7 @@ public class LaunchActivityItem extends ClientTransactionItem { result = 31 * result + Objects.hashCode(mShareableActivityToken); result = 31 * result + Objects.hashCode(mTaskFragmentToken); result = 31 * result + Objects.hashCode(mInitialCallerInfoAccessToken); + result = 31 * result + Objects.hashCode(mActivityWindowInfo); return result; } @@ -335,7 +344,9 @@ public class LaunchActivityItem extends ClientTransactionItem { + ",sceneTransitionInfo=" + mSceneTransitionInfo + ",profilerInfo=" + mProfilerInfo + ",assistToken=" + mAssistToken - + ",shareableActivityToken=" + mShareableActivityToken + "}"; + + ",shareableActivityToken=" + mShareableActivityToken + + ",activityWindowInfo=" + mActivityWindowInfo + + "}"; } // Using the same method to set and clear values to make sure we don't forget anything @@ -351,7 +362,8 @@ public class LaunchActivityItem extends ClientTransactionItem { @Nullable ProfilerInfo profilerInfo, @Nullable IBinder assistToken, @Nullable IActivityClientController activityClientController, @Nullable IBinder shareableActivityToken, boolean launchedFromBubble, - @Nullable IBinder taskFragmentToken, @Nullable IBinder initialCallerInfoAccessToken) { + @Nullable IBinder taskFragmentToken, @Nullable IBinder initialCallerInfoAccessToken, + @Nullable ActivityWindowInfo activityWindowInfo) { instance.mActivityToken = activityToken; instance.mIntent = intent; instance.mIdent = ident; @@ -375,5 +387,6 @@ public class LaunchActivityItem extends ClientTransactionItem { instance.mLaunchedFromBubble = launchedFromBubble; instance.mTaskFragmentToken = taskFragmentToken; instance.mInitialCallerInfoAccessToken = initialCallerInfoAccessToken; + instance.mActivityWindowInfo = activityWindowInfo; } } diff --git a/core/java/android/app/wearable/IWearableSensingManager.aidl b/core/java/android/app/wearable/IWearableSensingManager.aidl index f67802279e26..7d3b28511537 100644 --- a/core/java/android/app/wearable/IWearableSensingManager.aidl +++ b/core/java/android/app/wearable/IWearableSensingManager.aidl @@ -30,7 +30,7 @@ import android.os.SharedMemory; */ interface IWearableSensingManager { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE)") - void provideWearableConnection(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); + void provideConnection(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE)") void provideDataStream(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE)") diff --git a/core/java/android/app/wearable/WearableSensingManager.java b/core/java/android/app/wearable/WearableSensingManager.java index 637f6776bd1b..fd72c491bf16 100644 --- a/core/java/android/app/wearable/WearableSensingManager.java +++ b/core/java/android/app/wearable/WearableSensingManager.java @@ -127,7 +127,7 @@ public class WearableSensingManager { /** * The value of the status code that indicates an error occurred in the encrypted channel backed - * by the provided connection. See {@link #provideWearableConnection(ParcelFileDescriptor, + * by the provided connection. See {@link #provideConnection(ParcelFileDescriptor, * Executor, Consumer)}. */ @FlaggedApi(Flags.FLAG_ENABLE_PROVIDE_WEARABLE_CONNECTION_API) @@ -223,13 +223,13 @@ public class WearableSensingManager { */ @RequiresPermission(Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE) @FlaggedApi(Flags.FLAG_ENABLE_PROVIDE_WEARABLE_CONNECTION_API) - public void provideWearableConnection( + public void provideConnection( @NonNull ParcelFileDescriptor wearableConnection, @NonNull @CallbackExecutor Executor executor, @NonNull @StatusCode Consumer<Integer> statusConsumer) { try { RemoteCallback callback = createStatusCallback(executor, statusConsumer); - mService.provideWearableConnection(wearableConnection, callback); + mService.provideConnection(wearableConnection, callback); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 7505372fe295..f77ebc148070 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5068,7 +5068,6 @@ public abstract class Context { * {@link android.hardware.fingerprint.FingerprintManager} for handling management * of fingerprints. * - * @removed See {@link android.hardware.biometrics.BiometricPrompt} * @see #getSystemService(String) * @see android.hardware.fingerprint.FingerprintManager */ diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 22e233aebf36..ac80561c3b50 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -177,3 +177,10 @@ flag { description: "Enable the sensitive notifications toggle to be visible in the Private space settings page" bug: "317067050" } + +flag { + name: "enable_private_space_intent_redirection" + namespace: "profile_experiences" + description: "Enable Private Space telephony and SMS intent redirection to the main user" + bug: "325576602" +} diff --git a/core/java/android/credentials/GetCredentialResponse.java b/core/java/android/credentials/GetCredentialResponse.java index ea699b9a74e5..a1477ee1a43a 100644 --- a/core/java/android/credentials/GetCredentialResponse.java +++ b/core/java/android/credentials/GetCredentialResponse.java @@ -63,9 +63,6 @@ public final class GetCredentialResponse implements Parcelable { } /** - * - * @return - * * @hide */ public AutofillId getAutofillId() { diff --git a/core/java/android/credentials/flags.aconfig b/core/java/android/credentials/flags.aconfig index ef7b2594fd5d..09e59d315428 100644 --- a/core/java/android/credentials/flags.aconfig +++ b/core/java/android/credentials/flags.aconfig @@ -68,4 +68,18 @@ flag { name: "new_framework_metrics" description: "Enables new metrics fror 24Q3 / VIC" bug: "324291187" -}
\ No newline at end of file +} + +flag { + namespace: "credential_manager" + name: "clear_credentials_api_fix_enabled" + description: "Fixes bug in clearCredential API that causes indefinite suspension" + bug: "314926460" +} + +flag { + namespace: "credential_manager" + name: "hybrid_filter_fix_enabled" + description: "Removes capability check from hybrid implementation" + bug: "323923403" +} diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index b0f69f56cba7..81e321d96aa6 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -83,8 +83,7 @@ import javax.crypto.Mac; /** * A class that coordinates access to the fingerprint hardware. - * - * @removed See {@link BiometricPrompt} which shows a system-provided dialog upon starting + * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting * authentication. In a world where devices may have different types of biometric authentication, * it's much more realistic to have a system-provided authentication dialog since the method may * vary by vendor/device. @@ -95,6 +94,7 @@ import javax.crypto.Mac; @RequiresFeature(PackageManager.FEATURE_FINGERPRINT) public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants { private static final String TAG = "FingerprintManager"; + private static final boolean DEBUG = true; private static final int MSG_ENROLL_RESULT = 100; private static final int MSG_ACQUIRED = 101; private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; @@ -196,7 +196,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Retrieves a test session for FingerprintManager. - * * @hide */ @TestApi @@ -255,10 +254,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** - * A wrapper class for the crypto objects supported by FingerprintManager. Currently, the + * A wrapper class for the crypto objects supported by FingerprintManager. Currently the * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. - * - * @removed See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} + * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} */ @Deprecated public static final class CryptoObject extends android.hardware.biometrics.CryptoObject { @@ -332,8 +330,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, * CancellationSignal, int, AuthenticationCallback, Handler)}. - * - * @removed See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult} + * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult} */ @Deprecated public static class AuthenticationResult { @@ -395,8 +392,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * FingerprintManager#authenticate(CryptoObject, CancellationSignal, * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to * fingerprint events. - * - * @removed See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback} + * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback} */ @Deprecated public static abstract class AuthenticationCallback @@ -459,7 +455,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Callback structure provided for {@link #detectFingerprint(CancellationSignal, * FingerprintDetectionCallback, int, Surface)}. - * * @hide */ public interface FingerprintDetectionCallback { @@ -613,8 +608,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * by <a href="{@docRoot}training/articles/keystore.html">Android Keystore * facility</a>. * @throws IllegalStateException if the crypto primitive is not initialized. - * - * @removed See {@link BiometricPrompt#authenticate(CancellationSignal, Executor, + * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor, * BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate( * BiometricPrompt.CryptoObject, CancellationSignal, Executor, * BiometricPrompt.AuthenticationCallback)} @@ -629,7 +623,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Per-user version of authenticate. * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}. - * * @hide */ @Deprecated @@ -642,7 +635,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Per-user and per-sensor version of authenticate. * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}. - * * @hide */ @Deprecated @@ -659,7 +651,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Version of authenticate with additional options. - * * @hide */ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) @@ -707,7 +698,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Uses the fingerprint hardware to detect for the presence of a finger, without giving details * about accept/reject/lockout. - * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @@ -750,7 +740,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @param callback an object to receive enrollment events * @param shouldLogMetrics a flag that indicates if enrollment failure/success metrics * should be logged. - * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) @@ -821,7 +810,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first * enumerated sensor. - * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) @@ -836,7 +824,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Revokes the specified challenge. - * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) @@ -862,7 +849,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @param sensorId Sensor ID that this operation takes effect for * @param userId User ID that this operation takes effect for. * @param hardwareAuthToken An opaque token returned by password confirmation. - * * @hide */ @RequiresPermission(RESET_FINGERPRINT_LOCKOUT) @@ -900,7 +886,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Removes all fingerprint templates for the given user. - * * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) @@ -1020,7 +1005,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Forwards BiometricStateListener to FingerprintService * @param listener new BiometricStateListener being added - * * @hide */ public void registerBiometricStateListener(@NonNull BiometricStateListener listener) { @@ -1172,8 +1156,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** - * This is triggered by SideFpsEventHandler. - * + * This is triggered by SideFpsEventHandler * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @@ -1186,8 +1169,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * Determine if there is at least one fingerprint enrolled. * * @return true if at least one fingerprint is enrolled, false otherwise - * - * @removed See {@link BiometricPrompt} and + * @deprecated See {@link BiometricPrompt} and * {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS} */ @Deprecated @@ -1221,8 +1203,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * Determine if fingerprint hardware is present and functional. * * @return true if hardware is present and functional, false otherwise. - * - * @removed See {@link BiometricPrompt} and + * @deprecated See {@link BiometricPrompt} and * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE} */ @Deprecated @@ -1248,7 +1229,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Get statically configured sensor properties. - * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @@ -1267,7 +1247,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Returns whether the device has a power button fingerprint sensor. * @return boolean indicating whether power button is fingerprint sensor - * * @hide */ public boolean isPowerbuttonFps() { diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig index 6efb87225183..9f9aef8acc6a 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -17,3 +17,9 @@ flag { bug: "307898240" } +flag { + name: "register_nsd_offload_engine" + namespace: "android_core_networking" + description: "Flag for registerOffloadEngine API in NsdManager" + bug: "294777050" +} diff --git a/core/java/android/os/ExternalVibrationScale.aidl b/core/java/android/os/ExternalVibrationScale.aidl new file mode 100644 index 000000000000..cf6f8ed52f7d --- /dev/null +++ b/core/java/android/os/ExternalVibrationScale.aidl @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +/** + * ExternalVibrationScale holds the vibration scale level and adaptive haptics scale. These + * can be used to scale external vibrations. + * + * @hide + */ +parcelable ExternalVibrationScale { + @Backing(type="int") + enum ScaleLevel { + SCALE_MUTE = -100, + SCALE_VERY_LOW = -2, + SCALE_LOW = -1, + SCALE_NONE = 0, + SCALE_HIGH = 1, + SCALE_VERY_HIGH = 2 + } + + /** + * The scale level that will be applied to external vibrations. + */ + ScaleLevel scaleLevel = ScaleLevel.SCALE_NONE; + + /** + * The adaptive haptics scale that will be applied to external vibrations. + */ + float adaptiveHapticsScale = 1f; +} diff --git a/core/java/android/os/IExternalVibratorService.aidl b/core/java/android/os/IExternalVibratorService.aidl index 666171fcbcb3..a9df15a088bf 100644 --- a/core/java/android/os/IExternalVibratorService.aidl +++ b/core/java/android/os/IExternalVibratorService.aidl @@ -17,6 +17,7 @@ package android.os; import android.os.ExternalVibration; +import android.os.ExternalVibrationScale; /** * The communication channel by which an external system that wants to control the system @@ -32,29 +33,24 @@ import android.os.ExternalVibration; * {@hide} */ interface IExternalVibratorService { - const int SCALE_MUTE = -100; - const int SCALE_VERY_LOW = -2; - const int SCALE_LOW = -1; - const int SCALE_NONE = 0; - const int SCALE_HIGH = 1; - const int SCALE_VERY_HIGH = 2; - /** * A method called by the external system to start a vibration. * - * If this returns {@code SCALE_MUTE}, then the vibration should <em>not</em> play. If this - * returns any other scale level, then any currently playing vibration controlled by the - * requesting system must be muted and this vibration can begin playback. + * This returns an {@link ExternalVibrationScale} which includes the vibration scale level and + * the adaptive haptics scale. + * + * If the returned scale level is {@link ExternalVibrationScale.ScaleLevel#SCALE_MUTE}, then + * the vibration should <em>not</em> play. If it returns any other scale level, then + * any currently playing vibration controlled by the requesting system must be muted and this + * vibration can begin playback. * * Note that the IExternalVibratorService implementation will not call mute on any currently * playing external vibrations in order to avoid re-entrancy with the system on the other side. * - * @param vibration An ExternalVibration - * - * @return {@code SCALE_MUTE} if the external vibration should not play, and any other scale - * level if it should. + * @param vib The external vibration starting. + * @return {@link ExternalVibrationScale} including scale level and adaptive haptics scale. */ - int onExternalVibrationStart(in ExternalVibration vib); + ExternalVibrationScale onExternalVibrationStart(in ExternalVibration vib); /** * A method called by the external system when a vibration no longer wants to play. diff --git a/core/java/android/os/WakeLockStats.java b/core/java/android/os/WakeLockStats.java index 69e70a0a8b07..3769f38a9fbf 100644 --- a/core/java/android/os/WakeLockStats.java +++ b/core/java/android/os/WakeLockStats.java @@ -23,17 +23,21 @@ import java.util.List; /** * Snapshot of wake lock stats. - * @hide + * + * @hide */ @android.ravenwood.annotation.RavenwoodKeepWholeClass public final class WakeLockStats implements Parcelable { - /** @hide */ - public static class WakeLock { - public final int uid; - @NonNull - public final String name; + public static class WakeLockData { + + public static final WakeLockData EMPTY = new WakeLockData( + /* timesAcquired= */ 0, /* totalTimeHeldMs= */ 0, /* timeHeldMs= */ 0); + + /** How many times this wakelock has been acquired. */ public final int timesAcquired; + + /** Time in milliseconds that the lock has been held in total. */ public final long totalTimeHeldMs; /** @@ -41,26 +45,34 @@ public final class WakeLockStats implements Parcelable { */ public final long timeHeldMs; - public WakeLock(int uid, @NonNull String name, int timesAcquired, long totalTimeHeldMs, - long timeHeldMs) { - this.uid = uid; - this.name = name; + public WakeLockData(int timesAcquired, long totalTimeHeldMs, long timeHeldMs) { this.timesAcquired = timesAcquired; this.totalTimeHeldMs = totalTimeHeldMs; this.timeHeldMs = timeHeldMs; } - private WakeLock(Parcel in) { - uid = in.readInt(); - name = in.readString(); + /** + * Whether the fields are able to construct a valid wakelock. + */ + public boolean isDataValid() { + final boolean isDataReasonable = timesAcquired > 0 + && totalTimeHeldMs > 0 + && timeHeldMs >= 0 + && totalTimeHeldMs >= timeHeldMs; + return isEmpty() || isDataReasonable; + } + + private boolean isEmpty() { + return timesAcquired == 0 && totalTimeHeldMs == 0 && timeHeldMs == 0; + } + + private WakeLockData(Parcel in) { timesAcquired = in.readInt(); totalTimeHeldMs = in.readLong(); timeHeldMs = in.readLong(); } private void writeToParcel(Parcel out) { - out.writeInt(uid); - out.writeString(name); out.writeInt(timesAcquired); out.writeLong(totalTimeHeldMs); out.writeLong(timeHeldMs); @@ -68,21 +80,98 @@ public final class WakeLockStats implements Parcelable { @Override public String toString() { + return "WakeLockData{" + + "timesAcquired=" + + timesAcquired + + ", totalTimeHeldMs=" + + totalTimeHeldMs + + ", timeHeldMs=" + + timeHeldMs + + "}"; + } + } + + /** @hide */ + public static class WakeLock { + + public static final String NAME_AGGREGATED = "wakelockstats_aggregated"; + + public final int uid; + @NonNull public final String name; + public final boolean isAggregated; + + /** Wakelock data on both foreground and background. */ + @NonNull public final WakeLockData totalWakeLockData; + + /** Wakelock data on background. */ + @NonNull public final WakeLockData backgroundWakeLockData; + + public WakeLock( + int uid, + @NonNull String name, + boolean isAggregated, + @NonNull WakeLockData totalWakeLockData, + @NonNull WakeLockData backgroundWakeLockData) { + this.uid = uid; + this.name = name; + this.isAggregated = isAggregated; + this.totalWakeLockData = totalWakeLockData; + this.backgroundWakeLockData = backgroundWakeLockData; + } + + /** Whether the combination of total and background wakelock data is invalid. */ + public static boolean isDataValid( + WakeLockData totalWakeLockData, WakeLockData backgroundWakeLockData) { + return totalWakeLockData.totalTimeHeldMs > 0 + && totalWakeLockData.isDataValid() + && backgroundWakeLockData.isDataValid() + && totalWakeLockData.timesAcquired >= backgroundWakeLockData.timesAcquired + && totalWakeLockData.totalTimeHeldMs >= backgroundWakeLockData.totalTimeHeldMs + && totalWakeLockData.timeHeldMs >= backgroundWakeLockData.timeHeldMs; + } + + private WakeLock(Parcel in) { + uid = in.readInt(); + name = in.readString(); + isAggregated = in.readBoolean(); + totalWakeLockData = new WakeLockData(in); + backgroundWakeLockData = new WakeLockData(in); + } + + private void writeToParcel(Parcel out) { + out.writeInt(uid); + out.writeString(name); + out.writeBoolean(isAggregated); + totalWakeLockData.writeToParcel(out); + backgroundWakeLockData.writeToParcel(out); + } + + @Override + public String toString() { return "WakeLock{" - + "uid=" + uid - + ", name='" + name + '\'' - + ", timesAcquired=" + timesAcquired - + ", totalTimeHeldMs=" + totalTimeHeldMs - + ", timeHeldMs=" + timeHeldMs - + '}'; + + "uid=" + + uid + + ", name='" + + name + + '\'' + + ", isAggregated=" + + isAggregated + + ", totalWakeLockData=" + + totalWakeLockData + + ", backgroundWakeLockData=" + + backgroundWakeLockData + + '}'; } } private final List<WakeLock> mWakeLocks; + private final List<WakeLock> mAggregatedWakeLocks; - /** @hide **/ - public WakeLockStats(@NonNull List<WakeLock> wakeLocks) { + /** @hide */ + public WakeLockStats( + @NonNull List<WakeLock> wakeLocks, @NonNull List<WakeLock> aggregatedWakeLocks) { mWakeLocks = wakeLocks; + mAggregatedWakeLocks = aggregatedWakeLocks; } @NonNull @@ -90,22 +179,38 @@ public final class WakeLockStats implements Parcelable { return mWakeLocks; } + @NonNull + public List<WakeLock> getAggregatedWakeLocks() { + return mAggregatedWakeLocks; + } + private WakeLockStats(Parcel in) { - final int size = in.readInt(); - mWakeLocks = new ArrayList<>(size); - for (int i = 0; i < size; i++) { + final int wakelockSize = in.readInt(); + mWakeLocks = new ArrayList<>(wakelockSize); + for (int i = 0; i < wakelockSize; i++) { mWakeLocks.add(new WakeLock(in)); } + final int aggregatedWakelockSize = in.readInt(); + mAggregatedWakeLocks = new ArrayList<>(aggregatedWakelockSize); + for (int i = 0; i < aggregatedWakelockSize; i++) { + mAggregatedWakeLocks.add(new WakeLock(in)); + } } @Override public void writeToParcel(@NonNull Parcel out, int flags) { - final int size = mWakeLocks.size(); - out.writeInt(size); - for (int i = 0; i < size; i++) { + final int wakelockSize = mWakeLocks.size(); + out.writeInt(wakelockSize); + for (int i = 0; i < wakelockSize; i++) { WakeLock stats = mWakeLocks.get(i); stats.writeToParcel(out); } + final int aggregatedWakelockSize = mAggregatedWakeLocks.size(); + out.writeInt(aggregatedWakelockSize); + for (int i = 0; i < aggregatedWakelockSize; i++) { + WakeLock stats = mAggregatedWakeLocks.get(i); + stats.writeToParcel(out); + } } @NonNull @@ -127,6 +232,13 @@ public final class WakeLockStats implements Parcelable { @Override public String toString() { - return "WakeLockStats " + mWakeLocks; + return "WakeLockStats{" + + "mWakeLocks: [" + + mWakeLocks + + "]" + + ", mAggregatedWakeLocks: [" + + mAggregatedWakeLocks + + "]" + + '}'; } } diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index fd52c769e408..8495f3747573 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -1944,25 +1944,27 @@ public final class PermissionManager { * * @param permissionName The name of the permission you are checking for. * @param packageName The name of the package you are checking against. - * @param persistentDeviceId The persistent device id you are checking against. - * @param userId The user Id associated with context. + * @param persistentDeviceId The id of the physical device that you are checking permission + * against. * * @return If the package has the permission on the device, PERMISSION_GRANTED is * returned. If it does not have the permission on the device, PERMISSION_DENIED * is returned. * + * @see VirtualDevice#getPersistentDeviceId() * @see PackageManager#PERMISSION_GRANTED * @see PackageManager#PERMISSION_DENIED * * @hide */ @SystemApi + @PermissionResult @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) - public static int checkPermission(@NonNull String permissionName, @NonNull String packageName, - @NonNull String persistentDeviceId, @UserIdInt int userId) { + public int checkPermission(@NonNull String permissionName, @NonNull String packageName, + @NonNull String persistentDeviceId) { return sPackageNamePermissionCache.query( new PackageNamePermissionQuery(permissionName, packageName, persistentDeviceId, - userId)); + mContext.getUserId())); } /** diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index 9218cb8f497d..de7008b19f54 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -130,3 +130,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "ignore_process_text" + namespace: "permissions" + description: "Ignore activities that handle PROCESS_TEXT in TextView" + bug: "325356776" +} + diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ec4d5876070a..20b4857bdd4d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11969,6 +11969,16 @@ public final class Settings { "accessibility_pinch_to_zoom_anywhere_enabled"; /** + * For magnification feature where panning can be controlled with a single finger. + * + * If true, you can pan using a single finger gesture. + * + * @hide + */ + public static final String ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED = + "accessibility_single_finger_panning_enabled"; + + /** * Controls magnification capability. Accessibility magnification is capable of at least one * of the magnification modes. * @@ -12481,6 +12491,24 @@ public final class Settings { public static void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { } + + /** + * List of system components that support restore in a V-> U OS downgrade but do not have + * RestoreAnyVersion set to true. Value set before system restore. + * This setting is not B&Rd + * List is stored as a comma-separated string of package names e.g. "a,b,c" + * @hide + */ + public static final String V_TO_U_RESTORE_ALLOWLIST = "v_to_u_restore_allowlist"; + + /** + * List of system components that have RestoreAnyVersion set to true but do not support + * restore in a V-> U OS downgrade. Value set before system restore. + * This setting is not B&Rd + * List is stored as a comma-separated string of package names e.g. "a,b,c" + * @hide + */ + public static final String V_TO_U_RESTORE_DENYLIST = "v_to_u_restore_denylist"; } /** diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 15fb6ccf82fa..d9ca935b35b3 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -216,7 +216,7 @@ public class ZenModeConfig implements Parcelable { private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn"; private static final String ALLOW_ATT_CONV = "convos"; private static final String ALLOW_ATT_CONV_FROM = "convosFrom"; - private static final String ALLOW_ATT_CHANNELS = "priorityChannels"; + private static final String ALLOW_ATT_CHANNELS = "priorityChannelsAllowed"; private static final String POLICY_USER_MODIFIED_FIELDS = "policyUserModifiedFields"; private static final String DISALLOW_TAG = "disallow"; private static final String DISALLOW_ATT_VISUAL_EFFECTS = "visualEffects"; diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java index aa47d3a5c2af..786d768bc55b 100644 --- a/core/java/android/service/notification/ZenPolicy.java +++ b/core/java/android/service/notification/ZenPolicy.java @@ -673,10 +673,6 @@ public final class ZenPolicy implements Parcelable { mZenPolicy.mPriorityMessages = PEOPLE_TYPE_NONE; mZenPolicy.mPriorityCalls = PEOPLE_TYPE_NONE; mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_NONE; - - if (Flags.modesApi()) { - mZenPolicy.mAllowChannels = CHANNEL_POLICY_NONE; - } return this; } diff --git a/core/java/android/service/notification/flags.aconfig b/core/java/android/service/notification/flags.aconfig index 446fe3de6482..c5acc2ceb968 100644 --- a/core/java/android/service/notification/flags.aconfig +++ b/core/java/android/service/notification/flags.aconfig @@ -1,4 +1,5 @@ package: "android.service.notification" +container: "system" flag { name: "ranking_update_ashmem" @@ -12,6 +13,7 @@ flag { namespace: "systemui" description: "This flag controls the redacting of sensitive notifications from untrusted NotificationListenerServices" bug: "306271190" + is_exported: true } flag { diff --git a/core/java/android/service/wearable/IWearableSensingService.aidl b/core/java/android/service/wearable/IWearableSensingService.aidl index 22d8fda9cb8e..dffadf0cda70 100644 --- a/core/java/android/service/wearable/IWearableSensingService.aidl +++ b/core/java/android/service/wearable/IWearableSensingService.aidl @@ -28,7 +28,7 @@ import android.os.SharedMemory; * @hide */ oneway interface IWearableSensingService { - void provideSecureWearableConnection(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); + void provideSecureConnection(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); void provideDataStream(in ParcelFileDescriptor parcelFileDescriptor, in RemoteCallback callback); void provideData(in PersistableBundle data, in SharedMemory sharedMemory, in RemoteCallback callback); void registerDataRequestObserver(int dataType, in RemoteCallback dataRequestCallback, int dataRequestObserverId, in String packageName, in RemoteCallback statusCallback); diff --git a/core/java/android/service/wearable/WearableSensingService.java b/core/java/android/service/wearable/WearableSensingService.java index 808c3ae7b6bc..a2770172d3ca 100644 --- a/core/java/android/service/wearable/WearableSensingService.java +++ b/core/java/android/service/wearable/WearableSensingService.java @@ -112,11 +112,11 @@ public abstract class WearableSensingService extends Service { return new IWearableSensingService.Stub() { /** {@inheritDoc} */ @Override - public void provideSecureWearableConnection( + public void provideSecureConnection( ParcelFileDescriptor secureWearableConnection, RemoteCallback callback) { Objects.requireNonNull(secureWearableConnection); Consumer<Integer> consumer = createWearableStatusConsumer(callback); - WearableSensingService.this.onSecureWearableConnectionProvided( + WearableSensingService.this.onSecureConnectionProvided( secureWearableConnection, consumer); } @@ -311,12 +311,12 @@ public abstract class WearableSensingService extends Service { /** * Called when a secure connection to the wearable is available. See {@link - * WearableSensingManager#provideWearableConnection(ParcelFileDescriptor, Executor, Consumer)} + * WearableSensingManager#provideConnection(ParcelFileDescriptor, Executor, Consumer)} * for details about the secure connection. * * <p>When the {@code secureWearableConnection} is closed, the system will send a {@link * WearableSensingManager#STATUS_CHANNEL_ERROR} status code to the status consumer provided by - * the caller of {@link WearableSensingManager#provideWearableConnection(ParcelFileDescriptor, + * the caller of {@link WearableSensingManager#provideConnection(ParcelFileDescriptor, * Executor, Consumer)}. * * <p>The implementing class should override this method. It should return an appropriate status @@ -327,7 +327,7 @@ public abstract class WearableSensingService extends Service { */ @FlaggedApi(Flags.FLAG_ENABLE_PROVIDE_WEARABLE_CONNECTION_API) @BinderThread - public void onSecureWearableConnectionProvided( + public void onSecureConnectionProvided( @NonNull ParcelFileDescriptor secureWearableConnection, @NonNull Consumer<Integer> statusConsumer) { statusConsumer.accept(WearableSensingManager.STATUS_UNSUPPORTED_OPERATION); diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 8e52af3fb57b..8dee4b19c6d3 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -16,6 +16,7 @@ package android.text; +import static com.android.graphics.hwui.flags.Flags.highContrastTextLuminance; import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE; import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH; import static com.android.text.flags.Flags.FLAG_LETTER_SPACING_JUSTIFICATION; @@ -28,7 +29,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.compat.annotation.UnsupportedAppUsage; +import android.graphics.BlendMode; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; @@ -46,7 +49,9 @@ import android.text.style.ReplacementSpan; import android.text.style.TabStopSpan; import android.widget.TextView; +import com.android.graphics.hwui.flags.Flags; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.ColorUtils; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; @@ -480,9 +485,23 @@ public abstract class Layout { int lastLine = TextUtils.unpackRangeEndFromLong(lineRange); if (lastLine < 0) return; - drawWithoutText(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint, - cursorOffsetVertical, firstLine, lastLine); + if (shouldDrawHighlightsOnTop(canvas)) { + drawBackground(canvas, firstLine, lastLine); + } else { + drawWithoutText(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint, + cursorOffsetVertical, firstLine, lastLine); + } + drawText(canvas, firstLine, lastLine); + + // Since high contrast text draws a solid rectangle background behind the text, it covers up + // the highlights and selections. In this case we draw over the top of the text with a + // blend mode that ensures the text stays high-contrast. + if (shouldDrawHighlightsOnTop(canvas)) { + drawHighlights(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint, + cursorOffsetVertical, firstLine, lastLine); + } + if (leftShift != 0) { // Manually translate back to the original position because of b/324498002, using // save/restore disappears the toggle switch drawables. @@ -490,6 +509,19 @@ public abstract class Layout { } } + private static boolean shouldDrawHighlightsOnTop(Canvas canvas) { + return Flags.highContrastTextSmallTextRect() && canvas.isHighContrastTextEnabled(); + } + + private static Paint setToHighlightPaint(Paint p, BlendMode blendMode, Paint outPaint) { + if (p == null) return null; + outPaint.set(p); + outPaint.setBlendMode(blendMode); + // Yellow for maximum contrast + outPaint.setColor(Color.YELLOW); + return outPaint; + } + /** * Draw text part of this layout. * @@ -542,11 +574,28 @@ public abstract class Layout { int firstLine, int lastLine) { drawBackground(canvas, firstLine, lastLine); + drawHighlights(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint, + cursorOffsetVertical, firstLine, lastLine); + } + + /** + * @hide public for Editor.java + */ + public void drawHighlights( + @NonNull Canvas canvas, + @Nullable List<Path> highlightPaths, + @Nullable List<Paint> highlightPaints, + @Nullable Path selectionPath, + @Nullable Paint selectionPaint, + int cursorOffsetVertical, + int firstLine, + int lastLine) { if (highlightPaths == null && highlightPaints == null) { return; } if (cursorOffsetVertical != 0) canvas.translate(0, cursorOffsetVertical); try { + BlendMode blendMode = determineHighContrastHighlightBlendMode(canvas); if (highlightPaths != null) { if (highlightPaints == null) { throw new IllegalArgumentException( @@ -559,7 +608,12 @@ public abstract class Layout { } for (int i = 0; i < highlightPaths.size(); ++i) { final Path highlight = highlightPaths.get(i); - final Paint highlightPaint = highlightPaints.get(i); + Paint highlightPaint = highlightPaints.get(i); + if (shouldDrawHighlightsOnTop(canvas)) { + highlightPaint = setToHighlightPaint(highlightPaint, blendMode, + mWorkPlainPaint); + } + if (highlight != null) { canvas.drawPath(highlight, highlightPaint); } @@ -567,6 +621,10 @@ public abstract class Layout { } if (selectionPath != null) { + if (shouldDrawHighlightsOnTop(canvas)) { + selectionPaint = setToHighlightPaint(selectionPaint, blendMode, + mWorkPlainPaint); + } canvas.drawPath(selectionPath, selectionPaint); } } finally { @@ -574,6 +632,31 @@ public abstract class Layout { } } + @Nullable + private BlendMode determineHighContrastHighlightBlendMode(Canvas canvas) { + if (!shouldDrawHighlightsOnTop(canvas)) { + return null; + } + + return isHighContrastTextDark() ? BlendMode.MULTIPLY : BlendMode.DIFFERENCE; + } + + private boolean isHighContrastTextDark() { + // High-contrast text mode + // Determine if the text is black-on-white or white-on-black, so we know what blendmode will + // give the highest contrast and most realistic text color. + // This equation should match the one in libs/hwui/hwui/DrawTextFunctor.h + if (highContrastTextLuminance()) { + var lab = new double[3]; + ColorUtils.colorToLAB(mPaint.getColor(), lab); + return lab[0] < 0.5; + } else { + var color = mPaint.getColor(); + int channelSum = Color.red(color) + Color.green(color) + Color.blue(color); + return channelSum < (128 * 3); + } + } + private boolean isJustificationRequired(int lineNum) { if (mJustificationMode == JUSTIFICATION_MODE_NONE) return false; final int lineEnd = getLineEnd(lineNum); @@ -3396,7 +3479,8 @@ public abstract class Layout { private CharSequence mText; @UnsupportedAppUsage private TextPaint mPaint; - private TextPaint mWorkPaint = new TextPaint(); + private final TextPaint mWorkPaint = new TextPaint(); + private final Paint mWorkPlainPaint = new Paint(); private int mWidth; private Alignment mAlignment = Alignment.ALIGN_NORMAL; private float mSpacingMult; diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig index c6e8844bc47a..b1bca96c5c09 100644 --- a/core/java/android/tracing/flags.aconfig +++ b/core/java/android/tracing/flags.aconfig @@ -12,4 +12,5 @@ flag { namespace: "windowing_tools" description: "Migrate protolog to Perfetto" bug: "276432490" + is_fixed_read_only: true } diff --git a/core/java/android/tracing/perfetto/DataSource.java b/core/java/android/tracing/perfetto/DataSource.java index 4e08aeef88e6..d0c719b86ac9 100644 --- a/core/java/android/tracing/perfetto/DataSource.java +++ b/core/java/android/tracing/perfetto/DataSource.java @@ -18,6 +18,8 @@ package android.tracing.perfetto; import android.util.proto.ProtoInputStream; +import com.android.internal.annotations.VisibleForTesting; + /** * Templated base class meant to be derived by embedders to create a custom data * source. @@ -87,7 +89,8 @@ public abstract class DataSource<DataSourceInstanceType extends DataSourceInstan * * NOTE: Should only be called from native side. */ - protected TlsStateType createTlsState(CreateTlsStateArgs<DataSourceInstanceType> args) { + @VisibleForTesting + public TlsStateType createTlsState(CreateTlsStateArgs<DataSourceInstanceType> args) { return null; } diff --git a/core/java/android/tracing/perfetto/DataSourceInstance.java b/core/java/android/tracing/perfetto/DataSourceInstance.java index 3710b4df33e8..904cf55e014a 100644 --- a/core/java/android/tracing/perfetto/DataSourceInstance.java +++ b/core/java/android/tracing/perfetto/DataSourceInstance.java @@ -16,6 +16,8 @@ package android.tracing.perfetto; +import com.android.internal.annotations.VisibleForTesting; + /** * @hide */ @@ -66,7 +68,8 @@ public abstract class DataSourceInstance implements AutoCloseable { * Only required to be called when instance was retrieved with * `DataSource#getDataSourceInstanceLocked`. */ - public final void release() { + @VisibleForTesting + public void release() { mDataSource.releaseDataSourceInstance(mInstanceIndex); } diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index b33214dffb7e..8358b9a51adb 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -72,8 +72,11 @@ import java.net.UnknownHostException; * a positive value may be considered as a successful invocation. */ @android.ravenwood.annotation.RavenwoodKeepWholeClass -@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass( - "com.android.platform.test.ravenwood.nativesubstitution.Log_host") +@android.ravenwood.annotation.RavenwoodClassLoadHook( + "com.android.platform.test.ravenwood.runtimehelper.ClassLoadHook.onClassLoaded") +// Uncomment the following annotation to switch to the Java substitution version. +//@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass( +// "com.android.platform.test.ravenwood.nativesubstitution.Log_host") public final class Log { /** @hide */ @IntDef({ASSERT, ERROR, WARN, INFO, DEBUG, VERBOSE}) diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java index e679f2998ca1..ca2e56d383e5 100644 --- a/core/java/android/view/BatchedInputEventReceiver.java +++ b/core/java/android/view/BatchedInputEventReceiver.java @@ -19,6 +19,7 @@ package android.view; import android.compat.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.Looper; +import android.os.Trace; /** * Similar to {@link InputEventReceiver}, but batches events to vsync boundaries when possible. @@ -42,6 +43,8 @@ public class BatchedInputEventReceiver extends InputEventReceiver { super(inputChannel, looper); mChoreographer = choreographer; mBatchingEnabled = true; + traceBoolVariable("mBatchingEnabled", mBatchingEnabled); + traceBoolVariable("mBatchedInputScheduled", mBatchedInputScheduled); mHandler = new Handler(looper); } @@ -71,6 +74,7 @@ public class BatchedInputEventReceiver extends InputEventReceiver { } mBatchingEnabled = batchingEnabled; + traceBoolVariable("mBatchingEnabled", mBatchingEnabled); mHandler.removeCallbacks(mConsumeBatchedInputEvents); if (!batchingEnabled) { unscheduleBatchedInput(); @@ -81,6 +85,7 @@ public class BatchedInputEventReceiver extends InputEventReceiver { protected void doConsumeBatchedInput(long frameTimeNanos) { if (mBatchedInputScheduled) { mBatchedInputScheduled = false; + traceBoolVariable("mBatchedInputScheduled", mBatchedInputScheduled); if (consumeBatchedInputEvents(frameTimeNanos) && frameTimeNanos != -1) { // If we consumed a batch here, we want to go ahead and schedule the // consumption of batched input events on the next frame. Otherwise, we would @@ -95,6 +100,7 @@ public class BatchedInputEventReceiver extends InputEventReceiver { private void scheduleBatchedInput() { if (!mBatchedInputScheduled) { mBatchedInputScheduled = true; + traceBoolVariable("mBatchedInputScheduled", mBatchedInputScheduled); mChoreographer.postCallback(Choreographer.CALLBACK_INPUT, mBatchedInputRunnable, null); } } @@ -102,11 +108,18 @@ public class BatchedInputEventReceiver extends InputEventReceiver { private void unscheduleBatchedInput() { if (mBatchedInputScheduled) { mBatchedInputScheduled = false; + traceBoolVariable("mBatchedInputScheduled", mBatchedInputScheduled); mChoreographer.removeCallbacks( Choreographer.CALLBACK_INPUT, mBatchedInputRunnable, null); } } + // @TODO(b/311142655): Delete this temporary tracing. It's only used here to debug a very + // specific issue. + private void traceBoolVariable(String name, boolean value) { + Trace.traceCounter(Trace.TRACE_TAG_INPUT, name, value ? 1 : 0); + } + private final class BatchedInputRunnable implements Runnable { @Override public void run() { diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 9c430cd4acb4..2cc05b0bc4b0 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -271,12 +271,29 @@ public abstract class InputEventReceiver { return mInputChannel.getToken(); } + private String getShortDescription(InputEvent event) { + if (event instanceof MotionEvent motion) { + return "MotionEvent " + MotionEvent.actionToString(motion.getAction()) + " deviceId=" + + motion.getDeviceId() + " source=0x" + + Integer.toHexString(motion.getSource()) + " historySize=" + + motion.getHistorySize(); + } else if (event instanceof KeyEvent key) { + return "KeyEvent " + KeyEvent.actionToString(key.getAction()) + + " deviceId=" + key.getDeviceId(); + } else { + Log.wtf(TAG, "Illegal InputEvent type: " + event); + return "InputEvent"; + } + } + // Called from native code. @SuppressWarnings("unused") @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private void dispatchInputEvent(int seq, InputEvent event) { + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "dispatchInputEvent " + getShortDescription(event)); mSeqMap.put(event.getSequenceNumber(), seq); onInputEvent(event); + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } /** diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index 13b9c4518711..f5f4fd9f7042 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -480,11 +480,19 @@ public final class PointerIcon implements Parcelable { mBitmapFrames = new Bitmap[frames - 1]; final int width = drawable.getIntrinsicWidth(); final int height = drawable.getIntrinsicHeight(); + final boolean isVectorAnimation = drawable instanceof VectorDrawable; + mDrawNativeDropShadow = isVectorAnimation; for (int i = 1; i < frames; ++i) { Drawable drawableFrame = animationDrawable.getFrame(i); - if (!(drawableFrame instanceof BitmapDrawable)) { + if (!(drawableFrame instanceof BitmapDrawable) + && !(drawableFrame instanceof VectorDrawable)) { throw new IllegalArgumentException("Frame of an animated pointer icon " - + "must refer to a bitmap drawable."); + + "must refer to a bitmap drawable or vector drawable."); + } + if (isVectorAnimation != (drawableFrame instanceof VectorDrawable)) { + throw new IllegalArgumentException("The drawable of the " + i + "-th frame " + + "is a different type from the others. All frames should be the " + + "same type."); } if (drawableFrame.getIntrinsicWidth() != width || drawableFrame.getIntrinsicHeight() != height) { @@ -492,8 +500,11 @@ public final class PointerIcon implements Parcelable { + "is different. All frames should have the exact same size and " + "share the same hotspot."); } - BitmapDrawable bitmapDrawableFrame = (BitmapDrawable) drawableFrame; - mBitmapFrames[i - 1] = getBitmapFromDrawable(bitmapDrawableFrame); + if (isVectorAnimation) { + drawableFrame = getBitmapDrawableFromVectorDrawable(resources, + (VectorDrawable) drawableFrame); + } + mBitmapFrames[i - 1] = getBitmapFromDrawable((BitmapDrawable) drawableFrame); } } } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 021bbf7b9c9f..124aecef1d5a 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -16,6 +16,8 @@ package android.view; +import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL; + import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; @@ -196,8 +198,6 @@ public class TextureView extends View { private Canvas mCanvas; private int mSaveCount; - @Surface.FrameRateCompatibility int mFrameRateCompatibility; - private final Object[] mNativeWindowLock = new Object[0]; // Set by native code, do not write! @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -885,6 +885,17 @@ public class TextureView extends View { mListener = listener; } + /** + * @hide + */ + @Override + protected int calculateFrameRateCategory(float sizePercentage) { + if (mMinusTwoFrameIntervalMillis > 15 && mMinusOneFrameIntervalMillis > 15) { + return FRAME_RATE_CATEGORY_NORMAL; + } + return super.calculateFrameRateCategory(sizePercentage); + } + @UnsupportedAppUsage private final SurfaceTexture.OnFrameAvailableListener mUpdateListener = surfaceTexture -> { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cd6d79c81b98..cbb3be7c4155 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -24,6 +24,7 @@ import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH; import static android.view.Surface.FRAME_RATE_CATEGORY_LOW; import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL; import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE; +import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW; @@ -35,6 +36,7 @@ import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY; import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API; import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout; +import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision; import static android.view.flags.Flags.toolkitSetFrameRateReadOnly; import static android.view.flags.Flags.viewVelocityApi; @@ -85,6 +87,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.credentials.CredentialManager; +import android.credentials.CredentialOption; import android.credentials.GetCredentialException; import android.credentials.GetCredentialRequest; import android.credentials.GetCredentialResponse; @@ -129,9 +132,11 @@ import android.os.SystemClock; import android.os.Trace; import android.os.Vibrator; import android.os.vibrator.Flags; +import android.service.credentials.CredentialProviderService; import android.sysprop.DisplayProperties; import android.text.InputType; import android.text.TextUtils; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FloatProperty; @@ -1047,7 +1052,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @Nullable private ViewCredentialHandler mViewCredentialHandler; - /** Used to avoid computing the full strings each time when layout tracing is enabled. */ @Nullable private ViewTraversalTracingStrings mTracingStrings; @@ -2367,6 +2371,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static boolean sToolkitSetFrameRateReadOnlyFlagValue; private static boolean sToolkitMetricsForFrameRateDecisionFlagValue; + // Used to set frame rate compatibility. + @Surface.FrameRateCompatibility int mFrameRateCompatibility = + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; static { EMPTY_STATE_SET = StateSet.get(0); @@ -3696,6 +3703,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT * 1 PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT * 11 PFLAG4_CONTENT_SENSITIVITY_MASK + * 1 PFLAG4_IS_COUNTED_AS_SENSITIVE * |-------|-------|-------|-------| */ @@ -3821,6 +3829,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG4_CONTENT_SENSITIVITY_MASK = (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT; + + /** + * Whether this view has been counted as a sensitive view or not. + * + * @see AttachInfo#mSensitiveViewsCount + */ + private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000; /* End of masks for mPrivateFlags4 */ /** @hide */ @@ -5634,9 +5649,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private int mInfrequentUpdateCount = 0; private long mLastUpdateTimeMillis = 0; - private long mMinusOneFrameIntervalMillis = 0; - private long mMinusTwoFrameIntervalMillis = 0; - private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_HIGH; + /** + * @hide + */ + protected long mMinusOneFrameIntervalMillis = 0; + /** + * @hide + */ + protected long mMinusTwoFrameIntervalMillis = 0; + private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE; @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN; @@ -7035,6 +7056,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Preconditions.checkNotNull(request, "request must not be null"); Preconditions.checkNotNull(callback, "request must not be null"); + for (CredentialOption option : request.getCredentialOptions()) { + ArrayList<AutofillId> ids = option.getCandidateQueryData() + .getParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class); + ids = ids != null ? ids : new ArrayList<>(); + if (!ids.contains(getAutofillId())) { + ids.add(getAutofillId()); + } + option.getCandidateQueryData() + .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids); + } mViewCredentialHandler = new ViewCredentialHandler(request, callback); } @@ -9915,6 +9947,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * @hide + */ + public void onGetCredentialResponse(GetCredentialResponse response) { + if (getCredentialManagerCallback() == null) { + Log.w(AUTOFILL_LOG_TAG, "onGetCredentialResponse called but no callback found"); + return; + } + getCredentialManagerCallback().onResult(response); + } + + /** + * @hide + */ + public void onGetCredentialException(String errorType, String errorMsg) { + if (getCredentialManagerCallback() == null) { + Log.w(AUTOFILL_LOG_TAG, "onGetCredentialException called but no callback found"); + return; + } + getCredentialManagerCallback().onError(new GetCredentialException(errorType, errorMsg)); + } + + /** * Gets the unique, logical identifier of this view in the activity, for autofill purposes. * * <p>The autofill id is created on demand, unless it is explicitly set by @@ -10360,6 +10414,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK; mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT) & PFLAG4_CONTENT_SENSITIVITY_MASK); + if (sensitiveContentAppProtection()) { + updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); + } } /** @@ -10391,13 +10448,44 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) public final boolean isContentSensitive() { - if (getContentSensitivity() == CONTENT_SENSITIVITY_SENSITIVE) { + final int contentSensitivity = getContentSensitivity(); + if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) { return true; + } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) { + return false; + } else if (sensitiveContentAppProtection()) { + return SensitiveAutofillHintsHelper + .containsSensitiveAutofillHint(getAutofillHints()); } return false; } /** + * Helper used to track sensitive views when they are added or removed from the window + * based on whether it's laid out and visible. + * + * <p>This method is called from many places (visibility changed, view laid out, view attached + * or detached to/from window, etc...) + */ + private void updateSensitiveViewsCountIfNeeded(boolean appeared) { + if (!sensitiveContentAppProtection() || mAttachInfo == null) { + return; + } + + if (appeared && isContentSensitive()) { + if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) { + mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE; + mAttachInfo.increaseSensitiveViewsCount(); + } + } else { + if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) { + mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE; + mAttachInfo.decreaseSensitiveViewsCount(); + } + } + } + + /** * Gets the mode for determining whether this view is important for content capture. * * <p>See {@link #setImportantForContentCapture(int)} and @@ -10866,8 +10954,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, structure.setAutofillId(new AutofillId(getAutofillId(), AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()))); } - structure.setCredentialManagerRequest(getCredentialManagerRequest(), - getCredentialManagerCallback()); + if (getViewCredentialHandler() != null) { + structure.setCredentialManagerRequest( + getViewCredentialHandler().getRequest(), + getViewCredentialHandler().getCallback()); + } CharSequence cname = info.getClassName(); structure.setClassName(cname != null ? cname.toString() : null); structure.setContentDescription(info.getContentDescription()); @@ -13427,6 +13518,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mAutofillHints = autofillHints; } + if (sensitiveContentAppProtection()) { + if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) { + updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); + } + } } /** @@ -16651,6 +16747,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); + updateSensitiveViewsCountIfNeeded(isVisible); if (!getSystemGestureExclusionRects().isEmpty()) { postUpdate(this::updateSystemGestureExclusionRects); @@ -22640,6 +22737,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); + updateSensitiveViewsCountIfNeeded(false); mAttachInfo = null; if (mOverlay != null) { @@ -31787,6 +31885,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, ScrollCaptureInternal mScrollCaptureInternal; /** + * sensitive views attached to the window + */ + int mSensitiveViewsCount; + + /** * Creates a new set of attachment information with the specified * events handler and thread. * @@ -31805,6 +31908,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTreeObserver = new ViewTreeObserver(context); } + void increaseSensitiveViewsCount() { + if (mSensitiveViewsCount == 0) { + mViewRootImpl.notifySensitiveContentAppProtection(true); + } + mSensitiveViewsCount++; + } + + void decreaseSensitiveViewsCount() { + mSensitiveViewsCount--; + if (mSensitiveViewsCount == 0) { + mViewRootImpl.notifySensitiveContentAppProtection(false); + } + if (mSensitiveViewsCount < 0) { + Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount); + mSensitiveViewsCount = 0; + } + } + @Nullable ContentCaptureManager getContentCaptureManager(@NonNull Context context) { if (mContentCaptureManager != null) { @@ -32418,6 +32539,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + private static class SensitiveAutofillHintsHelper { + /** + * List of autofill hints deemed sensitive for screen protection during screen share. + */ + private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>(); + static { + SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME); + SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO); + SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD); + } + + /** + * Whether View's autofill hints contains a sensitive autofill hint. + * + * @see #SENSITIVE_CONTENT_AUTOFILL_HINTS + */ + static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) { + if (autofillHints == null) { + return false; + } + + int size = autofillHints.length; + for (int i = 0; i < size; i++) { + if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) { + return true; + } + } + return false; + } + } /** * Returns the current scroll capture hint for this view. @@ -33478,7 +33629,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return (float) viewSize / screenSize; } - private int calculateFrameRateCategory(float sizePercentage) { + /** + * Used to calculate the frame rate category of a View. + * + * @hide + */ + protected int calculateFrameRateCategory(float sizePercentage) { if (mMinusTwoFrameIntervalMillis + mMinusOneFrameIntervalMillis < INFREQUENT_UPDATE_INTERVAL_MILLIS) { if (sizePercentage <= FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD) { @@ -33515,7 +33671,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, frameRateCateogry = FRAME_RATE_CATEGORY_HIGH; } } else { - viewRootImpl.votePreferredFrameRate(mPreferredFrameRate); + viewRootImpl.votePreferredFrameRate(mPreferredFrameRate, + mFrameRateCompatibility); return; } } @@ -33611,7 +33768,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mMinusTwoFrameIntervalMillis = mMinusOneFrameIntervalMillis; mMinusOneFrameIntervalMillis = timeIntervalMillis; - mLastUpdateTimeMillis = currentTimeMillis; + if (mMinusOneFrameIntervalMillis - mMinusTwoFrameIntervalMillis >= 30 + && timeIntervalMillis < 2) { + return; + } if (timeIntervalMillis >= INFREQUENT_UPDATE_INTERVAL_MILLIS) { mInfrequentUpdateCount = mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS ? mInfrequentUpdateCount : mInfrequentUpdateCount + 1; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1e79786d7554..b5f3b9a8fa2d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -30,6 +30,7 @@ import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT; import static android.view.Surface.FRAME_RATE_CATEGORY_LOW; import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL; import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE; +import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; import static android.view.View.PFLAG_DRAW_ANIMATION; import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; @@ -57,6 +58,7 @@ import static android.view.ViewRootImplProto.WIDTH; import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES; import static android.view.ViewRootImplProto.WIN_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; +import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; @@ -99,6 +101,7 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; import static com.android.input.flags.Flags.enablePointerChoreographer; +import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay; import android.Manifest; import android.accessibilityservice.AccessibilityService; @@ -165,6 +168,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; @@ -923,6 +927,8 @@ public final class ViewRootImpl implements ViewParent, private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; + private final ISensitiveContentProtectionManager mSensitiveContentProtectionService; + static final class SystemUiVisibilityInfo { int globalVisibility; int localValue; @@ -992,8 +998,6 @@ public final class ViewRootImpl implements ViewParent, */ private final boolean mViewBoundsSandboxingEnabled; - private int mLastTransformHint = Integer.MIN_VALUE; - private AccessibilityWindowAttributes mAccessibilityWindowAttributes; /* @@ -1027,12 +1031,19 @@ public final class ViewRootImpl implements ViewParent, // as needed and can be useful for power saving. // Should not enable the dVRR feature if the value is false. private boolean mIsFrameRatePowerSavingsBalanced = true; + // Used to check if there is a conflict between different frame rate voting. + // Take 24 and 30 as an example, 24 is not a divisor of 30. + // We consider there is a conflict. + private boolean mIsFrameRateConflicted = false; + // Used to set frame rate compatibility. + @Surface.FrameRateCompatibility int mFrameRateCompatibility = + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; // time for touch boost period. private static final int FRAME_RATE_TOUCH_BOOST_TIME = 3000; // time for checking idle status periodically. private static final int FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS = 500; // time for revaluating the idle status before lowering the frame rate. - private static final int FRAME_RATE_IDLENESS_REEVALUATE_TIME = 500; + private static final int FRAME_RATE_IDLENESS_REEVALUATE_TIME = 1000; // time for evaluating the interval between current time and // the time when frame rate was set previously. private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100; @@ -1195,6 +1206,13 @@ public final class ViewRootImpl implements ViewParent, mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher(context); + if (sensitiveContentAppProtection()) { + mSensitiveContentProtectionService = + ISensitiveContentProtectionManager.Stub.asInterface( + ServiceManager.getService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE)); + } else { + mSensitiveContentProtectionService = null; + } } public static void addFirstDrawHandler(Runnable callback) { @@ -4110,6 +4128,7 @@ public final class ViewRootImpl implements ViewParent, ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount; mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE; mPreferredFrameRate = -1; + mIsFrameRateConflicted = false; } private void createSyncIfNeeded() { @@ -4145,6 +4164,29 @@ public final class ViewRootImpl implements ViewParent, mWmsRequestSyncGroup.add(this, null /* runnable */); } + /** + * Helper used to notify the service to block projection when a sensitive + * view (the view displays sensitive content) is attached to the window. + * The window manager service is also notified to unblock projection when + * no attached view (to the window) displays sensitive content. + * + * <ol> + * <li>It should only notify service to block projection when first sensitive view is + * attached to the window. + * <li>It should only notify service to unblock projection when all sensitive view are + * removed from the window. + * </ol> + */ + void notifySensitiveContentAppProtection(boolean showSensitiveContent) { + try { + // The window would be blocked during screen share if it shows sensitive content. + mSensitiveContentProtectionService.setSensitiveContentProtection( + getWindowToken(), mContext.getPackageName(), showSensitiveContent); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to protect sensitive content during screen share", ex); + } + } + private void notifyContentCaptureEvents() { if (!isContentCaptureEnabled()) { if (DEBUG_CONTENT_CAPTURE) { @@ -6498,6 +6540,7 @@ public final class ViewRootImpl implements ViewParent, mHasInvalidation = false; mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE, FRAME_RATE_IDLENESS_REEVALUATE_TIME); + mHasIdledMessage = true; } break; case MSG_REFRESH_POINTER_ICON: @@ -6508,6 +6551,7 @@ public final class ViewRootImpl implements ViewParent, break; case MSG_FRAME_RATE_SETTING: mPreferredFrameRate = 0; + mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; setPreferredFrameRate(mPreferredFrameRate); break; } @@ -8874,11 +8918,13 @@ public final class ViewRootImpl implements ViewParent, final int transformHint = SurfaceControl.rotationToBufferTransform( (mDisplay.getInstallOrientation() + mDisplay.getRotation()) % 4); + final boolean transformHintChanged = transformHint != mPreviousTransformHint; + mPreviousTransformHint = transformHint; + mSurfaceControl.setTransformHint(transformHint); WindowLayout.computeSurfaceSize(mWindowAttributes, winConfig.getMaxBounds(), requestedWidth, requestedHeight, mWinFrameInScreen, mPendingDragResizing, mSurfaceSize); - final boolean transformHintChanged = transformHint != mLastTransformHint; final boolean sizeChanged = !mLastSurfaceSize.equals(mSurfaceSize); final boolean surfaceControlChanged = (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED) == RELAYOUT_RES_SURFACE_CHANGED; @@ -8907,10 +8953,6 @@ public final class ViewRootImpl implements ViewParent, } } - mLastTransformHint = transformHint; - - mSurfaceControl.setTransformHint(transformHint); - if (mAttachInfo.mContentCaptureManager != null) { ContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager .getMainContentCaptureSession(); @@ -8924,8 +8966,7 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue); } mHdrRenderState.forceUpdateHdrSdrRatio(); - if (mPreviousTransformHint != transformHint) { - mPreviousTransformHint = transformHint; + if (transformHintChanged) { dispatchTransformHintChanged(transformHint); } } else { @@ -11889,6 +11930,14 @@ public final class ViewRootImpl implements ViewParent, @Override public @SurfaceControl.BufferTransform int getBufferTransformHint() { + // TODO(b/326482114) We use mPreviousTransformHint (calculated using mDisplay's rotation) + // instead of mSurfaceControl#getTransformHint because there's a race where SurfaceFlinger + // can set an incorrect transform hint for a few frames before it is aware of the updated + // display rotation. + if (enableBufferTransformHintFromDisplay()) { + return mPreviousTransformHint; + } + if (mSurfaceControl.isValid()) { return mSurfaceControl.getTransformHint(); } else { @@ -12286,9 +12335,15 @@ public final class ViewRootImpl implements ViewParent, if (!shouldSetFrameRateCategory()) { return; } + int categoryFromConflictedFrameRates = FRAME_RATE_CATEGORY_NO_PREFERENCE; + if (mIsFrameRateConflicted) { + categoryFromConflictedFrameRates = mPreferredFrameRate > 60 + ? FRAME_RATE_CATEGORY_HIGH : FRAME_RATE_CATEGORY_NORMAL; + } int frameRateCategory = mIsTouchBoosting - ? FRAME_RATE_CATEGORY_HIGH_HINT : preferredFrameRateCategory; + ? FRAME_RATE_CATEGORY_HIGH_HINT + : Math.max(preferredFrameRateCategory, categoryFromConflictedFrameRates); // FRAME_RATE_CATEGORY_HIGH has a higher precedence than FRAME_RATE_CATEGORY_HIGH_HINT // For now, FRAME_RATE_CATEGORY_HIGH_HINT is used for boosting with user interaction. @@ -12314,14 +12369,6 @@ public final class ViewRootImpl implements ViewParent, } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } - - if (mPreferredFrameRateCategory != FRAME_RATE_CATEGORY_NO_PREFERENCE && !mHasIdledMessage) { - // Check where the display is idled periodically. - // If so, set the frame rate category to NO_PREFERENCE - mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE, - FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS); - mHasIdledMessage = true; - } } private void setPreferredFrameRate(float preferredFrameRate) { @@ -12335,10 +12382,11 @@ public final class ViewRootImpl implements ViewParent, if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { Trace.traceBegin( Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRate " - + preferredFrameRate); + + preferredFrameRate + " compatibility " + + mFrameRateCompatibility); } mFrameRateTransaction.setFrameRate(mSurfaceControl, preferredFrameRate, - Surface.FRAME_RATE_COMPATIBILITY_DEFAULT).applyAsyncUnsafe(); + mFrameRateCompatibility).applyAsyncUnsafe(); mLastPreferredFrameRate = preferredFrameRate; } } catch (Exception e) { @@ -12361,7 +12409,8 @@ public final class ViewRootImpl implements ViewParent, private boolean shouldSetFrameRate() { // use toolkitSetFrameRate flag to gate the change - return mSurface.isValid() && mPreferredFrameRate > 0 && shouldEnableDvrr(); + return mSurface.isValid() && mPreferredFrameRate >= 0 + && shouldEnableDvrr() && !mIsFrameRateConflicted; } private boolean shouldTouchBoost(int motionEventAction, int windowType) { @@ -12401,32 +12450,50 @@ public final class ViewRootImpl implements ViewParent, mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_LOW; } mHasInvalidation = true; + checkIdleness(); } /** - * Allow Views to vote for the preferred frame rate + * Allow Views to vote for the preferred frame rate and compatibility. * When determining the preferred frame rate value, * we follow this logic: If no preferred frame rate has been set yet, * we assign the value of frameRate as the preferred frame rate. - * If either the current or the new preferred frame rate exceeds 60 Hz, - * we select the higher value between them. - * However, if both values are 60 Hz or lower, we set the preferred frame rate - * to 60 Hz to maintain optimal performance. + * IF there are multiple frame rates are voted: + * 1. There is a frame rate is a multiple of all other frame rates. + * We choose this frmae rate to be the one to be set. + * 2. There is no frame rate can be a multiple of others + * We set category to HIGH if the maximum frame rate is greater than 60. + * Otherwise, we set category to NORMAL. + * + * Use FRAME_RATE_COMPATIBILITY_GTE for velocity and FRAME_RATE_COMPATIBILITY_FIXED_SOURCE + * for TextureView video play and user requested frame rate. * * @param frameRate the preferred frame rate of a View + * @param frameRateCompatibility the preferred frame rate compatibility of a View */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED) - public void votePreferredFrameRate(float frameRate) { + public void votePreferredFrameRate(float frameRate, int frameRateCompatibility) { if (frameRate <= 0) { return; } + if (mPreferredFrameRate > 0 && mPreferredFrameRate % frameRate != 0 + && frameRate % mPreferredFrameRate != 0) { + mIsFrameRateConflicted = true; + mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; + } + if (frameRate > mPreferredFrameRate) { + mFrameRateCompatibility = frameRateCompatibility; + } mPreferredFrameRate = Math.max(mPreferredFrameRate, frameRate); - mHasInvalidation = true; - mHandler.removeMessages(MSG_FRAME_RATE_SETTING); - mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING, - FRAME_RATE_SETTING_REEVALUATE_TIME); + + if (!mIsFrameRateConflicted) { + mHandler.removeMessages(MSG_FRAME_RATE_SETTING); + mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING, + FRAME_RATE_SETTING_REEVALUATE_TIME); + } + checkIdleness(); } /** @@ -12454,6 +12521,14 @@ public final class ViewRootImpl implements ViewParent, } /** + * Get the value of mFrameRateCompatibility + */ + @VisibleForTesting + public int getFrameRateCompatibility() { + return mFrameRateCompatibility; + } + + /** * Get the value of mIsFrameRateBoosting */ @VisibleForTesting @@ -12503,6 +12578,15 @@ public final class ViewRootImpl implements ViewParent, } /** + * Get the value of mIsFrameRateConflicted + * Can be used to checked if there is a conflict of frame rate votes. + */ + @VisibleForTesting + public boolean isFrameRateConflicted() { + return mIsFrameRateConflicted; + } + + /** * Set the value of mIsFrameRatePowerSavingsBalanced * Can be used to checked if toolkit dVRR feature is enabled. */ @@ -12515,4 +12599,14 @@ public final class ViewRootImpl implements ViewParent, private boolean shouldEnableDvrr() { return sToolkitSetFrameRateReadOnlyFlagValue && mIsFrameRatePowerSavingsBalanced; } + + private void checkIdleness() { + if (!mHasIdledMessage) { + // Check where the display is idled periodically. + // If so, set the frame rate category to NO_PREFERENCE + mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE, + FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS); + mHasIdledMessage = true; + } + } } diff --git a/core/java/android/view/accessibility/IMagnificationConnection.aidl b/core/java/android/view/accessibility/IMagnificationConnection.aidl index aae51abd3c78..450cf7558c6f 100644 --- a/core/java/android/view/accessibility/IMagnificationConnection.aidl +++ b/core/java/android/view/accessibility/IMagnificationConnection.aidl @@ -124,4 +124,9 @@ oneway interface IMagnificationConnection { * @param scale magnification scale. */ void onUserMagnificationScaleChanged(int userId, int displayId, float scale); + + /** + * Notify the changes of fullscreen magnification activation on the specified display + */ + void onFullscreenMagnificationActivationChanged(int displayId, boolean activated); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 83683caa2ea8..64e5a5bb87a2 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -50,6 +50,8 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.credentials.GetCredentialException; +import android.credentials.GetCredentialResponse; import android.graphics.Rect; import android.metrics.LogMaker; import android.os.Build; @@ -104,6 +106,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.PrintWriter; +import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -2399,6 +2402,13 @@ public final class AutofillManager { final Bundle responseData = new Bundle(); responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result); + Serializable exception = data.getSerializableExtra( + CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION, + GetCredentialException.class); + if (exception != null && Flags.autofillCredmanIntegration()) { + responseData.putSerializable( + CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION, exception); + } final Bundle newClientState = data.getBundleExtra(EXTRA_CLIENT_STATE); if (newClientState != null) { responseData.putBundle(EXTRA_CLIENT_STATE, newClientState); @@ -2925,6 +2935,107 @@ public final class AutofillManager { } } + private void onGetCredentialException(int sessionId, AutofillId id, String errorType, + String errorMsg) { + synchronized (mLock) { + if (sessionId != mSessionId) { + Log.w(TAG, "onGetCredentialException afm sessionIds don't match"); + return; + } + + final AutofillClient client = getClient(); + if (client == null) { + Log.w(TAG, "onGetCredentialException afm client id null"); + return; + } + ArrayList<AutofillId> failedIds = new ArrayList<>(); + final View[] views = client.autofillClientFindViewsByAutofillIdTraversal( + Helper.toArray(new ArrayList<>(Collections.singleton(id)))); + if (views == null || views.length == 0) { + Log.w(TAG, "onGetCredentialException afm client view not found"); + return; + } + + final View view = views[0]; + if (view == null) { + Log.i(TAG, "onGetCredentialException View is null"); + + // Most likely view has been removed after the initial request was sent to the + // the service; this is fine, but we need to update the view status in the + // server side so it can be triggered again. + Log.d(TAG, "onGetCredentialException(): no View with id " + id); + failedIds.add(id); + } + if (id.isVirtualInt()) { + Log.i(TAG, "onGetCredentialException afm client id is virtual"); + // TODO(b/326314286): Handle virtual views + } else { + Log.i(TAG, "onGetCredentialException afm client id is NOT virtual"); + view.onGetCredentialException(errorType, errorMsg); + } + handleFailedIdsLocked(failedIds); + } + } + + private void onGetCredentialResponse(int sessionId, AutofillId id, + GetCredentialResponse response) { + synchronized (mLock) { + if (sessionId != mSessionId) { + Log.w(TAG, "onGetCredentialResponse afm sessionIds don't match"); + return; + } + + final AutofillClient client = getClient(); + if (client == null) { + Log.w(TAG, "onGetCredentialResponse afm client id null"); + return; + } + ArrayList<AutofillId> failedIds = new ArrayList<>(); + final View[] views = client.autofillClientFindViewsByAutofillIdTraversal( + Helper.toArray(new ArrayList<>(Collections.singleton(id)))); + if (views == null || views.length == 0) { + Log.w(TAG, "onGetCredentialResponse afm client view not found"); + return; + } + + final View view = views[0]; + if (view == null) { + Log.i(TAG, "onGetCredentialResponse View is null"); + + // Most likely view has been removed after the initial request was sent to the + // the service; this is fine, but we need to update the view status in the + // server side so it can be triggered again. + Log.d(TAG, "onGetCredentialResponse(): no View with id " + id); + failedIds.add(id); + } + if (id.isVirtualInt()) { + Log.i(TAG, "onGetCredentialResponse afm client id is virtual"); + // TODO(b/326314286): Handle virtual views + } else { + Log.i(TAG, "onGetCredentialResponse afm client id is NOT virtual"); + view.onGetCredentialResponse(response); + } + handleFailedIdsLocked(failedIds); + } + } + + @GuardedBy("mLock") + private void handleFailedIdsLocked(ArrayList<AutofillId> failedIds) { + if (failedIds != null && !failedIds.isEmpty()) { + if (sVerbose) { + Log.v(TAG, "autofill(): total failed views: " + failedIds); + } + try { + mService.setAutofillFailure(mSessionId, failedIds, mContext.getUserId()); + } catch (RemoteException e) { + // In theory, we could ignore this error since it's not a big deal, but + // in reality, we rather crash the app anyways, as the failure could be + // a consequence of something going wrong on the server side... + throw e.rethrowFromSystemServer(); + } + } + } + private void autofill(int sessionId, List<AutofillId> ids, List<AutofillValue> values, boolean hideHighlight) { synchronized (mLock) { @@ -2991,19 +3102,7 @@ public final class AutofillManager { } } - if (failedIds != null) { - if (sVerbose) { - Log.v(TAG, "autofill(): total failed views: " + failedIds); - } - try { - mService.setAutofillFailure(mSessionId, failedIds, mContext.getUserId()); - } catch (RemoteException e) { - // In theory, we could ignore this error since it's not a big deal, but - // in reality, we rather crash the app anyways, as the failure could be - // a consequence of something going wrong on the server side... - throw e.rethrowFromSystemServer(); - } - } + handleFailedIdsLocked(failedIds); if (virtualValues != null) { for (int i = 0; i < virtualValues.size(); i++) { @@ -3431,6 +3530,10 @@ public final class AutofillManager { if (view == null) { return false; } + if (view.getViewCredentialHandler() != null) { + return true; + } + String[] hints = view.getAutofillHints(); if (hints == null) { return false; @@ -4321,6 +4424,24 @@ public final class AutofillManager { } @Override + public void onGetCredentialResponse(int sessionId, AutofillId id, + GetCredentialResponse response) { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + afm.post(() -> afm.onGetCredentialResponse(sessionId, id, response)); + } + } + + @Override + public void onGetCredentialException(int sessionId, AutofillId id, + String errorType, String errorMsg) { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + afm.post(() -> afm.onGetCredentialException(sessionId, id, errorType, errorMsg)); + } + } + + @Override public void autofillContent(int sessionId, AutofillId id, ClipData content) { final AutofillManager afm = mAfm.get(); if (afm != null) { diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 917a974f992d..904a7e0d6173 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -22,6 +22,7 @@ import android.content.ClipData; import android.content.ComponentName; import android.content.Intent; import android.content.IntentSender; +import android.credentials.GetCredentialResponse; import android.graphics.Rect; import android.os.IBinder; import android.view.autofill.AutofillId; @@ -48,6 +49,12 @@ oneway interface IAutoFillManagerClient { void autofill(int sessionId, in List<AutofillId> ids, in List<AutofillValue> values, boolean hideHighlight); + void onGetCredentialResponse(int sessionId, in AutofillId id, + in GetCredentialResponse response); + + void onGetCredentialException(int sessionId, in AutofillId id, + in String errorType, in String errorMsg); + /** * Autofills the activity with rich content data (e.g. an image) from a dataset. */ diff --git a/core/java/android/view/inputmethod/InputBinding.java b/core/java/android/view/inputmethod/InputBinding.java index 2bfeb5abb395..fedee9de1372 100644 --- a/core/java/android/view/inputmethod/InputBinding.java +++ b/core/java/android/view/inputmethod/InputBinding.java @@ -19,11 +19,13 @@ package android.view.inputmethod; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.ravenwood.annotation.RavenwoodKeepWholeClass; /** * Information given to an {@link InputMethod} about a client connecting * to it. */ +@RavenwoodKeepWholeClass public final class InputBinding implements Parcelable { static final String TAG = "InputBinding"; diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 52384791f74b..3bce155049c8 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -462,8 +462,8 @@ public final class InputMethodManager { * Flag indicating that views from the default home screen ({@link Intent#CATEGORY_HOME}) may * act as a handwriting delegator for the delegate editor view. If set, views from the home * screen package will be trusted for handwriting delegation, in addition to views in the {@code - * delegatorPackageName} passed to {@link #acceptStylusHandwritingDelegation(View, String, - * int)}. + * delegatorPackageName} passed to + * {@link #acceptStylusHandwritingDelegation(View, String, int, Executor, Consumer)} . */ @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR) public static final int HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED = 0x0001; @@ -2896,6 +2896,8 @@ public final class InputMethodManager { * @param delegateView delegate view capable of receiving input via {@link InputConnection} * @param delegatorPackageName package name of the delegator that handled initial stylus stroke. * @param flags {@link #HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED} or {@code 0} + * @param executor The executor to run the callback on. + * @param callback {@code true>} would be received if delegation was accepted. * @return {@code true} if view belongs to allowed delegate package declared in {@link * #prepareStylusHandwritingDelegation(View, String)} and delegation is accepted * @see #prepareStylusHandwritingDelegation(View, String) @@ -2908,13 +2910,16 @@ public final class InputMethodManager { // session to the delegate view. // @see #startConnectionlessStylusHandwritingForDelegation(View, ResultReceiver, // CursorAnchorInfo, String) + // @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR) - public boolean acceptStylusHandwritingDelegation( + public void acceptStylusHandwritingDelegation( @NonNull View delegateView, @NonNull String delegatorPackageName, - @HandwritingDelegateFlags int flags) { + @HandwritingDelegateFlags int flags, @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback) { Objects.requireNonNull(delegatorPackageName); - return startStylusHandwritingInternal(delegateView, delegatorPackageName, flags); + startStylusHandwritingInternal( + delegateView, delegatorPackageName, flags, executor, callback); } /** diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig index 55986e7ada47..8d3920f8b1da 100644 --- a/core/java/android/view/inputmethod/flags.aconfig +++ b/core/java/android/view/inputmethod/flags.aconfig @@ -78,3 +78,11 @@ flag { bug: "300979854" is_fixed_read_only: true } + +flag { + name: "predictive_back_ime" + namespace: "input_method" + description: "Predictive back animation for IMEs" + bug: "322836622" + is_fixed_read_only: true +} diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 57d268ced6f4..139ebc38706e 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -19,6 +19,8 @@ package android.widget; import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP; import static android.widget.TextView.ACCESSIBILITY_ACTION_SMART_START_ID; +import static com.android.graphics.hwui.flags.Flags.highContrastTextSmallTextRect; + import android.R; import android.animation.ValueAnimator; import android.annotation.IntDef; @@ -2151,8 +2153,15 @@ public class Editor { int lastLine = TextUtils.unpackRangeEndFromLong(lineRange); if (lastLine < 0) return; - layout.drawWithoutText(canvas, highlightPaths, highlightPaints, selectionHighlight, - selectionHighlightPaint, cursorOffsetVertical, firstLine, lastLine); + boolean shouldDrawHighlightsOnTop = highContrastTextSmallTextRect() + && canvas.isHighContrastTextEnabled(); + + if (!shouldDrawHighlightsOnTop) { + layout.drawWithoutText(canvas, highlightPaths, highlightPaints, selectionHighlight, + selectionHighlightPaint, cursorOffsetVertical, firstLine, lastLine); + } else { + layout.drawBackground(canvas, firstLine, lastLine); + } if (layout instanceof DynamicLayout) { if (mTextRenderNodes == null) { @@ -2226,6 +2235,11 @@ public class Editor { // Boring layout is used for empty and hint text layout.drawText(canvas, firstLine, lastLine); } + + if (shouldDrawHighlightsOnTop) { + layout.drawHighlights(canvas, highlightPaths, highlightPaints, selectionHighlight, + selectionHighlightPaint, cursorOffsetVertical, firstLine, lastLine); + } } private int drawHardwareAcceleratedInner(Canvas canvas, Layout layout, Path highlight, diff --git a/core/java/android/window/flags/accessibility.aconfig b/core/java/android/window/flags/accessibility.aconfig index d467be6e5311..814c62017391 100644 --- a/core/java/android/window/flags/accessibility.aconfig +++ b/core/java/android/window/flags/accessibility.aconfig @@ -5,4 +5,11 @@ flag { namespace: "accessibility" description: "The flag controls whether the intersection check for non-magnifiable windows is needed when onWindowTransition," bug: "312624253" +} + +flag { + name: "magnification_always_draw_fullscreen_border" + namespace: "accessibility" + description: "Always draw fullscreen orange border in fullscreen magnification" + bug: "291891390" }
\ No newline at end of file diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig new file mode 100644 index 000000000000..63a2474e70c1 --- /dev/null +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -0,0 +1,16 @@ +package: "com.android.window.flags" + +flag { + name: "enable_scaled_resizing" + namespace: "lse_desktop_experience" + description: "Enable the resizing of un-resizable apps through scaling their bounds up/down" + bug: "320350734" + is_fixed_read_only: true +} + +flag { + name: "enable_desktop_windowing_mode" + namespace: "lse_desktop_experience" + description: "Enables desktop windowing" + bug: "304778354" +} diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig index 8b3bd974b3fa..3f483418c6b3 100644 --- a/core/java/android/window/flags/window_surfaces.aconfig +++ b/core/java/android/window/flags/window_surfaces.aconfig @@ -81,3 +81,14 @@ flag { is_fixed_read_only: true bug: "321263247" } + +flag { + namespace: "window_surfaces" + name: "enable_buffer_transform_hint_from_display" + description: "Always use display info to determine VRI's buffer transform hint" + is_fixed_read_only: true + bug: "301238858" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java index 51a5ddfa8dd6..3d3db47faddb 100644 --- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java @@ -111,8 +111,9 @@ public final class AccessibilityTargetHelper { * @param context The context of the application. * @param shortcutType The shortcut type. * @return The list of {@link AccessibilityTarget}. + * @hide */ - static List<AccessibilityTarget> getInstalledTargets(Context context, + public static List<AccessibilityTarget> getInstalledTargets(Context context, @ShortcutType int shortcutType) { final List<AccessibilityTarget> targets = new ArrayList<>(); targets.addAll(getAccessibilityFilteredTargets(context, shortcutType)); diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index 73914a2a99f6..4ef0a1baa4d1 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -67,6 +67,8 @@ public class UnlaunchableAppActivity extends Activity mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT, android.content.IntentSender.class); + String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); + final UserManager userManager = UserManager.get(this); if (mUserId == UserHandle.USER_NULL) { Log.wtf(TAG, "Invalid user id: " + mUserId + ". Stopping."); @@ -74,13 +76,20 @@ public class UnlaunchableAppActivity extends Activity return; } + if (android.os.Flags.allowPrivateProfile() + && !userManager.isManagedProfile(mUserId)) { + Log.e(TAG, "Unlaunchable activity for target package " + targetPackageName + + " called for a non-managed-profile " + mUserId); + finish(); + return; + } + if (mReason != UNLAUNCHABLE_REASON_QUIET_MODE) { Log.wtf(TAG, "Invalid unlaunchable type: " + mReason); finish(); return; } - String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); boolean showEmergencyCallButton = (targetPackageName != null && targetPackageName.equals( mTelecomManager.getDefaultDialerPackage(UserHandle.of(mUserId)))); diff --git a/core/java/com/android/internal/display/RefreshRateSettingsUtils.java b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java index fab8984ce067..c23a5012923b 100644 --- a/core/java/com/android/internal/display/RefreshRateSettingsUtils.java +++ b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java @@ -16,6 +16,8 @@ package com.android.internal.display; +import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED; + import android.content.Context; import android.hardware.display.DisplayManager; import android.util.Log; @@ -54,4 +56,31 @@ public class RefreshRateSettingsUtils { } return maxRefreshRate; } + + /** + * Find the highest refresh rate among all the modes of all the displays. + * + * This method will acquire DisplayManager.mLock, so calling it while holding other locks + * should be done with care. + * @param context The context + * @return The highest refresh rate + */ + public static float findHighestRefreshRateAmongAllDisplays(Context context) { + final DisplayManager dm = context.getSystemService(DisplayManager.class); + final Display[] displays = dm.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); + if (displays.length == 0) { + Log.w(TAG, "No valid display devices"); + return DEFAULT_REFRESH_RATE; + } + + float maxRefreshRate = DEFAULT_REFRESH_RATE; + for (Display display : displays) { + for (Display.Mode mode : display.getSupportedModes()) { + if (mode.getRefreshRate() > maxRefreshRate) { + maxRefreshRate = mode.getRefreshRate(); + } + } + } + return maxRefreshRate; + } } diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java index c5c17cffa48b..2a52264515fc 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistory.java +++ b/core/java/com/android/internal/os/BatteryStatsHistory.java @@ -136,10 +136,8 @@ public class BatteryStatsHistory { private final Parcel mHistoryBuffer; private final File mSystemDir; private final HistoryStepDetailsCalculator mStepDetailsCalculator; - private final File mHistoryDir; private final Clock mClock; - private int mMaxHistoryFiles; private int mMaxHistoryBufferSize; /** @@ -150,7 +148,7 @@ public class BatteryStatsHistory { /** * A list of history files with increasing timestamps. */ - private final List<BatteryHistoryFile> mHistoryFiles = new ArrayList<>(); + private final BatteryHistoryDirectory mHistoryDir; /** * A list of small history parcels, used when BatteryStatsImpl object is created from @@ -161,7 +159,8 @@ public class BatteryStatsHistory { /** * When iterating history files, the current file index. */ - private int mCurrentFileIndex; + private BatteryHistoryFile mCurrentFile; + /** * When iterating history files, the current file parcel. */ @@ -203,7 +202,6 @@ public class BatteryStatsHistory { private byte mLastHistoryStepLevel = 0; private boolean mMutable = true; private final BatteryStatsHistory mWritableHistory; - private boolean mCleanupEnabled = true; private static class BatteryHistoryFile implements Comparable<BatteryHistoryFile> { public final long monotonicTimeMs; @@ -235,6 +233,271 @@ public class BatteryStatsHistory { } } + private static class BatteryHistoryDirectory { + private final File mDirectory; + private final MonotonicClock mMonotonicClock; + private int mMaxHistoryFiles; + private final List<BatteryHistoryFile> mHistoryFiles = new ArrayList<>(); + private final ReentrantLock mLock = new ReentrantLock(); + private boolean mCleanupNeeded; + + BatteryHistoryDirectory(File directory, MonotonicClock monotonicClock, + int maxHistoryFiles) { + mDirectory = directory; + mMonotonicClock = monotonicClock; + mMaxHistoryFiles = maxHistoryFiles; + if (mMaxHistoryFiles == 0) { + Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history"); + } + } + + void setMaxHistoryFiles(int maxHistoryFiles) { + mMaxHistoryFiles = maxHistoryFiles; + cleanup(); + } + + void lock() { + mLock.lock(); + } + + void unlock() { + mLock.unlock(); + if (mCleanupNeeded) { + cleanup(); + } + } + + boolean isLocked() { + return mLock.isLocked(); + } + + void load() { + mDirectory.mkdirs(); + if (!mDirectory.exists()) { + Slog.wtf(TAG, "HistoryDir does not exist:" + mDirectory.getPath()); + } + + final List<File> toRemove = new ArrayList<>(); + final Set<BatteryHistoryFile> dedup = new ArraySet<>(); + mDirectory.listFiles((dir, name) -> { + final int b = name.lastIndexOf(FILE_SUFFIX); + if (b <= 0) { + toRemove.add(new File(dir, name)); + return false; + } + try { + long monotonicTime = Long.parseLong(name.substring(0, b)); + dedup.add(new BatteryHistoryFile(mDirectory, monotonicTime)); + } catch (NumberFormatException e) { + toRemove.add(new File(dir, name)); + return false; + } + return true; + }); + if (!dedup.isEmpty()) { + mHistoryFiles.addAll(dedup); + Collections.sort(mHistoryFiles); + } + if (!toRemove.isEmpty()) { + // Clear out legacy history files, which did not follow the X-Y.bin naming format. + BackgroundThread.getHandler().post(() -> { + lock(); + try { + for (File file : toRemove) { + file.delete(); + } + } finally { + unlock(); + } + }); + } + } + + List<String> getFileNames() { + lock(); + try { + List<String> names = new ArrayList<>(); + for (BatteryHistoryFile historyFile : mHistoryFiles) { + names.add(historyFile.atomicFile.getBaseFile().getName()); + } + return names; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getFirstFile() { + lock(); + try { + if (!mHistoryFiles.isEmpty()) { + return mHistoryFiles.get(0); + } + return null; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getLastFile() { + lock(); + try { + if (!mHistoryFiles.isEmpty()) { + return mHistoryFiles.get(mHistoryFiles.size() - 1); + } + return null; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getNextFile(BatteryHistoryFile current, long startTimeMs, + long endTimeMs) { + if (!mLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Iterating battery history without a lock"); + } + + int nextFileIndex = 0; + int firstFileIndex = 0; + // skip the last file because its data is in history buffer. + int lastFileIndex = mHistoryFiles.size() - 2; + for (int i = lastFileIndex; i >= 0; i--) { + BatteryHistoryFile file = mHistoryFiles.get(i); + if (current != null && file.monotonicTimeMs == current.monotonicTimeMs) { + nextFileIndex = i + 1; + } + if (file.monotonicTimeMs > endTimeMs) { + lastFileIndex = i - 1; + } + if (file.monotonicTimeMs <= startTimeMs) { + firstFileIndex = i; + break; + } + } + + if (nextFileIndex < firstFileIndex) { + nextFileIndex = firstFileIndex; + } + + if (nextFileIndex <= lastFileIndex) { + return mHistoryFiles.get(nextFileIndex); + } + + return null; + } + + BatteryHistoryFile makeBatteryHistoryFile() { + BatteryHistoryFile file = new BatteryHistoryFile(mDirectory, + mMonotonicClock.monotonicTime()); + lock(); + try { + mHistoryFiles.add(file); + } finally { + unlock(); + } + return file; + } + + void writeToParcel(Parcel out, boolean useBlobs) { + lock(); + try { + final long start = SystemClock.uptimeMillis(); + out.writeInt(mHistoryFiles.size() - 1); + for (int i = 0; i < mHistoryFiles.size() - 1; i++) { + AtomicFile file = mHistoryFiles.get(i).atomicFile; + byte[] raw = new byte[0]; + try { + raw = file.readFully(); + } catch (Exception e) { + Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e); + } + if (useBlobs) { + out.writeBlob(raw); + } else { + // Avoiding blobs in the check-in file for compatibility + out.writeByteArray(raw); + } + } + if (DEBUG) { + Slog.d(TAG, + "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start)); + } + } finally { + unlock(); + } + } + + int getFileCount() { + lock(); + try { + return mHistoryFiles.size(); + } finally { + unlock(); + } + } + + int getSize() { + lock(); + try { + int ret = 0; + for (int i = 0; i < mHistoryFiles.size() - 1; i++) { + ret += (int) mHistoryFiles.get(i).atomicFile.getBaseFile().length(); + } + return ret; + } finally { + unlock(); + } + } + + void reset() { + lock(); + try { + if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!"); + for (BatteryHistoryFile file : mHistoryFiles) { + file.atomicFile.delete(); + } + mHistoryFiles.clear(); + } finally { + unlock(); + } + } + + private void cleanup() { + if (mDirectory == null) { + return; + } + + if (isLocked()) { + mCleanupNeeded = true; + return; + } + + mCleanupNeeded = false; + + lock(); + try { + // if free disk space is less than 100MB, delete oldest history file. + if (!hasFreeDiskSpace(mDirectory)) { + BatteryHistoryFile oldest = mHistoryFiles.remove(0); + oldest.atomicFile.delete(); + } + + // if there are more history files than allowed, delete oldest history files. + // mMaxHistoryFiles comes from Constants.MAX_HISTORY_FILES and + // can be updated by DeviceConfig at run time. + while (mHistoryFiles.size() > mMaxHistoryFiles) { + BatteryHistoryFile oldest = mHistoryFiles.get(0); + oldest.atomicFile.delete(); + mHistoryFiles.remove(0); + } + } finally { + unlock(); + } + } + } + /** * A delegate responsible for computing additional details for a step in battery history. */ @@ -351,7 +614,6 @@ public class BatteryStatsHistory { BatteryStatsHistory writableHistory) { mHistoryBuffer = historyBuffer; mSystemDir = systemDir; - mMaxHistoryFiles = maxHistoryFiles; mMaxHistoryBufferSize = maxHistoryBufferSize; mStepDetailsCalculator = stepDetailsCalculator; mTracer = tracer; @@ -363,66 +625,32 @@ public class BatteryStatsHistory { mMutable = false; } - mHistoryDir = new File(systemDir, HISTORY_DIR); - mHistoryDir.mkdirs(); - if (!mHistoryDir.exists()) { - Slog.wtf(TAG, "HistoryDir does not exist:" + mHistoryDir.getPath()); - } - - final List<File> toRemove = new ArrayList<>(); - final Set<BatteryHistoryFile> dedup = new ArraySet<>(); - mHistoryDir.listFiles((dir, name) -> { - final int b = name.lastIndexOf(FILE_SUFFIX); - if (b <= 0) { - toRemove.add(new File(dir, name)); - return false; - } - try { - long monotonicTime = Long.parseLong(name.substring(0, b)); - dedup.add(new BatteryHistoryFile(mHistoryDir, monotonicTime)); - } catch (NumberFormatException e) { - toRemove.add(new File(dir, name)); - return false; + if (writableHistory != null) { + mHistoryDir = writableHistory.mHistoryDir; + } else { + mHistoryDir = new BatteryHistoryDirectory(new File(systemDir, HISTORY_DIR), + monotonicClock, maxHistoryFiles); + mHistoryDir.load(); + BatteryHistoryFile activeFile = mHistoryDir.getLastFile(); + if (activeFile == null) { + activeFile = mHistoryDir.makeBatteryHistoryFile(); } - return true; - }); - if (!dedup.isEmpty()) { - mHistoryFiles.addAll(dedup); - Collections.sort(mHistoryFiles); - setActiveFile(mHistoryFiles.get(mHistoryFiles.size() - 1)); - } else if (mMutable) { - // No file found, default to have the initial file. - BatteryHistoryFile name = makeBatteryHistoryFile(); - mHistoryFiles.add(name); - setActiveFile(name); - } - if (!toRemove.isEmpty()) { - // Clear out legacy history files, which did not follow the X-Y.bin naming format. - BackgroundThread.getHandler().post(() -> { - for (File file : toRemove) { - file.delete(); - } - }); + setActiveFile(activeFile); } } - private BatteryHistoryFile makeBatteryHistoryFile() { - return new BatteryHistoryFile(mHistoryDir, mMonotonicClock.monotonicTime()); - } - - public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize, + public BatteryStatsHistory(int maxHistoryBufferSize, HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock, MonotonicClock monotonicClock) { - this(maxHistoryFiles, maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock, + this(maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock, new TraceDelegate(), new EventLogger()); } @VisibleForTesting - public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize, + public BatteryStatsHistory(int maxHistoryBufferSize, HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock, MonotonicClock monotonicClock, TraceDelegate traceDelegate, EventLogger eventLogger) { - mMaxHistoryFiles = maxHistoryFiles; mMaxHistoryBufferSize = maxHistoryBufferSize; mStepDetailsCalculator = stepDetailsCalculator; mTracer = traceDelegate; @@ -484,7 +712,9 @@ public class BatteryStatsHistory { * Changes the maximum number of history files to be kept. */ public void setMaxHistoryFiles(int maxHistoryFiles) { - mMaxHistoryFiles = maxHistoryFiles; + if (mHistoryDir != null) { + mHistoryDir.setMaxHistoryFiles(maxHistoryFiles); + } } /** @@ -513,7 +743,7 @@ public class BatteryStatsHistory { * Returns true if this instance only supports reading history. */ public boolean isReadOnly() { - return !mMutable || mActiveFile == null || mHistoryDir == null; + return !mMutable || mActiveFile == null/* || mHistoryDir == null*/; } /** @@ -538,25 +768,13 @@ public class BatteryStatsHistory { @GuardedBy("this") private void startNextFileLocked(long elapsedRealtimeMs) { - if (mMaxHistoryFiles == 0) { - Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history"); - return; - } - - if (mHistoryFiles.isEmpty()) { - Slog.wtf(TAG, "mFileNumbers should never be empty"); - return; - } - final long start = SystemClock.uptimeMillis(); writeHistory(); if (DEBUG) { Slog.d(TAG, "writeHistory took ms:" + (SystemClock.uptimeMillis() - start)); } - final BatteryHistoryFile next = makeBatteryHistoryFile(); - mHistoryFiles.add(next); - setActiveFile(next); + setActiveFile(mHistoryDir.makeBatteryHistoryFile()); try { mActiveFile.getBaseFile().createNewFile(); } catch (IOException e) { @@ -578,37 +796,7 @@ public class BatteryStatsHistory { } mWrittenPowerStatsDescriptors.clear(); - cleanupLocked(); - } - - @GuardedBy("this") - private void setCleanupEnabledLocked(boolean enabled) { - mCleanupEnabled = enabled; - if (mCleanupEnabled) { - cleanupLocked(); - } - } - - @GuardedBy("this") - private void cleanupLocked() { - if (!mCleanupEnabled || mHistoryDir == null) { - return; - } - - // if free disk space is less than 100MB, delete oldest history file. - if (!hasFreeDiskSpace()) { - BatteryHistoryFile oldest = mHistoryFiles.remove(0); - oldest.atomicFile.delete(); - } - - // if there are more history files than allowed, delete oldest history files. - // mMaxHistoryFiles comes from Constants.MAX_HISTORY_FILES and can be updated by GService - // config at run time. - while (mHistoryFiles.size() > mMaxHistoryFiles) { - BatteryHistoryFile oldest = mHistoryFiles.get(0); - oldest.atomicFile.delete(); - mHistoryFiles.remove(0); - } + mHistoryDir.cleanup(); } /** @@ -616,9 +804,7 @@ public class BatteryStatsHistory { * currently being read. */ public boolean isResetEnabled() { - synchronized (this) { - return mCleanupEnabled; - } + return mHistoryDir == null || !mHistoryDir.isLocked(); } /** @@ -627,16 +813,10 @@ public class BatteryStatsHistory { */ public void reset() { synchronized (this) { - if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!"); - for (BatteryHistoryFile file : mHistoryFiles) { - file.atomicFile.delete(); + if (mHistoryDir != null) { + mHistoryDir.reset(); + setActiveFile(mHistoryDir.makeBatteryHistoryFile()); } - mHistoryFiles.clear(); - - BatteryHistoryFile name = makeBatteryHistoryFile(); - mHistoryFiles.add(name); - setActiveFile(name); - initHistoryBuffer(); } } @@ -646,8 +826,9 @@ public class BatteryStatsHistory { */ public long getStartTime() { synchronized (this) { - if (!mHistoryFiles.isEmpty()) { - return mHistoryFiles.get(0).monotonicTimeMs; + BatteryHistoryFile file = mHistoryDir.getFirstFile(); + if (file != null) { + return file.monotonicTimeMs; } else { return mHistoryBufferStartTime; } @@ -668,15 +849,13 @@ public class BatteryStatsHistory { return copy().iterate(startTimeMs, endTimeMs); } - mCurrentFileIndex = 0; + if (mHistoryDir != null) { + mHistoryDir.lock(); + } + mCurrentFile = null; mCurrentParcel = null; mCurrentParcelEnd = 0; mParcelIndex = 0; - if (mWritableHistory != null) { - synchronized (mWritableHistory) { - mWritableHistory.setCleanupEnabledLocked(false); - } - } return new BatteryStatsHistoryIterator(this, startTimeMs, endTimeMs); } @@ -685,10 +864,8 @@ public class BatteryStatsHistory { */ void iteratorFinished() { mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); - if (mWritableHistory != null) { - synchronized (mWritableHistory) { - mWritableHistory.setCleanupEnabledLocked(true); - } + if (mHistoryDir != null) { + mHistoryDir.unlock(); } } @@ -719,39 +896,27 @@ public class BatteryStatsHistory { } } - int firstFileIndex = 0; - // skip the last file because its data is in history buffer. - int lastFileIndex = mHistoryFiles.size() - 1; - for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { - BatteryHistoryFile file = mHistoryFiles.get(i); - if (file.monotonicTimeMs >= endTimeMs) { - lastFileIndex = i; - } - if (file.monotonicTimeMs <= startTimeMs) { - firstFileIndex = i; - break; - } - } - - if (mCurrentFileIndex < firstFileIndex) { - mCurrentFileIndex = firstFileIndex; - } - - while (mCurrentFileIndex < lastFileIndex) { - mCurrentParcel = null; - mCurrentParcelEnd = 0; - final Parcel p = Parcel.obtain(); - AtomicFile file = mHistoryFiles.get(mCurrentFileIndex++).atomicFile; - if (readFileToParcel(p, file)) { - int bufSize = p.readInt(); - int curPos = p.dataPosition(); - mCurrentParcelEnd = curPos + bufSize; - mCurrentParcel = p; - if (curPos < mCurrentParcelEnd) { - return mCurrentParcel; + if (mHistoryDir != null) { + BatteryHistoryFile nextFile = mHistoryDir.getNextFile(mCurrentFile, startTimeMs, + endTimeMs); + while (nextFile != null) { + mCurrentParcel = null; + mCurrentParcelEnd = 0; + final Parcel p = Parcel.obtain(); + AtomicFile file = nextFile.atomicFile; + if (readFileToParcel(p, file)) { + int bufSize = p.readInt(); + int curPos = p.dataPosition(); + mCurrentParcelEnd = curPos + bufSize; + mCurrentParcel = p; + if (curPos < mCurrentParcelEnd) { + mCurrentFile = nextFile; + return mCurrentParcel; + } + } else { + p.recycle(); } - } else { - p.recycle(); + nextFile = mHistoryDir.getNextFile(nextFile, startTimeMs, endTimeMs); } } @@ -922,25 +1087,8 @@ public class BatteryStatsHistory { } private void writeToParcel(Parcel out, boolean useBlobs) { - final long start = SystemClock.uptimeMillis(); - out.writeInt(mHistoryFiles.size() - 1); - for (int i = 0; i < mHistoryFiles.size() - 1; i++) { - AtomicFile file = mHistoryFiles.get(i).atomicFile; - byte[] raw = new byte[0]; - try { - raw = file.readFully(); - } catch (Exception e) { - Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e); - } - if (useBlobs) { - out.writeBlob(raw); - } else { - // Avoiding blobs in the check-in file for compatibility - out.writeByteArray(raw); - } - } - if (DEBUG) { - Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start)); + if (mHistoryDir != null) { + mHistoryDir.writeToParcel(out, useBlobs); } } @@ -1021,22 +1169,18 @@ public class BatteryStatsHistory { * @return true if there is more than 100MB free disk space left. */ @android.ravenwood.annotation.RavenwoodReplace - private boolean hasFreeDiskSpace() { - final StatFs stats = new StatFs(mHistoryDir.getAbsolutePath()); + private static boolean hasFreeDiskSpace(File systemDir) { + final StatFs stats = new StatFs(systemDir.getAbsolutePath()); return stats.getAvailableBytes() > MIN_FREE_SPACE; } - private boolean hasFreeDiskSpace$ravenwood() { + private static boolean hasFreeDiskSpace$ravenwood(File systemDir) { return true; } @VisibleForTesting public List<String> getFilesNames() { - List<String> names = new ArrayList<>(); - for (BatteryHistoryFile historyFile : mHistoryFiles) { - names.add(historyFile.atomicFile.getBaseFile().getName()); - } - return names; + return mHistoryDir.getFileNames(); } @VisibleForTesting @@ -1048,10 +1192,7 @@ public class BatteryStatsHistory { * @return the total size of all history files and history buffer. */ public int getHistoryUsedSize() { - int ret = 0; - for (int i = 0; i < mHistoryFiles.size() - 1; i++) { - ret += mHistoryFiles.get(i).atomicFile.getBaseFile().length(); - } + int ret = mHistoryDir.getSize(); ret += mHistoryBuffer.dataSize(); if (mHistoryParcels != null) { for (int i = 0; i < mHistoryParcels.size(); i++) { @@ -1109,7 +1250,7 @@ public class BatteryStatsHistory { */ public void continueRecordingHistory() { synchronized (this) { - if (mHistoryBuffer.dataPosition() <= 0 && mHistoryFiles.size() <= 1) { + if (mHistoryBuffer.dataPosition() <= 0 && mHistoryDir.getFileCount() <= 1) { return; } diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java index b2a6a934ba3f..83e9407fbdde 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java @@ -44,6 +44,7 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor private BatteryStats.HistoryItem mHistoryItem = new BatteryStats.HistoryItem(); private boolean mNextItemReady; private boolean mTimeInitialized; + private boolean mClosed; public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history, long startTimeMs, long endTimeMs) { @@ -322,6 +323,9 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor */ @Override public void close() { - mBatteryStatsHistory.iteratorFinished(); + if (!mClosed) { + mClosed = true; + mBatteryStatsHistory.iteratorFinished(); + } } } diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java index abe6c7c079c2..d9ac5a9fe47a 100644 --- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,8 +37,11 @@ import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ILogger; +import com.android.internal.protolog.common.IProtoLog; import com.android.internal.protolog.common.IProtoLogGroup; import com.android.internal.protolog.common.LogDataType; +import com.android.internal.protolog.common.LogLevel; import com.android.internal.util.TraceBuffer; import java.io.File; @@ -48,52 +51,49 @@ import java.util.ArrayList; import java.util.TreeMap; import java.util.stream.Collectors; - /** * A service for the ProtoLog logging system. */ -public class BaseProtoLogImpl { - protected static final TreeMap<String, IProtoLogGroup> LOG_GROUPS = new TreeMap<>(); - - /** - * A runnable to update the cached output of {@link #isEnabled}. - * - * Must be invoked after every action that could change the result of {@link #isEnabled}, eg. - * starting / stopping proto log, or enabling / disabling log groups. - */ - public static Runnable sCacheUpdater = () -> { }; - - protected static void addLogGroupEnum(IProtoLogGroup[] config) { - for (IProtoLogGroup group : config) { - LOG_GROUPS.put(group.name(), group); - } - } +public class LegacyProtoLogImpl implements IProtoLog { + private final TreeMap<String, IProtoLogGroup> mLogGroups = new TreeMap<>(); + private static final int BUFFER_CAPACITY = 1024 * 1024; + private static final int PER_CHUNK_SIZE = 1024; private static final String TAG = "ProtoLog"; private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L; static final String PROTOLOG_VERSION = "1.0.0"; private static final int DEFAULT_PER_CHUNK_SIZE = 0; private final File mLogFile; - private final String mViewerConfigFilename; + private final String mLegacyViewerConfigFilename; private final TraceBuffer mBuffer; - protected final ProtoLogViewerConfigReader mViewerConfig; + private final LegacyProtoLogViewerConfigReader mViewerConfig; private final int mPerChunkSize; private boolean mProtoLogEnabled; private boolean mProtoLogEnabledLockFree; private final Object mProtoLogEnabledLock = new Object(); - @VisibleForTesting - public enum LogLevel { - DEBUG, VERBOSE, INFO, WARN, ERROR, WTF + public LegacyProtoLogImpl(String outputFile, String viewerConfigFilename) { + this(new File(outputFile), viewerConfigFilename, BUFFER_CAPACITY, + new LegacyProtoLogViewerConfigReader(), PER_CHUNK_SIZE); + } + + public LegacyProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity, + LegacyProtoLogViewerConfigReader viewerConfig, int perChunkSize) { + mLogFile = file; + mBuffer = new TraceBuffer(bufferCapacity); + mLegacyViewerConfigFilename = viewerConfigFilename; + mViewerConfig = viewerConfig; + mPerChunkSize = perChunkSize; } /** * Main log method, do not call directly. */ @VisibleForTesting - public void log(LogLevel level, IProtoLogGroup group, int messageHash, int paramsMask, + @Override + public void log(LogLevel level, IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object[] args) { if (group.isLogToProto()) { logToProto(messageHash, paramsMask, args); @@ -103,7 +103,7 @@ public class BaseProtoLogImpl { } } - private void logToLogcat(String tag, LogLevel level, int messageHash, + private void logToLogcat(String tag, LogLevel level, long messageHash, @Nullable String messageString, Object[] args) { String message = null; if (messageString == null) { @@ -157,7 +157,7 @@ public class BaseProtoLogImpl { } } - private void logToProto(int messageHash, int paramsMask, Object[] args) { + private void logToProto(long messageHash, int paramsMask, Object[] args) { if (!isProtoEnabled()) { return; } @@ -219,20 +219,6 @@ public class BaseProtoLogImpl { } } - public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity, - ProtoLogViewerConfigReader viewerConfig) { - this(file, viewerConfigFilename, bufferCapacity, viewerConfig, DEFAULT_PER_CHUNK_SIZE); - } - - public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity, - ProtoLogViewerConfigReader viewerConfig, int perChunkSize) { - mLogFile = file; - mBuffer = new TraceBuffer(bufferCapacity); - mViewerConfigFilename = viewerConfigFilename; - mViewerConfig = viewerConfig; - mPerChunkSize = perChunkSize; - } - /** * Starts the logging a circular proto buffer. * @@ -248,7 +234,6 @@ public class BaseProtoLogImpl { mProtoLogEnabled = true; mProtoLogEnabledLockFree = true; } - sCacheUpdater.run(); } /** @@ -274,7 +259,6 @@ public class BaseProtoLogImpl { throw new IllegalStateException("logging enabled while waiting for flush."); } } - sCacheUpdater.run(); } /** @@ -284,11 +268,11 @@ public class BaseProtoLogImpl { return mProtoLogEnabledLockFree; } - protected int setLogging(boolean setTextLogging, boolean value, PrintWriter pw, + private int setLogging(boolean setTextLogging, boolean value, ILogger logger, String... groups) { for (int i = 0; i < groups.length; i++) { String group = groups[i]; - IProtoLogGroup g = LOG_GROUPS.get(group); + IProtoLogGroup g = mLogGroups.get(group); if (g != null) { if (setTextLogging) { g.setLogToLogcat(value); @@ -296,11 +280,10 @@ public class BaseProtoLogImpl { g.setLogToProto(value); } } else { - logAndPrintln(pw, "No IProtoLogGroup named " + group); + logger.log("No IProtoLogGroup named " + group); return -1; } } - sCacheUpdater.run(); return 0; } @@ -330,6 +313,7 @@ public class BaseProtoLogImpl { while ((arg = shell.getNextArg()) != null) { args.add(arg); } + final ILogger logger = (msg) -> logAndPrintln(pw, msg); String[] groups = args.toArray(new String[args.size()]); switch (cmd) { case "start": @@ -342,14 +326,14 @@ public class BaseProtoLogImpl { logAndPrintln(pw, getStatus()); return 0; case "enable": - return setLogging(false, true, pw, groups); + return setLogging(false, true, logger, groups); case "enable-text": - mViewerConfig.loadViewerConfig(pw, mViewerConfigFilename); - return setLogging(true, true, pw, groups); + mViewerConfig.loadViewerConfig(logger, mLegacyViewerConfigFilename); + return setLogging(true, true, logger, groups); case "disable": - return setLogging(false, false, pw, groups); + return setLogging(false, false, logger, groups); case "disable-text": - return setLogging(true, false, pw, groups); + return setLogging(true, false, logger, groups); default: return unknownCommand(pw); } @@ -362,12 +346,12 @@ public class BaseProtoLogImpl { return "ProtoLog status: " + ((isProtoEnabled()) ? "Enabled" : "Disabled") + "\nEnabled log groups: \n Proto: " - + LOG_GROUPS.values().stream().filter( - it -> it.isEnabled() && it.isLogToProto()) + + mLogGroups.values().stream().filter( + it -> it.isEnabled() && it.isLogToProto()) .map(IProtoLogGroup::name).collect(Collectors.joining(" ")) + "\n Logcat: " - + LOG_GROUPS.values().stream().filter( - it -> it.isEnabled() && it.isLogToLogcat()) + + mLogGroups.values().stream().filter( + it -> it.isEnabled() && it.isLogToLogcat()) .map(IProtoLogGroup::name).collect(Collectors.joining(" ")) + "\nLogging definitions loaded: " + mViewerConfig.knownViewerStringsNumber(); } @@ -393,5 +377,26 @@ public class BaseProtoLogImpl { pw.flush(); } } + + /** + * Start text logging + * @param groups Groups to start text logging for + * @param logger A logger to write status updates to + * @return status code + */ + public int startLoggingToLogcat(String[] groups, ILogger logger) { + mViewerConfig.loadViewerConfig(logger, mLegacyViewerConfigFilename); + return setLogging(true /* setTextLogging */, true, logger, groups); + } + + /** + * Stop text logging + * @param groups Groups to start text logging for + * @param logger A logger to write status updates to + * @return status code + */ + public int stopLoggingToLogcat(String[] groups, ILogger logger) { + return setLogging(true /* setTextLogging */, false, logger, groups); + } } diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/LegacyProtoLogViewerConfigReader.java new file mode 100644 index 000000000000..1833410950ba --- /dev/null +++ b/core/java/com/android/internal/protolog/LegacyProtoLogViewerConfigReader.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import com.android.internal.protolog.common.ILogger; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; +import java.util.zip.GZIPInputStream; + +/** + * Handles loading and parsing of ProtoLog viewer configuration. + */ +public class LegacyProtoLogViewerConfigReader { + + private static final String TAG = "ProtoLogViewerConfigReader"; + private Map<Long, String> mLogMessageMap = null; + + /** Returns message format string for its hash or null if unavailable. */ + public synchronized String getViewerString(long messageHash) { + if (mLogMessageMap != null) { + return mLogMessageMap.get(messageHash); + } else { + return null; + } + } + + /** + * Reads the specified viewer configuration file. Does nothing if the config is already loaded. + */ + public synchronized void loadViewerConfig(ILogger logger, String viewerConfigFilename) { + try { + loadViewerConfig(new GZIPInputStream(new FileInputStream(viewerConfigFilename))); + logger.log("Loaded " + mLogMessageMap.size() + + " log definitions from " + viewerConfigFilename); + } catch (FileNotFoundException e) { + logger.log("Unable to load log definitions: File " + + viewerConfigFilename + " not found." + e); + } catch (IOException e) { + logger.log("Unable to load log definitions: IOException while reading " + + viewerConfigFilename + ". " + e); + } catch (JSONException e) { + logger.log("Unable to load log definitions: JSON parsing exception while reading " + + viewerConfigFilename + ". " + e); + } + } + + /** + * Reads the specified viewer configuration input stream. + * Does nothing if the config is already loaded. + */ + public synchronized void loadViewerConfig(InputStream viewerConfigInputStream) + throws IOException, JSONException { + if (mLogMessageMap != null) { + return; + } + InputStreamReader config = new InputStreamReader(viewerConfigInputStream); + BufferedReader reader = new BufferedReader(config); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + builder.append(line).append('\n'); + } + reader.close(); + JSONObject json = new JSONObject(builder.toString()); + JSONObject messages = json.getJSONObject("messages"); + + mLogMessageMap = new TreeMap<>(); + Iterator it = messages.keys(); + while (it.hasNext()) { + String key = (String) it.next(); + try { + long hash = Long.parseLong(key); + JSONObject val = messages.getJSONObject(key); + String msg = val.getString("message"); + mLogMessageMap.put(hash, msg); + } catch (NumberFormatException expected) { + // Not a messageHash - skip it + } + } + } + + /** + * Returns the number of loaded log definitions kept in memory. + */ + public synchronized int knownViewerStringsNumber() { + if (mLogMessageMap != null) { + return mLogMessageMap.size(); + } + return 0; + } + +} diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java new file mode 100644 index 000000000000..53062d837cfa --- /dev/null +++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import static perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STACKTRACE; +import static perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STRING_ARGS; +import static perfetto.protos.PerfettoTrace.InternedString.IID; +import static perfetto.protos.PerfettoTrace.InternedString.STR; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.BOOLEAN_PARAMS; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.DOUBLE_PARAMS; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.STACKTRACE_IID; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.MESSAGE_ID; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.SINT64_PARAMS; +import static perfetto.protos.PerfettoTrace.ProtoLogMessage.STR_PARAM_IIDS; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.GROUPS; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.ID; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.NAME; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.TAG; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.GROUP_ID; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.LEVEL; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE; +import static perfetto.protos.PerfettoTrace.TracePacket.INTERNED_DATA; +import static perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_MESSAGE; +import static perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_VIEWER_CONFIG; +import static perfetto.protos.PerfettoTrace.TracePacket.SEQUENCE_FLAGS; +import static perfetto.protos.PerfettoTrace.TracePacket.SEQ_INCREMENTAL_STATE_CLEARED; +import static perfetto.protos.PerfettoTrace.TracePacket.SEQ_NEEDS_INCREMENTAL_STATE; +import static perfetto.protos.PerfettoTrace.TracePacket.TIMESTAMP; + +import android.annotation.Nullable; +import android.os.ShellCommand; +import android.os.SystemClock; +import android.os.Trace; +import android.text.TextUtils; +import android.tracing.perfetto.DataSourceParams; +import android.tracing.perfetto.InitArguments; +import android.tracing.perfetto.Producer; +import android.tracing.perfetto.TracingContext; +import android.util.LongArray; +import android.util.Slog; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ILogger; +import com.android.internal.protolog.common.IProtoLog; +import com.android.internal.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.LogDataType; +import com.android.internal.protolog.common.LogLevel; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicInteger; + +import perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData; + +/** + * A service for the ProtoLog logging system. + */ +public class PerfettoProtoLogImpl implements IProtoLog { + private final TreeMap<String, IProtoLogGroup> mLogGroups = new TreeMap<>(); + private static final String LOG_TAG = "ProtoLog"; + private final AtomicInteger mTracingInstances = new AtomicInteger(); + + private final ProtoLogDataSource mDataSource = new ProtoLogDataSource( + this.mTracingInstances::incrementAndGet, + this::dumpTransitionTraceConfig, + this.mTracingInstances::decrementAndGet + ); + private final ProtoLogViewerConfigReader mViewerConfigReader; + private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider; + + public PerfettoProtoLogImpl(String viewerConfigFilePath) { + this(() -> { + try { + return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); + } catch (FileNotFoundException e) { + Slog.w(LOG_TAG, "Failed to load viewer config file " + viewerConfigFilePath, e); + return null; + } + }); + } + + public PerfettoProtoLogImpl(ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) { + this(viewerConfigInputStreamProvider, + new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider)); + } + + @VisibleForTesting + public PerfettoProtoLogImpl( + ViewerConfigInputStreamProvider viewerConfigInputStreamProvider, + ProtoLogViewerConfigReader viewerConfigReader + ) { + Producer.init(InitArguments.DEFAULTS); + mDataSource.register(DataSourceParams.DEFAULTS); + this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider; + this.mViewerConfigReader = viewerConfigReader; + } + + /** + * Main log method, do not call directly. + */ + @VisibleForTesting + @Override + public void log(LogLevel level, IProtoLogGroup group, long messageHash, int paramsMask, + @Nullable String messageString, Object[] args) { + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "log"); + + long tsNanos = SystemClock.elapsedRealtimeNanos(); + try { + logToProto(level, group.name(), messageHash, paramsMask, args, tsNanos); + if (group.isLogToLogcat()) { + logToLogcat(group.getTag(), level, messageHash, messageString, args); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } + } + + private void dumpTransitionTraceConfig() { + ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream(); + + if (pis == null) { + Slog.w(LOG_TAG, "Failed to get viewer input stream."); + return; + } + + mDataSource.trace(ctx -> { + final ProtoOutputStream os = ctx.newTracePacket(); + + os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos()); + + final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG); + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + if (pis.getFieldNumber() == (int) MESSAGES) { + final long inMessageToken = pis.start(MESSAGES); + final long outMessagesToken = os.start(MESSAGES); + + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (pis.getFieldNumber()) { + case (int) MessageData.MESSAGE_ID: + os.write(MessageData.MESSAGE_ID, + pis.readLong(MessageData.MESSAGE_ID)); + break; + case (int) MESSAGE: + os.write(MESSAGE, pis.readString(MESSAGE)); + break; + case (int) LEVEL: + os.write(LEVEL, pis.readInt(LEVEL)); + break; + case (int) GROUP_ID: + os.write(GROUP_ID, pis.readInt(GROUP_ID)); + break; + default: + throw new RuntimeException( + "Unexpected field id " + pis.getFieldNumber()); + } + } + + pis.end(inMessageToken); + os.end(outMessagesToken); + } + + if (pis.getFieldNumber() == (int) GROUPS) { + final long inGroupToken = pis.start(GROUPS); + final long outGroupToken = os.start(GROUPS); + + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (pis.getFieldNumber()) { + case (int) ID: + int id = pis.readInt(ID); + os.write(ID, id); + break; + case (int) NAME: + String name = pis.readString(NAME); + os.write(NAME, name); + break; + case (int) TAG: + String tag = pis.readString(TAG); + os.write(TAG, tag); + break; + default: + throw new RuntimeException( + "Unexpected field id " + pis.getFieldNumber()); + } + } + + pis.end(inGroupToken); + os.end(outGroupToken); + } + } + + os.end(outProtologViewerConfigToken); + + ctx.flush(); + }); + + mDataSource.flush(); + } + + private void logToLogcat(String tag, LogLevel level, long messageHash, + @Nullable String messageString, Object[] args) { + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "logToLogcat"); + try { + doLogToLogcat(tag, level, messageHash, messageString, args); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } + } + + private void doLogToLogcat(String tag, LogLevel level, long messageHash, + @androidx.annotation.Nullable String messageString, Object[] args) { + String message = null; + if (messageString == null) { + messageString = mViewerConfigReader.getViewerString(messageHash); + } + if (messageString != null) { + if (args != null) { + try { + message = TextUtils.formatSimple(messageString, args); + } catch (Exception ex) { + Slog.w(LOG_TAG, "Invalid ProtoLog format string.", ex); + } + } else { + message = messageString; + } + } + if (message == null) { + StringBuilder builder = new StringBuilder("UNKNOWN MESSAGE (" + messageHash + ")"); + for (Object o : args) { + builder.append(" ").append(o); + } + message = builder.toString(); + } + passToLogcat(tag, level, message); + } + + /** + * SLog wrapper. + */ + @VisibleForTesting + public void passToLogcat(String tag, LogLevel level, String message) { + switch (level) { + case DEBUG: + Slog.d(tag, message); + break; + case VERBOSE: + Slog.v(tag, message); + break; + case INFO: + Slog.i(tag, message); + break; + case WARN: + Slog.w(tag, message); + break; + case ERROR: + Slog.e(tag, message); + break; + case WTF: + Slog.wtf(tag, message); + break; + } + } + + private void logToProto(LogLevel level, String groupName, long messageHash, int paramsMask, + Object[] args, long tsNanos) { + if (!isProtoEnabled()) { + return; + } + + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "logToProto"); + try { + doLogToProto(level, groupName, messageHash, paramsMask, args, tsNanos); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } + } + + private void doLogToProto(LogLevel level, String groupName, long messageHash, int paramsMask, + Object[] args, long tsNanos) { + mDataSource.trace(ctx -> { + final ProtoLogDataSource.TlsState tlsState = ctx.getCustomTlsState(); + final LogLevel logFrom = tlsState.getLogFromLevel(groupName); + + if (level.ordinal() < logFrom.ordinal()) { + return; + } + + if (args != null) { + // Intern all string params before creating the trace packet for the proto + // message so that the interned strings appear before in the trace to make the + // trace processing easier. + int argIndex = 0; + for (Object o : args) { + int type = LogDataType.bitmaskToLogDataType(paramsMask, argIndex); + if (type == LogDataType.STRING) { + internStringArg(ctx, o.toString()); + } + argIndex++; + } + } + + int internedStacktrace = 0; + if (tlsState.getShouldCollectStacktrace(groupName)) { + // Intern stackstraces before creating the trace packet for the proto message so + // that the interned stacktrace strings appear before in the trace to make the + // trace processing easier. + String stacktrace = collectStackTrace(); + internedStacktrace = internStacktraceString(ctx, stacktrace); + } + + final ProtoOutputStream os = ctx.newTracePacket(); + os.write(TIMESTAMP, tsNanos); + long token = os.start(PROTOLOG_MESSAGE); + os.write(MESSAGE_ID, messageHash); + + boolean needsIncrementalState = false; + + if (args != null) { + + int argIndex = 0; + LongArray longParams = new LongArray(); + ArrayList<Double> doubleParams = new ArrayList<>(); + ArrayList<Boolean> booleanParams = new ArrayList<>(); + for (Object o : args) { + int type = LogDataType.bitmaskToLogDataType(paramsMask, argIndex); + try { + switch (type) { + case LogDataType.STRING: + final int internedStringId = internStringArg(ctx, o.toString()); + os.write(STR_PARAM_IIDS, internedStringId); + needsIncrementalState = true; + break; + case LogDataType.LONG: + longParams.add(((Number) o).longValue()); + break; + case LogDataType.DOUBLE: + doubleParams.add(((Number) o).doubleValue()); + break; + case LogDataType.BOOLEAN: + booleanParams.add((boolean) o); + break; + } + } catch (ClassCastException ex) { + Slog.e(LOG_TAG, "Invalid ProtoLog paramsMask", ex); + } + argIndex++; + } + + for (int i = 0; i < longParams.size(); ++i) { + os.write(SINT64_PARAMS, longParams.get(i)); + } + doubleParams.forEach(it -> os.write(DOUBLE_PARAMS, it)); + // Converting booleans to int because Perfetto doesn't yet support repeated + // booleans, so we use a repeated integers instead (b/313651412). + booleanParams.forEach(it -> os.write(BOOLEAN_PARAMS, it ? 1 : 0)); + } + + if (tlsState.getShouldCollectStacktrace(groupName)) { + os.write(STACKTRACE_IID, internedStacktrace); + } + + os.end(token); + + if (needsIncrementalState) { + os.write(SEQUENCE_FLAGS, SEQ_NEEDS_INCREMENTAL_STATE); + } + + }); + } + + private static final int STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL = 12; + + private String collectStackTrace() { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + for (int i = STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL; i < stackTrace.length; ++i) { + pw.println("\tat " + stackTrace[i]); + } + } + + return sw.toString(); + } + + private int internStacktraceString(TracingContext<ProtoLogDataSource.Instance, + ProtoLogDataSource.TlsState, + ProtoLogDataSource.IncrementalState> ctx, + String stacktrace) { + final ProtoLogDataSource.IncrementalState incrementalState = ctx.getIncrementalState(); + return internString(ctx, incrementalState.stacktraceInterningMap, + PROTOLOG_STACKTRACE, stacktrace); + } + + private int internStringArg( + TracingContext<ProtoLogDataSource.Instance, + ProtoLogDataSource.TlsState, + ProtoLogDataSource.IncrementalState> ctx, + String string + ) { + final ProtoLogDataSource.IncrementalState incrementalState = ctx.getIncrementalState(); + return internString(ctx, incrementalState.argumentInterningMap, + PROTOLOG_STRING_ARGS, string); + } + + private int internString( + TracingContext<ProtoLogDataSource.Instance, + ProtoLogDataSource.TlsState, + ProtoLogDataSource.IncrementalState> ctx, + Map<String, Integer> internMap, + long fieldId, + String string + ) { + final ProtoLogDataSource.IncrementalState incrementalState = ctx.getIncrementalState(); + + if (!incrementalState.clearReported) { + final ProtoOutputStream os = ctx.newTracePacket(); + os.write(SEQUENCE_FLAGS, SEQ_INCREMENTAL_STATE_CLEARED); + incrementalState.clearReported = true; + } + + if (!internMap.containsKey(string)) { + final int internedIndex = internMap.size() + 1; + internMap.put(string, internedIndex); + + final ProtoOutputStream os = ctx.newTracePacket(); + final long token = os.start(INTERNED_DATA); + final long innerToken = os.start(fieldId); + os.write(IID, internedIndex); + os.write(STR, string.getBytes()); + os.end(innerToken); + os.end(token); + } + + return internMap.get(string); + } + + /** + * Responds to a shell command. + */ + public int onShellCommand(ShellCommand shell) { + PrintWriter pw = shell.getOutPrintWriter(); + String cmd = shell.getNextArg(); + if (cmd == null) { + return unknownCommand(pw); + } + ArrayList<String> args = new ArrayList<>(); + String arg; + while ((arg = shell.getNextArg()) != null) { + args.add(arg); + } + final ILogger logger = (msg) -> logAndPrintln(pw, msg); + String[] groups = args.toArray(new String[args.size()]); + switch (cmd) { + case "enable-text": + return this.startLoggingToLogcat(groups, logger); + case "disable-text": + return this.stopLoggingToLogcat(groups, logger); + default: + return unknownCommand(pw); + } + } + + private int unknownCommand(PrintWriter pw) { + pw.println("Unknown command"); + pw.println("Window manager logging options:"); + pw.println(" enable-text [group...]: Enable logcat logging for given groups"); + pw.println(" disable-text [group...]: Disable logcat logging for given groups"); + return -1; + } + + /** + * Returns {@code true} iff logging to proto is enabled. + */ + public boolean isProtoEnabled() { + return mTracingInstances.get() > 0; + } + + /** + * Start text logging + * @param groups Groups to start text logging for + * @param logger A logger to write status updates to + * @return status code + */ + public int startLoggingToLogcat(String[] groups, ILogger logger) { + mViewerConfigReader.loadViewerConfig(logger); + return setTextLogging(true, logger, groups); + } + + /** + * Stop text logging + * @param groups Groups to start text logging for + * @param logger A logger to write status updates to + * @return status code + */ + public int stopLoggingToLogcat(String[] groups, ILogger logger) { + mViewerConfigReader.unloadViewerConfig(); + return setTextLogging(false, logger, groups); + } + + /** + * Start logging the stack trace of the when the log message happened for target groups + * @return status code + */ + public int startLoggingStackTrace(String[] groups, ILogger logger) { + return -1; + } + + /** + * Stop logging the stack trace of the when the log message happened for target groups + * @return status code + */ + public int stopLoggingStackTrace() { + return -1; + } + + private int setTextLogging(boolean value, ILogger logger, String... groups) { + for (int i = 0; i < groups.length; i++) { + String group = groups[i]; + IProtoLogGroup g = mLogGroups.get(group); + if (g != null) { + g.setLogToLogcat(value); + } else { + logger.log("No IProtoLogGroup named " + group); + return -1; + } + } + return 0; + } + + static void logAndPrintln(@Nullable PrintWriter pw, String msg) { + Slog.i(LOG_TAG, msg); + if (pw != null) { + pw.println(msg); + pw.flush(); + } + } +} + diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSource.java b/core/java/com/android/internal/protolog/ProtoLogDataSource.java new file mode 100644 index 000000000000..a8ff75d6595e --- /dev/null +++ b/core/java/com/android/internal/protolog/ProtoLogDataSource.java @@ -0,0 +1,294 @@ +/* + * 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.protolog; + +import static perfetto.protos.PerfettoTrace.DataSourceConfig.PROTOLOG_CONFIG; +import static perfetto.protos.PerfettoTrace.ProtoLogConfig.GROUP_OVERRIDES; +import static perfetto.protos.PerfettoTrace.ProtoLogConfig.TRACING_MODE; +import static perfetto.protos.PerfettoTrace.ProtoLogGroup.COLLECT_STACKTRACE; +import static perfetto.protos.PerfettoTrace.ProtoLogGroup.LOG_FROM; +import static perfetto.protos.PerfettoTrace.ProtoLogGroup.GROUP_NAME; + +import android.tracing.perfetto.CreateIncrementalStateArgs; +import android.tracing.perfetto.CreateTlsStateArgs; +import android.tracing.perfetto.DataSource; +import android.tracing.perfetto.DataSourceInstance; +import android.tracing.perfetto.FlushCallbackArguments; +import android.tracing.perfetto.StartCallbackArguments; +import android.tracing.perfetto.StopCallbackArguments; +import android.util.proto.ProtoInputStream; +import android.util.proto.WireTypeMismatchException; + +import com.android.internal.protolog.common.LogLevel; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import perfetto.protos.PerfettoTrace; + +public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance, + ProtoLogDataSource.TlsState, + ProtoLogDataSource.IncrementalState> { + + private final Runnable mOnStart; + private final Runnable mOnFlush; + private final Runnable mOnStop; + + public ProtoLogDataSource(Runnable onStart, Runnable onFlush, Runnable onStop) { + super("android.protolog"); + this.mOnStart = onStart; + this.mOnFlush = onFlush; + this.mOnStop = onStop; + } + + @Override + public Instance createInstance(ProtoInputStream configStream, int instanceIndex) { + ProtoLogConfig config = null; + + try { + while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + try { + if (configStream.getFieldNumber() == (int) PROTOLOG_CONFIG) { + if (config != null) { + throw new RuntimeException("ProtoLog config already set in loop"); + } + config = readProtoLogConfig(configStream); + } + } catch (WireTypeMismatchException e) { + throw new RuntimeException("Failed to parse ProtoLog DataSource config", e); + } + } + } catch (IOException e) { + throw new RuntimeException("Failed to read ProtoLog DataSource config", e); + } + + if (config == null) { + // No config found + config = ProtoLogConfig.DEFAULT; + } + + return new Instance( + this, instanceIndex, config, mOnStart, mOnFlush, mOnStop); + } + + @Override + public TlsState createTlsState(CreateTlsStateArgs<Instance> args) { + try (Instance dsInstance = args.getDataSourceInstanceLocked()) { + if (dsInstance == null) { + // Datasource instance has been removed + return new TlsState(ProtoLogConfig.DEFAULT); + } + return new TlsState(dsInstance.mConfig); + } + } + + @Override + public IncrementalState createIncrementalState(CreateIncrementalStateArgs<Instance> args) { + return new IncrementalState(); + } + + public static class TlsState { + private final ProtoLogConfig mConfig; + + private TlsState(ProtoLogConfig config) { + this.mConfig = config; + } + + /** + * Get the log from level for a group. + * @param groupTag The tag of the group to get the log from level. + * @return The lowest LogLevel (inclusive) to log message from. + */ + public LogLevel getLogFromLevel(String groupTag) { + return getConfigFor(groupTag).logFrom; + } + + /** + * Get if the stacktrace for the log message should be collected for this group. + * @param groupTag The tag of the group to get whether or not a stacktrace was requested. + * @return True iff a stacktrace was requested to be collected from this group in the + * tracing config. + */ + public boolean getShouldCollectStacktrace(String groupTag) { + return getConfigFor(groupTag).collectStackTrace; + } + + private GroupConfig getConfigFor(String groupTag) { + return mConfig.getConfigFor(groupTag); + } + } + + public static class IncrementalState { + public final Map<String, Integer> argumentInterningMap = new HashMap<>(); + public final Map<String, Integer> stacktraceInterningMap = new HashMap<>(); + public boolean clearReported = false; + } + + private static class ProtoLogConfig { + private final LogLevel mDefaultLogFromLevel; + private final Map<String, GroupConfig> mGroupConfigs; + + private static final ProtoLogConfig DEFAULT = + new ProtoLogConfig(LogLevel.WTF, new HashMap<>()); + + private ProtoLogConfig( + LogLevel defaultLogFromLevel, Map<String, GroupConfig> groupConfigs) { + this.mDefaultLogFromLevel = defaultLogFromLevel; + this.mGroupConfigs = groupConfigs; + } + + private GroupConfig getConfigFor(String groupTag) { + return mGroupConfigs.getOrDefault(groupTag, getDefaultGroupConfig()); + } + + private GroupConfig getDefaultGroupConfig() { + return new GroupConfig(mDefaultLogFromLevel, false); + } + } + + public static class GroupConfig { + public final LogLevel logFrom; + public final boolean collectStackTrace; + + public GroupConfig(LogLevel logFromLevel, boolean collectStackTrace) { + this.logFrom = logFromLevel; + this.collectStackTrace = collectStackTrace; + } + } + + private ProtoLogConfig readProtoLogConfig(ProtoInputStream configStream) + throws IOException { + final long config_token = configStream.start(PROTOLOG_CONFIG); + + LogLevel defaultLogFromLevel = LogLevel.WTF; + final Map<String, GroupConfig> groupConfigs = new HashMap<>(); + + while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + if (configStream.getFieldNumber() == (int) TRACING_MODE) { + int tracingMode = configStream.readInt(TRACING_MODE); + switch (tracingMode) { + case PerfettoTrace.ProtoLogConfig.DEFAULT: + break; + case PerfettoTrace.ProtoLogConfig.ENABLE_ALL: + defaultLogFromLevel = LogLevel.DEBUG; + break; + default: + throw new RuntimeException("Unhandled ProtoLog tracing mode type"); + } + } + if (configStream.getFieldNumber() == (int) GROUP_OVERRIDES) { + final long group_overrides_token = configStream.start(GROUP_OVERRIDES); + + String tag = null; + LogLevel logFromLevel = defaultLogFromLevel; + boolean collectStackTrace = false; + while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + if (configStream.getFieldNumber() == (int) GROUP_NAME) { + tag = configStream.readString(GROUP_NAME); + } + if (configStream.getFieldNumber() == (int) LOG_FROM) { + final int logFromInt = configStream.readInt(LOG_FROM); + switch (logFromInt) { + case (PerfettoTrace.PROTOLOG_LEVEL_DEBUG): { + logFromLevel = LogLevel.DEBUG; + break; + } + case (PerfettoTrace.PROTOLOG_LEVEL_VERBOSE): { + logFromLevel = LogLevel.VERBOSE; + break; + } + case (PerfettoTrace.PROTOLOG_LEVEL_INFO): { + logFromLevel = LogLevel.INFO; + break; + } + case (PerfettoTrace.PROTOLOG_LEVEL_WARN): { + logFromLevel = LogLevel.WARN; + break; + } + case (PerfettoTrace.PROTOLOG_LEVEL_ERROR): { + logFromLevel = LogLevel.ERROR; + break; + } + case (PerfettoTrace.PROTOLOG_LEVEL_WTF): { + logFromLevel = LogLevel.WTF; + break; + } + default: { + throw new RuntimeException("Unhandled log level"); + } + } + } + if (configStream.getFieldNumber() == (int) COLLECT_STACKTRACE) { + collectStackTrace = configStream.readBoolean(COLLECT_STACKTRACE); + } + } + + if (tag == null) { + throw new RuntimeException("Failed to decode proto config. " + + "Got a group override without a group tag."); + } + + groupConfigs.put(tag, new GroupConfig(logFromLevel, collectStackTrace)); + + configStream.end(group_overrides_token); + } + } + + configStream.end(config_token); + + return new ProtoLogConfig(defaultLogFromLevel, groupConfigs); + } + + public static class Instance extends DataSourceInstance { + + private final Runnable mOnStart; + private final Runnable mOnFlush; + private final Runnable mOnStop; + private final ProtoLogConfig mConfig; + + public Instance( + DataSource<Instance, TlsState, IncrementalState> dataSource, + int instanceIdx, + ProtoLogConfig config, + Runnable onStart, + Runnable onFlush, + Runnable onStop + ) { + super(dataSource, instanceIdx); + this.mOnStart = onStart; + this.mOnFlush = onFlush; + this.mOnStop = onStop; + this.mConfig = config; + } + + @Override + public void onStart(StartCallbackArguments args) { + this.mOnStart.run(); + } + + @Override + public void onFlush(FlushCallbackArguments args) { + this.mOnFlush.run(); + } + + @Override + public void onStop(StopCallbackArguments args) { + this.mOnStop.run(); + } + } +} diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java index 527cfddf6d8e..78bed9478d84 100644 --- a/core/java/com/android/internal/protolog/ProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java @@ -16,30 +16,35 @@ package com.android.internal.protolog; +import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_OUTPUT_FILE_PATH; +import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_VIEWER_CONFIG_PATH; +import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.VIEWER_CONFIG_PATH; + import android.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.IProtoLog; import com.android.internal.protolog.common.IProtoLogGroup; - -import java.io.File; +import com.android.internal.protolog.common.LogLevel; +import com.android.internal.protolog.common.ProtoLogToolInjected; /** * A service for the ProtoLog logging system. */ -public class ProtoLogImpl extends BaseProtoLogImpl { - private static final int BUFFER_CAPACITY = 1024 * 1024; - private static final String LOG_FILENAME = "/data/misc/wmtrace/wm_log.winscope"; - private static final String VIEWER_CONFIG_FILENAME = "/system/etc/protolog.conf.json.gz"; - private static final int PER_CHUNK_SIZE = 1024; +public class ProtoLogImpl { + private static IProtoLog sServiceInstance = null; - private static ProtoLogImpl sServiceInstance = null; + @ProtoLogToolInjected(VIEWER_CONFIG_PATH) + private static String sViewerConfigPath; - static { - addLogGroupEnum(ProtoLogGroup.values()); - } + @ProtoLogToolInjected(LEGACY_VIEWER_CONFIG_PATH) + private static String sLegacyViewerConfigPath; + + @ProtoLogToolInjected(LEGACY_OUTPUT_FILE_PATH) + private static String sLegacyOutputFilePath; /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void d(IProtoLogGroup group, int messageHash, int paramsMask, + public static void d(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance() @@ -47,7 +52,7 @@ public class ProtoLogImpl extends BaseProtoLogImpl { } /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void v(IProtoLogGroup group, int messageHash, int paramsMask, + public static void v(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance().log(LogLevel.VERBOSE, group, messageHash, paramsMask, messageString, @@ -55,21 +60,21 @@ public class ProtoLogImpl extends BaseProtoLogImpl { } /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void i(IProtoLogGroup group, int messageHash, int paramsMask, + public static void i(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance().log(LogLevel.INFO, group, messageHash, paramsMask, messageString, args); } /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void w(IProtoLogGroup group, int messageHash, int paramsMask, + public static void w(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance().log(LogLevel.WARN, group, messageHash, paramsMask, messageString, args); } /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void e(IProtoLogGroup group, int messageHash, int paramsMask, + public static void e(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance() @@ -77,40 +82,36 @@ public class ProtoLogImpl extends BaseProtoLogImpl { } /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void wtf(IProtoLogGroup group, int messageHash, int paramsMask, + public static void wtf(IProtoLogGroup group, long messageHash, int paramsMask, @Nullable String messageString, Object... args) { getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args); } - /** Returns true iff logging is enabled for the given {@code IProtoLogGroup}. */ public static boolean isEnabled(IProtoLogGroup group) { - return group.isLogToLogcat() - || (group.isLogToProto() && getSingleInstance().isProtoEnabled()); + // TODO: Implement for performance reasons, with optional level parameter? + return true; } /** * Returns the single instance of the ProtoLogImpl singleton class. */ - public static synchronized ProtoLogImpl getSingleInstance() { + public static synchronized IProtoLog getSingleInstance() { if (sServiceInstance == null) { - sServiceInstance = new ProtoLogImpl( - new File(LOG_FILENAME) - , BUFFER_CAPACITY - , new ProtoLogViewerConfigReader() - , PER_CHUNK_SIZE); + if (android.tracing.Flags.perfettoProtolog()) { + sServiceInstance = + new PerfettoProtoLogImpl(sViewerConfigPath); + } else { + sServiceInstance = + new LegacyProtoLogImpl(sLegacyOutputFilePath, sLegacyViewerConfigPath); + } } return sServiceInstance; } @VisibleForTesting - public static synchronized void setSingleInstance(@Nullable ProtoLogImpl instance) { + public static synchronized void setSingleInstance(@Nullable IProtoLog instance) { sServiceInstance = instance; } - - public ProtoLogImpl(File logFile, int bufferCapacity, - ProtoLogViewerConfigReader viewConfigReader, int perChunkSize) { - super(logFile, VIEWER_CONFIG_FILENAME, bufferCapacity, viewConfigReader, perChunkSize); - } } diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java index aa30a7723ad9..3c206acf7c0f 100644 --- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java +++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java @@ -1,125 +1,93 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.android.internal.protolog; -import android.annotation.Nullable; -import android.util.Slog; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE; +import static perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE_ID; + +import android.util.proto.ProtoInputStream; -import org.json.JSONException; -import org.json.JSONObject; +import com.android.internal.protolog.common.ILogger; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.util.Iterator; import java.util.Map; -import java.util.TreeMap; -import java.util.zip.GZIPInputStream; -/** - * Handles loading and parsing of ProtoLog viewer configuration. - */ public class ProtoLogViewerConfigReader { - private static final String TAG = "ProtoLogViewerConfigReader"; - private Map<Integer, String> mLogMessageMap = null; + private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider; + private Map<Long, String> mLogMessageMap = null; - /** Returns message format string for its hash or null if unavailable. */ - public synchronized String getViewerString(int messageHash) { - if (mLogMessageMap != null) { - return mLogMessageMap.get(messageHash); - } else { - return null; - } + public ProtoLogViewerConfigReader( + ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) { + this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider; } /** - * Reads the specified viewer configuration file. Does nothing if the config is already loaded. + * Returns message format string for its hash or null if unavailable + * or the viewer config is not loaded into memory. */ - public synchronized void loadViewerConfig(PrintWriter pw, String viewerConfigFilename) { - try { - loadViewerConfig(new GZIPInputStream(new FileInputStream(viewerConfigFilename))); - logAndPrintln(pw, "Loaded " + mLogMessageMap.size() - + " log definitions from " + viewerConfigFilename); - } catch (FileNotFoundException e) { - logAndPrintln(pw, "Unable to load log definitions: File " - + viewerConfigFilename + " not found." + e); - } catch (IOException e) { - logAndPrintln(pw, "Unable to load log definitions: IOException while reading " - + viewerConfigFilename + ". " + e); - } catch (JSONException e) { - logAndPrintln(pw, "Unable to load log definitions: JSON parsing exception while reading " - + viewerConfigFilename + ". " + e); + public synchronized String getViewerString(long messageHash) { + if (mLogMessageMap != null) { + return mLogMessageMap.get(messageHash); + } else { + return null; } } /** - * Reads the specified viewer configuration input stream. - * Does nothing if the config is already loaded. + * Loads the viewer config into memory. No-op if already loaded in memory. */ - public synchronized void loadViewerConfig(InputStream viewerConfigInputStream) - throws IOException, JSONException { + public synchronized void loadViewerConfig(ILogger logger) { if (mLogMessageMap != null) { return; } - InputStreamReader config = new InputStreamReader(viewerConfigInputStream); - BufferedReader reader = new BufferedReader(config); - StringBuilder builder = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - builder.append(line).append('\n'); - } - reader.close(); - JSONObject json = new JSONObject(builder.toString()); - JSONObject messages = json.getJSONObject("messages"); - - mLogMessageMap = new TreeMap<>(); - Iterator it = messages.keys(); - while (it.hasNext()) { - String key = (String) it.next(); - try { - int hash = Integer.parseInt(key); - JSONObject val = messages.getJSONObject(key); - String msg = val.getString("message"); - mLogMessageMap.put(hash, msg); - } catch (NumberFormatException expected) { - // Not a messageHash - skip it - } + + try { + doLoadViewerConfig(); + logger.log("Loaded " + mLogMessageMap.size() + " log definitions"); + } catch (IOException e) { + logger.log("Unable to load log definitions: " + + "IOException while processing viewer config" + e); } } /** - * Returns the number of loaded log definitions kept in memory. + * Unload the viewer config from memory. */ - public synchronized int knownViewerStringsNumber() { - if (mLogMessageMap != null) { - return mLogMessageMap.size(); - } - return 0; + public synchronized void unloadViewerConfig() { + mLogMessageMap = null; } - static void logAndPrintln(@Nullable PrintWriter pw, String msg) { - Slog.i(TAG, msg); - if (pw != null) { - pw.println(msg); - pw.flush(); + private void doLoadViewerConfig() throws IOException { + final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream(); + + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + if (pis.getFieldNumber() == (int) MESSAGES) { + final long inMessageToken = pis.start(MESSAGES); + + long messageId = 0; + String message = null; + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (pis.getFieldNumber()) { + case (int) MESSAGE_ID: + messageId = pis.readLong(MESSAGE_ID); + break; + case (int) MESSAGE: + message = pis.readString(MESSAGE); + break; + } + } + + if (messageId == 0) { + throw new IOException("Failed to get message id"); + } + + if (message == null) { + throw new IOException("Failed to get message string"); + } + + mLogMessageMap.put(messageId, message); + + pis.end(inMessageToken); + } } } } diff --git a/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java b/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java new file mode 100644 index 000000000000..334f5488425a --- /dev/null +++ b/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import android.util.proto.ProtoInputStream; + +public interface ViewerConfigInputStreamProvider { + /** + * @return a ProtoInputStream. + */ + ProtoInputStream getInputStream(); +} diff --git a/core/java/com/android/internal/protolog/common/ILogger.java b/core/java/com/android/internal/protolog/common/ILogger.java new file mode 100644 index 000000000000..cc6fa5e73969 --- /dev/null +++ b/core/java/com/android/internal/protolog/common/ILogger.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog.common; + +public interface ILogger { + /** + * Log a message. + * @param message The log message. + */ + void log(String message); +} diff --git a/core/java/com/android/internal/protolog/common/IProtoLog.java b/core/java/com/android/internal/protolog/common/IProtoLog.java new file mode 100644 index 000000000000..c06d14b2075e --- /dev/null +++ b/core/java/com/android/internal/protolog/common/IProtoLog.java @@ -0,0 +1,55 @@ +/* + * 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.protolog.common; + +/** + * Interface for ProtoLog implementations. + */ +public interface IProtoLog { + + /** + * Log a ProtoLog message + * @param logLevel Log level of the proto message. + * @param group The group this message belongs to. + * @param messageHash The hash of the message. + * @param paramsMask The parameters mask of the message. + * @param messageString The message string. + * @param args The arguments of the message. + */ + void log(LogLevel logLevel, IProtoLogGroup group, long messageHash, int paramsMask, + String messageString, Object[] args); + + /** + * Check if ProtoLog is tracing. + * @return true iff a ProtoLog tracing session is active. + */ + boolean isProtoEnabled(); + + /** + * Start logging log groups to logcat + * @param groups Groups to start text logging for + * @return status code + */ + int startLoggingToLogcat(String[] groups, ILogger logger); + + /** + * Stop logging log groups to logcat + * @param groups Groups to start text logging for + * @return status code + */ + int stopLoggingToLogcat(String[] groups, ILogger logger); +} diff --git a/core/java/com/android/internal/protolog/common/IProtoLogGroup.java b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java index e3db46832a6f..4e9686f99f4b 100644 --- a/core/java/com/android/internal/protolog/common/IProtoLogGroup.java +++ b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java @@ -26,6 +26,7 @@ public interface IProtoLogGroup { boolean isEnabled(); /** + * @deprecated TODO(b/324128613) remove once we migrate fully to Perfetto * is binary logging enabled for the group. */ boolean isLogToProto(); diff --git a/core/java/com/android/internal/protolog/common/LogLevel.java b/core/java/com/android/internal/protolog/common/LogLevel.java new file mode 100644 index 000000000000..16c34e1f333e --- /dev/null +++ b/core/java/com/android/internal/protolog/common/LogLevel.java @@ -0,0 +1,26 @@ +/* + * 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.protolog.common; + +public enum LogLevel { + DEBUG("d"), VERBOSE("v"), INFO("i"), WARN("w"), ERROR("e"), WTF("wtf"); + + public final String shortCode; + LogLevel(String shortCode) { + this.shortCode = shortCode; + } +} diff --git a/core/java/com/android/internal/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java index 8870096f3db7..18e3f66c4795 100644 --- a/core/java/com/android/internal/protolog/common/ProtoLog.java +++ b/core/java/com/android/internal/protolog/common/ProtoLog.java @@ -16,8 +16,6 @@ package com.android.internal.protolog.common; -import android.util.Log; - /** * ProtoLog API - exposes static logging methods. Usage of this API is similar * to {@code android.utils.Log} class. Instead of plain text log messages each call consists of @@ -55,9 +53,6 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.d(group.getTag(), String.format(messageString, args)); - } } /** @@ -73,9 +68,6 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.v(group.getTag(), String.format(messageString, args)); - } } /** @@ -91,9 +83,6 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.i(group.getTag(), String.format(messageString, args)); - } } /** @@ -109,9 +98,6 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.w(group.getTag(), String.format(messageString, args)); - } } /** @@ -127,9 +113,6 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.e(group.getTag(), String.format(messageString, args)); - } } /** @@ -145,8 +128,30 @@ public class ProtoLog { throw new UnsupportedOperationException( "ProtoLog calls MUST be processed with ProtoLogTool"); } - if (group.isLogToLogcat()) { - Log.wtf(group.getTag(), String.format(messageString, args)); + } + + /** + * Check if ProtoLog isEnabled for a target group. + * @param group Group to check enable status of. + * @return true iff this is being logged. + */ + public static boolean isEnabled(IProtoLogGroup group) { + if (REQUIRE_PROTOLOGTOOL) { + throw new UnsupportedOperationException( + "ProtoLog calls MUST be processed with ProtoLogTool"); + } + return false; + } + + /** + * Get the single ProtoLog instance. + * @return A singleton instance of ProtoLog. + */ + public static IProtoLog getSingleInstance() { + if (REQUIRE_PROTOLOGTOOL) { + throw new UnsupportedOperationException( + "ProtoLog calls MUST be processed with ProtoLogTool"); } + return null; } } diff --git a/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java b/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java new file mode 100644 index 000000000000..ffd0d7623852 --- /dev/null +++ b/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.android.internal.protolog.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD, ElementType.PARAMETER}) +public @interface ProtoLogToolInjected { + enum Value { VIEWER_CONFIG_PATH, LEGACY_OUTPUT_FILE_PATH, LEGACY_VIEWER_CONFIG_PATH } + + Value value(); +} diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp index 01e9f437a79f..06d5eb305ff0 100644 --- a/core/jni/LayoutlibLoader.cpp +++ b/core/jni/LayoutlibLoader.cpp @@ -362,6 +362,22 @@ static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) { using namespace android; +// Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception. +void abort_handler(const char* abort_message) { + ALOGE("Abort to abort the process..."); + + JNIEnv* env = NULL; + if (javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("vm->GetEnv() failed"); + return; + } + if (env->ExceptionOccurred() != NULL) { + ALOGE("Pending exception:"); + env->ExceptionDescribe(); + } + ALOGE("Aborting because: %s", abort_message); +} + JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { javaVM = vm; JNIEnv* env = nullptr; @@ -369,6 +385,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } + __android_log_set_aborter(abort_handler); + init_android_graphics(); // Configuration is stored as java System properties. diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index f1b93db3e731..07cbaadf0580 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "InputEventReceiver" +#define ATRACE_TAG ATRACE_TAG_INPUT //#define LOG_NDEBUG 0 @@ -46,6 +47,16 @@ static const char* toString(bool value) { return value ? "true" : "false"; } +/** + * Trace a bool variable, writing "1" if the value is "true" and "0" otherwise. + * TODO(b/311142655): delete this tracing. It's only useful for debugging very specific issues. + * @param var the name of the variable + * @param value the value of the variable + */ +static void traceBoolVariable(const char* var, bool value) { + ATRACE_INT(var, value ? 1 : 0); +} + static struct { jclass clazz; @@ -130,6 +141,7 @@ NativeInputEventReceiver::NativeInputEventReceiver( mMessageQueue(messageQueue), mBatchedInputEventPending(false), mFdEvents(0) { + traceBoolVariable("mBatchedInputEventPending", mBatchedInputEventPending); if (kDebugDispatchCycle) { ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName().c_str()); } @@ -311,6 +323,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, if (consumeBatches) { mBatchedInputEventPending = false; + traceBoolVariable("mBatchedInputEventPending", mBatchedInputEventPending); } if (outConsumedBatch) { *outConsumedBatch = false; @@ -344,6 +357,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, } mBatchedInputEventPending = true; + traceBoolVariable("mBatchedInputEventPending", mBatchedInputEventPending); if (kDebugDispatchCycle) { ALOGD("channel '%s' ~ Dispatching batched input event pending notification.", getInputChannelName().c_str()); @@ -355,6 +369,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, if (env->ExceptionCheck()) { ALOGE("Exception dispatching batched input events."); mBatchedInputEventPending = false; // try again later + traceBoolVariable("mBatchedInputEventPending", mBatchedInputEventPending); } } return OK; diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index 285dee364bb0..b39d5cf3842b 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -85,9 +85,24 @@ static void android_view_MotionEvent_setNativePtr(JNIEnv* env, ScopedLocalRef<jo ScopedLocalRef<jobject> android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent& event) { - std::unique_ptr<MotionEvent> destEvent = std::make_unique<MotionEvent>(); + ScopedLocalRef<jobject> eventObj(env, + env->CallStaticObjectMethod(gMotionEventClassInfo.clazz, + gMotionEventClassInfo.obtain)); + if (env->ExceptionCheck() || !eventObj.get()) { + ALOGE("An exception occurred while obtaining a motion event."); + LOGE_EX(env); + env->ExceptionClear(); + return ScopedLocalRef<jobject>(env); + } + + MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj.get()); + if (!destEvent) { + destEvent = new MotionEvent(); + android_view_MotionEvent_setNativePtr(env, eventObj, destEvent); + } + destEvent->copyFrom(&event, true); - return android_view_MotionEvent_obtainFromNative(env, std::move(destEvent)); + return eventObj; } ScopedLocalRef<jobject> android_view_MotionEvent_obtainFromNative( diff --git a/core/proto/android/internal/protolog.proto b/core/proto/android/internal/protolog.proto index fee7a878f860..9e205e284c53 100644 --- a/core/proto/android/internal/protolog.proto +++ b/core/proto/android/internal/protolog.proto @@ -27,7 +27,7 @@ message ProtoLogMessage { option (.android.msg_privacy).dest = DEST_LOCAL; /* log statement identifier, created from message string and log level. */ - optional sfixed32 message_hash = 1; + optional sfixed32 message_hash_legacy = 1 [deprecated = true]; /* log time, relative to the elapsed system time clock. */ optional fixed64 elapsed_realtime_nanos = 2; /* string parameters passed to the log call. */ @@ -38,6 +38,9 @@ message ProtoLogMessage { repeated double double_params = 5 [packed=true]; /* boolean parameters passed to the log call. */ repeated bool boolean_params = 6 [packed=true]; + + /* log statement identifier, created from message string and log level. */ + optional sfixed64 message_hash = 7; } /* represents a log file containing ProtoLog log entries. diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 4fc9b40465ee..763d9ce1a053 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -101,6 +101,7 @@ message SecureSettingsProto { optional SettingProto accessibility_magnification_two_finger_triple_tap_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto qs_targets = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto accessibility_pinch_to_zoom_anywhere_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_single_finger_panning_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Accessibility accessibility = 2; diff --git a/core/res/Android.bp b/core/res/Android.bp index 277824cbb4c8..e2e419fcf5b7 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -159,7 +159,7 @@ android_app { "android.content.pm.flags-aconfig", "android.provider.flags-aconfig", "camera_platform_flags", - "com.android.net.flags-aconfig", + "android.net.platform.flags-aconfig", "com.android.window.flags.window-aconfig", ], } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8720f947bb8d..900f9cb67718 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2331,12 +2331,12 @@ <!-- Allows system apps to call methods to register itself as a mDNS offload engine. <p>Not for use by third-party or privileged applications. @SystemApi - @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") + @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine") @hide This should only be used by system apps. --> <permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE" android:protectionLevel="signature" - android:featureFlag="com.android.net.flags.register_nsd_offload_engine" /> + android:featureFlag="android.net.platform.flags.register_nsd_offload_engine" /> <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> diff --git a/core/res/res/drawable/pointer_wait_vector.xml b/core/res/res/drawable/pointer_wait_vector.xml new file mode 100644 index 000000000000..4de0690bc26b --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> + <item android:drawable="@drawable/pointer_wait_vector_0" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_1" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_2" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_3" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_4" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_5" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_6" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_7" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_8" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_9" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_10" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_11" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_12" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_13" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_14" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_15" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_16" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_17" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_18" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_19" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_20" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_21" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_22" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_23" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_24" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_25" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_26" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_27" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_28" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_29" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_30" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_31" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_32" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_33" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_34" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_35" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_36" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_37" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_38" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_39" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_40" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_41" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_42" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_43" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_44" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_45" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_46" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_47" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_48" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_49" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_50" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_51" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_52" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_53" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_54" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_55" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_56" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_57" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_58" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_59" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_60" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_61" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_62" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_63" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_64" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_65" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_66" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_67" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_68" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_69" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_70" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_71" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_72" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_73" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_74" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_75" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_76" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_77" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_78" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_79" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_80" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_81" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_82" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_83" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_84" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_85" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_86" android:duration="16"/> + <item android:drawable="@drawable/pointer_wait_vector_87" android:duration="16"/> +</animation-list> diff --git a/core/res/res/drawable/pointer_wait_vector_0.xml b/core/res/res/drawable/pointer_wait_vector_0.xml new file mode 100644 index 000000000000..4bfbc9f08b1e --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_0.xml @@ -0,0 +1,27 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.116,18.654a1.78,1.78 0,1 0,0.061 3.561,1.78 1.78,0 0,0 -0.061,-3.561m-7.194,-1.73a1.781,1.781 0,1 0,2.594 2.441,1.781 1.781,0 0,0 -2.594,-2.441" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.294,7.294a1.78,1.78 0,1 0,-2.517 -2.519,1.78 1.78,0 0,0 2.517,2.519" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.225,7.294a1.78,1.78 0,1 0,-2.517 -2.519,1.78 1.78,0 0,0 2.517,2.519" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.747,16.665a1.78,1.78 0,1 0,2.539 2.497,1.78 1.78,0 0,0 -2.539,-2.497" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_1.xml b/core/res/res/drawable/pointer_wait_vector_1.xml new file mode 100644 index 000000000000..bab91e1d9402 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_1.xml @@ -0,0 +1,21 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.174,18.653a1.782,1.782 0,1 0,0.094 3.562,1.782 1.782,0 0,0 -0.094,-3.562m-7.187,-1.637a1.782,1.782 0,1 0,2.627 2.407,1.782 1.782,0 0,0 -2.627,-2.407" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.294,7.294a1.78,1.78 0,1 0,-2.517 -2.519,1.78 1.78,0 0,0 2.517,2.519" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.225,7.294a1.78,1.78 0,1 0,-2.517 -2.519,1.78 1.78,0 0,0 2.517,2.519m1.203,2.888a1.78,1.78 0,1 0,0.016 3.562,1.78 1.78,0 1,0 -0.016,-3.562m-3.641,6.441a1.782,1.782 0,1 0,2.564 2.475,1.782 1.782,0 0,0 -2.564,-2.475" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_10.xml b/core/res/res/drawable/pointer_wait_vector_10.xml new file mode 100644 index 000000000000..ae3e36093aaa --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_10.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.028,20.374m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.952,18.76m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12.066m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.957,6.113m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.779,3.566m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.7,5.78m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.42,11.485m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.462,17.423m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_11.xml b/core/res/res/drawable/pointer_wait_vector_11.xml new file mode 100644 index 000000000000..d2c014d1ee3d --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_11.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.101,20.364m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.101,18.868m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12.074m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.931,6.139m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.706,3.569m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.646,5.731m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.41,11.338m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.509,17.366m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_12.xml b/core/res/res/drawable/pointer_wait_vector_12.xml new file mode 100644 index 000000000000..e9a36c033ca6 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_12.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.247,20.344m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.222,18.953m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.564,12.147m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.88,6.193m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.632,3.571m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.591,5.681m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.404,11.265m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.602,17.252m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_13.xml b/core/res/res/drawable/pointer_wait_vector_13.xml new file mode 100644 index 000000000000..5800f39fa7ef --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_13.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.392,20.321m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.344,19.035m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.565,12.184m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.83,6.246m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.559,3.575m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.535,5.633m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.39,11.118m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.693,17.136m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_14.xml b/core/res/res/drawable/pointer_wait_vector_14.xml new file mode 100644 index 000000000000..3566aaf358e7 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_14.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.537,20.295m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.467,19.115m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.567,12.258m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.755,6.327m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.485,3.579m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.423,5.537m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.386,11.082m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.759,17.048m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_15.xml b/core/res/res/drawable/pointer_wait_vector_15.xml new file mode 100644 index 000000000000..c995faf24f33 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_15.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.682,20.267m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.718,19.269m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.568,12.295m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.73,6.355m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.412,3.584m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.367,5.49m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.369,10.935m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.847,16.929m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_16.xml b/core/res/res/drawable/pointer_wait_vector_16.xml new file mode 100644 index 000000000000..179328205776 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_16.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.826,20.237m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.846,19.343m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.57,12.331m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.706,6.382m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.338,3.589m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.31,5.444m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.354,10.826m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.91,16.839m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_17.xml b/core/res/res/drawable/pointer_wait_vector_17.xml new file mode 100644 index 000000000000..59772f566644 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_17.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.969,20.204m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.974,19.414m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.571,12.368m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.681,6.41m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.191,3.602m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.194,5.352m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.333,10.68m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.994,16.718m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_18.xml b/core/res/res/drawable/pointer_wait_vector_18.xml new file mode 100644 index 000000000000..1bbb242d5663 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_18.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.184,20.149m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.236,19.55m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.575,12.442m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.585,6.521m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.118,3.61m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.136,5.307m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.315,10.571m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.075,16.595m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_19.xml b/core/res/res/drawable/pointer_wait_vector_19.xml new file mode 100644 index 000000000000..b8e0dd54708f --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_19.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.325,20.11m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.434,19.646m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.581,12.552m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.537,6.577m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.972,3.626m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.959,5.175m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.282,10.39m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.193,16.408m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_2.xml b/core/res/res/drawable/pointer_wait_vector_2.xml new file mode 100644 index 000000000000..5c4606f36569 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_2.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.331,20.43m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.355,18.269m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.035m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.435,11.89m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.094,17.834m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_20.xml b/core/res/res/drawable/pointer_wait_vector_20.xml new file mode 100644 index 000000000000..b3ac2dab2537 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_20.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.607,20.024m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.703,19.766m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.592,12.699m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.49,6.634m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.899,3.636m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.899,5.132m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.252,10.246m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.269,16.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_21.xml b/core/res/res/drawable/pointer_wait_vector_21.xml new file mode 100644 index 000000000000..884476e929a6 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_21.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.816,19.953m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.908,19.849m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.589,12.662m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.443,6.691m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.753,3.656m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.718,5.006m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.22,10.102m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.414,16.025m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_22.xml b/core/res/res/drawable/pointer_wait_vector_22.xml new file mode 100644 index 000000000000..20660ca89f3a --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_22.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M15.092,19.849m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.184,19.952m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.617,12.955m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.352,6.806m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.608,3.679m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.595,4.925m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.149,9.816m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.483,15.896m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_23.xml b/core/res/res/drawable/pointer_wait_vector_23.xml new file mode 100644 index 000000000000..6b594ee78eae --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_23.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M15.296,19.766m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.533,20.068m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.609,12.882m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.262,6.923m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.463,3.705m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.471,4.845m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.11,9.675m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.614,15.632m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_24.xml b/core/res/res/drawable/pointer_wait_vector_24.xml new file mode 100644 index 000000000000..a35203e3857b --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_24.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M15.632,19.615m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.816,20.149m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.626,13.028m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.175,7.041m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.318,3.733m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.346,4.769m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.046,9.463m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.677,15.498m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_25.xml b/core/res/res/drawable/pointer_wait_vector_25.xml new file mode 100644 index 000000000000..df8549af4006 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_25.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M15.896,19.483m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.174,20.236m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.645,13.174m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.089,7.161m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.174,3.763m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.219,4.694m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.977,9.253m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.794,15.228m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_26.xml b/core/res/res/drawable/pointer_wait_vector_26.xml new file mode 100644 index 000000000000..0abb7d41a59a --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_26.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M16.154,19.343m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.535,20.308m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.667,13.32m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.006,7.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.959,3.814m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.961,4.551m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.902,9.045m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.902,14.955m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_27.xml b/core/res/res/drawable/pointer_wait_vector_27.xml new file mode 100644 index 000000000000..bde242548af5 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_27.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M16.471,19.155m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.972,20.374m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.691,13.465m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.885,7.467m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.817,3.851m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.831,4.483m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.85,8.908m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.023,14.607m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_28.xml b/core/res/res/drawable/pointer_wait_vector_28.xml new file mode 100644 index 000000000000..19cb410b1405 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_28.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M16.778,18.953m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.411,20.416m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.718,13.61m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.807,7.592m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.604,3.911m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.566,4.354m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.677,8.502m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.109,14.325m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_29.xml b/core/res/res/drawable/pointer_wait_vector_29.xml new file mode 100644 index 000000000000..5d6776fcdb21 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_29.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M17.136,18.693m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.926,20.436m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.748,13.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.731,7.718m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.463,3.954m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.365,4.263m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.55,8.236m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.203,13.969m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_3.xml b/core/res/res/drawable/pointer_wait_vector_3.xml new file mode 100644 index 000000000000..8a19401bd401 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_3.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.368,20.429m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.437,18.343m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.94,6.009m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.435,11.853m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.119,17.807m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_30.xml b/core/res/res/drawable/pointer_wait_vector_30.xml new file mode 100644 index 000000000000..56dcdc228401 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_30.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M17.479,18.415m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.441,20.425m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.796,13.969m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.586,7.974m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.184,4.047m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.092,4.151m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.414,7.975m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.281,13.61m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_31.xml b/core/res/res/drawable/pointer_wait_vector_31.xml new file mode 100644 index 000000000000..5687a9b46b67 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_31.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M17.807,18.12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.028,20.373m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.832,14.112m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.517,8.104m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.908,4.15m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.817,4.047m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.269,7.718m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.344,13.247m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_32.xml b/core/res/res/drawable/pointer_wait_vector_32.xml new file mode 100644 index 000000000000..cb626e41d1d5 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_32.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18.17,17.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.61,20.281m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.87,14.254m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.417,8.302m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.704,4.234m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.537,3.954m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.076,7.405m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.397,12.809m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_33.xml b/core/res/res/drawable/pointer_wait_vector_33.xml new file mode 100644 index 000000000000..052f973f2ab4 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_33.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18.51,17.366m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.183,20.149m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.954,14.537m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.323,8.501m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.435,4.354m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.184,3.851m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.868,7.101m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.428,12.368m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_34.xml b/core/res/res/drawable/pointer_wait_vector_34.xml new file mode 100644 index 000000000000..9e665756f4c2 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_34.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18.911,16.839m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.885,19.928m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.999,14.677m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.206,8.771m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.17,4.483m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.826,3.764m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.603,6.748m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.433,11.779m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_35.xml b/core/res/res/drawable/pointer_wait_vector_35.xml new file mode 100644 index 000000000000..1d063fc9fbb9 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_35.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M19.232,16.345m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.566,19.646m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.098,14.955m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.098,9.045m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.846,4.657m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.465,3.692m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.27,6.355m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.41,11.338m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_36.xml b/core/res/res/drawable/pointer_wait_vector_36.xml new file mode 100644 index 000000000000..db0ad1c847bc --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_36.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M19.583,15.698m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.345,19.232m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.205,15.229m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.999,9.323m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.592,4.807m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.028,3.626m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.035m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.344,10.753m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_37.xml b/core/res/res/drawable/pointer_wait_vector_37.xml new file mode 100644 index 000000000000..ee944a6ccbe6 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_37.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M19.876,15.023m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.077,18.738m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.323,15.499m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.911,9.604m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.221,5.047m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.589,3.584m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.59,5.681m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.236,10.174m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_38.xml b/core/res/res/drawable/pointer_wait_vector_38.xml new file mode 100644 index 000000000000..a347a36e34b0 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_38.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M20.129,14.255m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.861,18.069m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.45,15.764m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.796,10.031m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.864,5.307m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.147,3.565m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.136,5.307m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.046,9.463m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_39.xml b/core/res/res/drawable/pointer_wait_vector_39.xml new file mode 100644 index 000000000000..2c86f0dd7849 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_39.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M20.321,13.392m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.557,17.309m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.586,16.026m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.705,10.462m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.521,5.585m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.559,3.575m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.657,4.965m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.766,8.704m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_4.xml b/core/res/res/drawable/pointer_wait_vector_4.xml new file mode 100644 index 000000000000..a6690c003c4b --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_4.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.441,20.425m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.493,18.391m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.914,5.983m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.433,11.772m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.17,17.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_40.xml b/core/res/res/drawable/pointer_wait_vector_40.xml new file mode 100644 index 000000000000..953fdc1deb23 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_40.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M20.428,12.368m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.232,16.345m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.731,16.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.656,10.753m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.193,5.88m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.972,3.626m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.026,4.586m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.449,8.039m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_41.xml b/core/res/res/drawable/pointer_wait_vector_41.xml new file mode 100644 index 000000000000..a1b17fa2d19d --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_41.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M20.41,11.338m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.766,15.296m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.924,16.595m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.602,11.191m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.83,6.246m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.39,3.719m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.364,4.263m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.994,7.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_42.xml b/core/res/res/drawable/pointer_wait_vector_42.xml new file mode 100644 index 000000000000..4de9b8d14dd8 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_42.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M20.244,10.21m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.14,14.219m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.153,16.929m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.571,11.632m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.49,6.634m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.817,3.851m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.677,4m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.367,6.465m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_43.xml b/core/res/res/drawable/pointer_wait_vector_43.xml new file mode 100644 index 000000000000..38187fe62ac4 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_43.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M19.94,9.149m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.365,13.101m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.397,17.252m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.566,12.221m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.089,7.161m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.115,4.072m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.826,3.763m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.645,5.73m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_44.xml b/core/res/res/drawable/pointer_wait_vector_44.xml new file mode 100644 index 000000000000..890ba7ee6533 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_44.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M19.466,8.072m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12.073m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.73,17.645m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.589,12.662m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.768,7.655m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.368,4.385m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.882,3.61m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.839,5.089m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_45.xml b/core/res/res/drawable/pointer_wait_vector_45.xml new file mode 100644 index 000000000000..309ac082edef --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_45.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18.847,7.071m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.382,11.045m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.139,18.069m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.656,13.247m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.417,8.302m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.592,4.807m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.853,3.565m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.83,4.483m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_46.xml b/core/res/res/drawable/pointer_wait_vector_46.xml new file mode 100644 index 000000000000..5a9bf706064a --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_46.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M18.195,6.273m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.237,10.174m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.465,18.367m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.797,13.969m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.124,8.977m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.864,5.307m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.826,3.646m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.747,4.023m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_47.xml b/core/res/res/drawable/pointer_wait_vector_47.xml new file mode 100644 index 000000000000..0068f27c78d5 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_47.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M17.451,5.561m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.046,9.463m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.922,18.738m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.954,14.537m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.851,9.817m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.087,5.983m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.675,3.89m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.61,3.718m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_48.xml b/core/res/res/drawable/pointer_wait_vector_48.xml new file mode 100644 index 000000000000..6ece990ad516 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_48.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M16.748,5.026m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.822,8.84m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.405,19.076m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.205,15.229m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.667,10.68m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.397,6.748m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.569,4.293m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.588,3.584m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_49.xml b/core/res/res/drawable/pointer_wait_vector_49.xml new file mode 100644 index 000000000000..d44438975224 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_49.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M16.09,4.621m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.583,8.302m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.974,19.414m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.586,16.025m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.571,11.632m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.768,7.655m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.655,4.768m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.558,3.575m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_5.xml b/core/res/res/drawable/pointer_wait_vector_5.xml new file mode 100644 index 000000000000..4952fe57397b --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_5.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.515,20.421m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.577,18.463m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.877,5.947m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.433,11.779m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.22,17.7m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_50.xml b/core/res/res/drawable/pointer_wait_vector_50.xml new file mode 100644 index 000000000000..a85155fc5dd2 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_50.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M15.499,4.323m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.343,7.846m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.636,19.737m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.047,16.778m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.589,12.662m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.234,8.704m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.634,5.49m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.608,3.679m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_51.xml b/core/res/res/drawable/pointer_wait_vector_51.xml new file mode 100644 index 000000000000..95b4aaa2365a --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_51.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.885,4.072m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.155,7.529m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.393,20.024m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.585,17.479m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.748,13.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.851,9.817m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.88,6.193m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.816,3.851m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_52.xml b/core/res/res/drawable/pointer_wait_vector_52.xml new file mode 100644 index 000000000000..34619b5d4361 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_52.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M14.396,3.911m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.953,7.221m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.246,20.252m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.3,18.22m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.072,14.885m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.636,10.899m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.307,6.864m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.114,4.072m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_53.xml b/core/res/res/drawable/pointer_wait_vector_53.xml new file mode 100644 index 000000000000..926b63998470 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_53.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.969,3.797m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.782,6.982m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.118,20.39m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.221,18.953m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.551,15.961m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.564,11.927m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.807,7.592m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.568,4.293m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_54.xml b/core/res/res/drawable/pointer_wait_vector_54.xml new file mode 100644 index 000000000000..c51851fce837 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_54.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.61,3.718m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.603,6.748m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.147,20.435m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.17,19.517m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.132,16.899m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.618,12.955m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.45,8.236m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.104,4.517m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_55.xml b/core/res/res/drawable/pointer_wait_vector_55.xml new file mode 100644 index 000000000000..cdf435fa0637 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_55.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.247,3.656m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.463,6.577m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.247,20.344m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.253,19.977m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.83,17.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.748,13.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.178,8.84m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.686,4.749m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_56.xml b/core/res/res/drawable/pointer_wait_vector_56.xml new file mode 100644 index 000000000000..1528711e2542 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_56.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M13.028,3.626m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.319,6.41m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.325,20.11m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.39,20.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.521,18.415m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.954,14.537m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.976,9.393m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.405,4.924m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_57.xml b/core/res/res/drawable/pointer_wait_vector_57.xml new file mode 100644 index 000000000000..1715db1e2bef --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_57.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.772,3.599m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.22,6.3m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.431,19.707m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.411,20.416m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.282,18.994m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.178,15.16m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.851,9.817m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.041,5.175m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_58.xml b/core/res/res/drawable/pointer_wait_vector_58.xml new file mode 100644 index 000000000000..83aec4b24851 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_58.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.589,3.584m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.12,6.193m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.471,19.155m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12.442,20.425m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M7.974,19.414m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.417,15.698m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.748,10.246m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.864,5.307m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_59.xml b/core/res/res/drawable/pointer_wait_vector_59.xml new file mode 100644 index 000000000000..2e5e4728ec85 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_59.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.442,3.575m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.069,6.139m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.309,18.556m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M13.465,20.308m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M8.568,19.707m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.657,16.154m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.679,10.608m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.634,5.49m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_6.xml b/core/res/res/drawable/pointer_wait_vector_6.xml new file mode 100644 index 000000000000..d4f57af49b40 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_6.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.588,20.416m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.633,18.51m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.926,3.564m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.861,5.931m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.431,11.706m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.269,17.645m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_60.xml b/core/res/res/drawable/pointer_wait_vector_60.xml new file mode 100644 index 000000000000..4f257671d25d --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_60.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.294,3.569m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.069,6.139m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.12,17.807m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.183,20.149m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.115,19.928m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M4.845,16.471m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.646,10.826m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.465,5.633m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_61.xml b/core/res/res/drawable/pointer_wait_vector_61.xml new file mode 100644 index 000000000000..7e06db4d1874 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_61.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.147,3.565m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.017,6.087m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.738,17.077m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M14.885,19.928m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M9.604,20.089m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.047,16.779m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.61,11.118m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.355,5.73m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_62.xml b/core/res/res/drawable/pointer_wait_vector_62.xml new file mode 100644 index 000000000000..b3d0541a6417 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_62.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.074,3.564m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.231,16.345m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.432,19.707m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.102,20.22m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.307,17.136m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.584,11.411m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.246,5.83m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_63.xml b/core/res/res/drawable/pointer_wait_vector_63.xml new file mode 100644 index 000000000000..ee09c2537d3f --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_63.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.583,15.698m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M15.961,19.449m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.39,20.282m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.397,17.252m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.575,11.558m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.193,5.88m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_64.xml b/core/res/res/drawable/pointer_wait_vector_64.xml new file mode 100644 index 000000000000..e87f94f33304 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_64.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M19.822,15.16m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.345,19.232m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.826,20.354m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.537,17.423m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.571,11.632m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.139,5.931m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_65.xml b/core/res/res/drawable/pointer_wait_vector_65.xml new file mode 100644 index 000000000000..b8407c448db5 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_65.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.023,14.607m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.718,18.994m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M10.972,20.374m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.681,17.59m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.569,11.706m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.087,5.983m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_66.xml b/core/res/res/drawable/pointer_wait_vector_66.xml new file mode 100644 index 000000000000..7e2448df4d11 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_66.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.149,14.184m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M16.959,18.825m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.265,20.405m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.78,17.7m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.565,11.853m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_67.xml b/core/res/res/drawable/pointer_wait_vector_67.xml new file mode 100644 index 000000000000..615ac04c40b3 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_67.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.252,13.754m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.194,18.648m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.412,20.416m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.88,17.807m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_68.xml b/core/res/res/drawable/pointer_wait_vector_68.xml new file mode 100644 index 000000000000..0ba4634a131f --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_68.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.308,13.465m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.366,18.51m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.632,20.429m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.931,17.861m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_69.xml b/core/res/res/drawable/pointer_wait_vector_69.xml new file mode 100644 index 000000000000..efa90bf9df22 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_69.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.354,13.174m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.535,18.367m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.706,20.432m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.931,17.86m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_7.xml b/core/res/res/drawable/pointer_wait_vector_7.xml new file mode 100644 index 000000000000..86d571a40f73 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_7.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.661,20.411m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.69,18.556m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.024,6.045m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.889,3.564m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.808,5.88m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.428,11.632m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.318,17.59m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_70.xml b/core/res/res/drawable/pointer_wait_vector_70.xml new file mode 100644 index 000000000000..4e58af5dfb3b --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_70.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.39,12.882m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.645,18.27m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.853,20.435m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_71.xml b/core/res/res/drawable/pointer_wait_vector_71.xml new file mode 100644 index 000000000000..5a534342ec8d --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_71.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.416,12.589m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.754,18.17m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.853,20.435m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_72.xml b/core/res/res/drawable/pointer_wait_vector_72.xml new file mode 100644 index 000000000000..40fb5d313f7c --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_72.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.425,12.442m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.807,18.12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_73.xml b/core/res/res/drawable/pointer_wait_vector_73.xml new file mode 100644 index 000000000000..933cc6ae4813 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_73.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.429,12.368m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.861,18.069m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_74.xml b/core/res/res/drawable/pointer_wait_vector_74.xml new file mode 100644 index 000000000000..6c7fef264f81 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_74.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.431,12.294m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_75.xml b/core/res/res/drawable/pointer_wait_vector_75.xml new file mode 100644 index 000000000000..24e64e3491cf --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_75.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.435,12.147m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_76.xml b/core/res/res/drawable/pointer_wait_vector_76.xml new file mode 100644 index 000000000000..2ede57de05fd --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_76.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12.073m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_77.xml b/core/res/res/drawable/pointer_wait_vector_77.xml new file mode 100644 index 000000000000..71f811a497a0 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_77.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12.037m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_78.xml b/core/res/res/drawable/pointer_wait_vector_78.xml new file mode 100644 index 000000000000..e2d56c6f676e --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_78.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.437,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_79.xml b/core/res/res/drawable/pointer_wait_vector_79.xml new file mode 100644 index 000000000000..e2d56c6f676e --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_79.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.437,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_8.xml b/core/res/res/drawable/pointer_wait_vector_8.xml new file mode 100644 index 000000000000..ebac74961497 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_8.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.808,20.398m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.806,18.648m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.008,6.061m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.853,3.565m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.754,5.83m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.425,11.558m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.367,17.535m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_80.xml b/core/res/res/drawable/pointer_wait_vector_80.xml new file mode 100644 index 000000000000..40fb5d313f7c --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_80.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.425,12.442m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.807,18.12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_81.xml b/core/res/res/drawable/pointer_wait_vector_81.xml new file mode 100644 index 000000000000..933cc6ae4813 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_81.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.429,12.368m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.861,18.069m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_82.xml b/core/res/res/drawable/pointer_wait_vector_82.xml new file mode 100644 index 000000000000..6c7fef264f81 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_82.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.431,12.294m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_83.xml b/core/res/res/drawable/pointer_wait_vector_83.xml new file mode 100644 index 000000000000..24e64e3491cf --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_83.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.435,12.147m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_84.xml b/core/res/res/drawable/pointer_wait_vector_84.xml new file mode 100644 index 000000000000..2ede57de05fd --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_84.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12.073m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_85.xml b/core/res/res/drawable/pointer_wait_vector_85.xml new file mode 100644 index 000000000000..71f811a497a0 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_85.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.436,12.037m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_86.xml b/core/res/res/drawable/pointer_wait_vector_86.xml new file mode 100644 index 000000000000..e2d56c6f676e --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_86.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.437,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_87.xml b/core/res/res/drawable/pointer_wait_vector_87.xml new file mode 100644 index 000000000000..e2d56c6f676e --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_87.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,3.563m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.437,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.966,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M12,20.437m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,17.966m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.034,6.034m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_9.xml b/core/res/res/drawable/pointer_wait_vector_9.xml new file mode 100644 index 000000000000..d46dfa394c01 --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_9.xml @@ -0,0 +1,30 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12.881,20.39m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M6.864,18.693m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M3.563,12.052m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M5.983,6.087m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M11.816,3.565m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M17.754,5.83m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M20.423,11.522m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> + <path + android:pathData="M18.415,17.479m-1.781,0a1.781,1.781 0,1 1,3.562 0a1.781,1.781 0,1 1,-3.562 0" + android:fillColor="#FFF"/> +</vector> diff --git a/core/res/res/drawable/pointer_wait_vector_icon.xml b/core/res/res/drawable/pointer_wait_vector_icon.xml new file mode 100644 index 000000000000..45d371e95c5d --- /dev/null +++ b/core/res/res/drawable/pointer_wait_vector_icon.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android" + android:bitmap="@drawable/pointer_wait_vector" + android:hotSpotX="12dp" + android:hotSpotY="12dp" /> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index da67efee4842..6cd2c4e277ea 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk is gestaaf"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesig is gestaaf"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesig is gestaaf; druk asseblief bevestig"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Vingerafdrukhardeware is nie beskikbaar nie"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan nie vingerafdruk opstel nie"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Vingerafdrukopstelling het uitgetel. Probeer weer."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Vingerafdrukhandeling is gekanselleer"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Vingerafdrukhandeling is deur gebruiker gekanselleer"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Te veel pogings. Gebruik eerder skermslot."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Te veel pogings. Gebruik eerder skermslot."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Kan nie vingerafdruk verwerk nie. Probeer weer."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Geen vingerafdrukke is geregistreer nie"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Hierdie toetstel het nie \'n vingerafdruksensor nie"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor is tydelik gedeaktiveer"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Kan nie vingerafdruksensor gebruik nie. Besoek ’n verskaffer wat herstelwerk doen."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Aan/af-skakelaar is gedruk"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Gebruik vingerafdruk"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 4a7f6f3b7976..b485b4bdd5f0 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"የጣት አሻራ ትክክለኛነት ተረጋግጧል"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ፊት ተረጋግጧል"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ፊት ተረጋግጧል፣ እባክዎ አረጋግጥን ይጫኑ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"የጣት አሻራ ሃርድዌር አይገኝም"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"የጣት አሻራን ማዋቀር አልተቻለም"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"የጣት አሻራ ውቅረት ጊዜው አብቅቷል። እንደገና ይሞክሩ።"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"የጣት አሻራ ክወና ተሰርዟል"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"የጣት አሻራ ክወና በተጠቃሚ ተሰርዟል"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"በጣም ብዙ ሙከራዎች። በምትኩ የማያ ገፅ መቆለፊያን ይጠቀሙ።"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"በጣም ብዙ ሙከራዎች። በምትኩ የማያ ገፅ መቆለፊያን ይጠቀሙ።"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"የጣት አሻራን ማሰናዳት አልተቻለም። እንደገና ይሞክሩ።"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ምንም የጣት አሻራዎች አልተመዘገቡም"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ይህ መሣሪያ የጣት አሻራ ዳሳሽ የለውም"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ዳሳሽ ለጊዜው ተሰናክሏል"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"የጣት አሻራ ዳሳሽን መጠቀም አይቻልም። የጥገና አገልግሎት አቅራቢን ይጎብኙ።"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"የኃይል አዝራር ተጭኗል"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ጣት <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"የጣት አሻራ ይጠቀሙ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index b767c5704cef..b12c1154f038 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -670,24 +670,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"تم مصادقة بصمة الإصبع"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"تمّت مصادقة الوجه"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"تمّت مصادقة الوجه، يُرجى الضغط على \"تأكيد\"."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"جهاز التعرّف على بصمة الإصبع غير متاح"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"يتعذّر إعداد بصمة الإصبع."</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"انتهت مهلة إعداد بصمة الإصبع. يُرجى إعادة المحاولة."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"تم إلغاء عملية قراءة بصمة الإصبع"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ألغى المستخدم عملية قراءة بصمة الإصبع"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"تم إجراء عدد كبير جدًا من المحاولات. عليك استخدام قفل الشاشة بدلاً من ذلك."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"تم إجراء عدد كبير جدًا من المحاولات. عليك استخدام قفل الشاشة بدلاً من ذلك."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"تتعذّر معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ما مِن بصمات إصبع مسجَّلة"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"لا يحتوي هذا الجهاز على جهاز استشعار بصمات الأصابع."</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"تم مؤقتًا إيقاف أداة الاستشعار"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"يتعذّر استخدام أداة استشعار بصمة الإصبع. يُرجى التواصل مع مقدِّم خدمات إصلاح."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"تم الضغط على زر التشغيل"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"الإصبع <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"استخدام بصمة الإصبع"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 19d8357644d8..01705ad6cd68 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল, অনুগ্ৰহ কৰি ‘নিশ্চিত কৰক’ বুটামটো টিপক"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ফিংগাৰপ্ৰিণ্ট ছেট আপ কৰিব নোৱাৰি"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ফিংগাৰপ্ৰিণ্ট ছেটআপ কৰাৰ সময় উকলি গৈছে। পুনৰ চেষ্টা কৰক।"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ফিংগাৰপ্ৰিণ্টৰ দ্বাৰা বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কাৰ্যটো বাতিল কৰা হৈছে"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ব্যৱহাৰকাৰীয়ে ফিংগাৰপ্ৰিণ্টৰ দ্বাৰা বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কাৰ্য বাতিল কৰিছে"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"অতি বেছিসংখ্যক প্ৰয়াস। ইয়াৰ সলনি স্ক্ৰীন লক ব্যৱহাৰ কৰক।"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"অতি বেছিসংখ্যক প্ৰয়াস। ইয়াৰ সলনি স্ক্ৰীন লক ব্যৱহাৰ কৰক।"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ফিংগাৰপ্ৰিণ্ট চিনাক্তকৰণ প্ৰক্ৰিয়া কৰিব পৰা নাই। পুনৰ চেষ্টা কৰক।"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"কোনো ফিংগাৰপ্ৰিণ্ট পঞ্জীয়ন কৰা হোৱা নাই"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"এই ডিভাইচটোত ফিংগাৰপ্ৰিণ্ট ছেন্সৰ নাই"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ছেন্সৰটো সাময়িকভাৱে অক্ষম হৈ আছে"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰ ব্যৱহাৰ কৰিব নোৱাৰি। মেৰামতি সেৱা প্ৰদানকাৰী কোনো প্ৰতিষ্ঠানলৈ যাওক।"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"পাৱাৰ বুটাম টিপা হৈছে"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> আঙুলি"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index b82ffdced01a..4ed5f5eadd5b 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmaq izi doğrulandı"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Üz doğrulandı"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Üz təsdiq edildi, təsdiq düyməsinə basın"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Barmaq izi avadanlığı əlçatan deyil"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Barmaq izini ayarlamaq mümkün deyil"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Barmaq izi ayarlama vaxtı bitib. Yenidən cəhd edin."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Barmaq izi əməliyyatı ləğv edildi"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"İstifadəçi barmaq izi əməliyyatını ləğv etdi"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Həddindən çox cəhd edilib. Əvəzində ekran kilidindən istifadə edin."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Həddindən çox cəhd edilib. Əvəzində ekran kilidindən istifadə edin."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Barmaq izini emal etmək mümkün deyil. Yenidən cəhd edin."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Barmaq izi qeydiyyatdan keçirilməyib"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Bu cihazda barmaq izi sensoru yoxdur"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor müvəqqəti deaktivdir"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Barmaq izi sensorundan istifadə etmək olmur. Servis mərkəzinə gedin."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Qidalanma düyməsi basılıb"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Barmaq <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Barmaq izini istifadə edin"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 655d1d81efe3..b31dca411edb 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je potvrđeno"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je potvrđeno. Pritisnite Potvrdi"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardver za otisak prsta nije dostupan"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Podešavanje otiska prsta nije uspelo"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Vreme za podešavanje otiska prsta je isteklo. Probajte ponovo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Radnja sa otiskom prsta je otkazana"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Korisnik je otkazao radnju sa otiskom prsta"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Previše pokušaja. Koristite zaključavanje ekrana umesto toga."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Koristite zaključavanje ekrana umesto toga."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Obrađivanje otiska prsta nije uspelo. Probajte ponovo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nije registrovan nijedan otisak prsta"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Ovaj uređaj nema senzor za otisak prsta"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor je privremeno onemogućen"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Ne možete da koristite senzor za otisak prsta. Posetite servis."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Pritisnuto je dugme za uključivanje"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Koristite otisak prsta"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index d36c7d1b8b66..2bd78e9080c1 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Адбітак пальца распазнаны"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Твар распазнаны"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Твар распазнаны. Націсніце, каб пацвердзіць"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Сканер адбіткаў пальцаў недаступны"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не ўдалося захаваць адбітак пальца"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Наладжванне адбітка пальца не завершана. Паўтарыце спробу."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Аперацыя з адбіткам пальца скасавана"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Аперацыя з адбіткам пальца скасавана карыстальнікам"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Занадта шмат спроб. Скарыстайце блакіроўку экрана."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Занадта шмат спроб. Скарыстайце блакіроўку экрана."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Не ўдалося апрацаваць адбітак пальца. Паўтарыце спробу."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Адбіткі пальцаў не зарэгістраваны"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"На гэтай прыладзе няма сканера адбіткаў пальцаў"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сканер часова адключаны"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Не ўдалося скарыстаць сканер адбіткаў пальцаў. Звярніцеся ў сэрвісны цэнтр."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Націснута кнопка сілкавання"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Выкарыстоўваць адбітак пальца"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 24d5d293d6f3..dc1e92ca7037 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатъкът е удостоверен"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е удостоверено"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е удостоверено. Моля, натиснете „Потвърждаване“"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Хардуерът за отпечатъци не е налице"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не може да се настрои отпечатък"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Настройването на отпечатък не завърши навреме. Опитайте отново."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Операцията за отпечатък е анулирана"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Операцията за удостоверяване чрез отпечатък бе анулирана от потребителя"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Твърде много опити. Вместо това използвайте опция за заключване на екрана."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Твърде много опити. Вместо това използвайте опция за заключване на екрана."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Отпечатъкът не може да бъде обработен. Опитайте отново."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Няма регистрирани отпечатъци"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Това устройство няма сензор за отпечатъци"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сензорът е временно деактивиран"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Сензорът за отпечатъци не може да се използва. Посетете оторизиран сервиз."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Бутонът за захранване е натиснат"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Пръст <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Използване на отпечатък"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index f7f63cc4cc6c..5dbaad626ab9 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ফেস যাচাই করা হয়েছে"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ফেস যাচাই করা হয়েছে, \'কনফার্ম করুন\' বোতাম প্রেস করুন"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ফিঙ্গারপ্রিন্ট হার্ডওয়্যার উপলভ্য নেই"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"আঙ্গুলের ছাপ সেট-আপ করতে পারছি না"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ফিঙ্গারপ্রিন্ট সেট-আপ করার সময় সীমা পেরিয়ে গেছে। আবার চেষ্টা করুন।"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ফিঙ্গারপ্রিন্ট অপারেশন বাতিল করা হয়েছে"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ব্যবহারকারী ফিঙ্গারপ্রিন্ট অপারেশন বাতিল করেছেন"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"অনেকবার চেষ্টা করেছেন। পরিবর্তে স্ক্রিন লক ব্যবহার করুন।"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"অনেকবার চেষ্টা করেছেন। পরিবর্তে স্ক্রিন লক ব্যবহার করুন।"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ফিঙ্গারপ্রিন্ট প্রসেস করা যায়নি। আবার চেষ্টা করুন।"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"কোনও ফিঙ্গারপ্রিন্ট নথিভুক্ত করা নেই"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"এই ডিভাইসে আঙ্গুলের ছাপের সেন্সর নেই"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"সেন্সর অস্থায়ীভাবে বন্ধ আছে"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ফিঙ্গারপ্রিন্ট সেন্সর ব্যবহার করা যাচ্ছে না। একজন মেরামতি মিস্ত্রির কাছে যান।"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"পাওয়ার বোতাম প্রেস করা হয়েছে"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"আঙ্গুলের ছাপ ব্যবহার করুন"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index b433f7762dd1..838a2db90408 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je provjereno"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je provjereno, pritisnite dugme za potvrdu"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardver za prepoznavanje otiska prsta nije dostupan"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nije moguće postaviti otisak prsta"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Postavljanje otiska prsta je isteklo. Pokušajte ponovo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Radnja s otiskom prsta je otkazana"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Korisnik je otkazao radnju s otiskom prsta"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Previše pokušaja. Umjesto toga koristite zaključavanje ekrana."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Umjesto toga koristite zaključavanje ekrana."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nije moguće obraditi otisak prsta. Pokušajte ponovo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nije registriran nijedan otisak prsta"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Ovaj uređaj nema senzor za otisak prsta"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor je privremeno onemogućen"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Nije moguće koristiti senzor za otisak prsta. Posjetite pružaoca usluga za popravke."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Dugme za uključivanje je pritisnuto"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Koristi otisak prsta"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index f93d6bb9562f..feb67c42ccf6 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"L\'empremta digital s\'ha autenticat"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Cara autenticada; prem el botó per confirmar"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"El maquinari d\'empremtes digitals no està disponible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No es pot configurar l\'empremta digital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Temps d\'espera esgotat per configurar l\'empremta digital. Torna-ho a provar."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"S\'ha cancel·lat l\'operació d\'empremta digital"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"L\'usuari ha cancel·lat l\'operació d\'empremta digital"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Massa intents. Utilitza el bloqueig de pantalla."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Massa intents. Utilitza el bloqueig de pantalla."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"No es pot processar l\'empremta digital. Torna-ho a provar."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No s\'ha registrat cap empremta digital"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Aquest dispositiu no té sensor d\'empremtes digitals"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"El sensor està desactivat temporalment"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"No es pot utilitzar el sensor d\'empremtes digitals. Visita un proveïdor de reparacions."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"S\'ha premut el botó d\'engegada"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utilitza l\'empremta digital"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 7edc6b46c623..1c0529a71e59 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisk byl ověřen"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Obličej byl ověřen"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Obličej byl ověřen, stiskněte tlačítko pro potvrzení"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Není k dispozici hardware ke snímání otisků prstů"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Otisk prstu se nepodařilo nastavit"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Časový limit nastavení otisku prstu vypršel. Zkuste to znovu."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operace otisku prstu byla zrušena"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Uživatel operaci s otiskem prstu zrušil"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Příliš mnoho pokusů. Použijte zámek obrazovky."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Příliš mnoho pokusů. Použijte zámek obrazovky."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Otisk prstu nelze zpracovat. Zkuste to znovu."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nejsou zaregistrovány žádné otisky prstů"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Toto zařízení nemá snímač otisků prstů"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor je dočasně deaktivován"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Snímač otisků prstů nelze použít. Navštivte servis"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Bylo stisknut vypínač"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Použít otisk prstu"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index b5938fd09d96..3010dc7ec883 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeraftrykket blev godkendt"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansigtet er godkendt"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansigtet er godkendt. Tryk på Bekræft."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware til aflæsning af fingeraftryk er ikke tilgængelig"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Fingeraftrykket kan ikke gemmes"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Konfigurationen af fingeraftryk fik timeout. Prøv igen."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingeraftrykshandlingen er annulleret"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingeraftrykshandlingen er annulleret af brugeren"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Du har brugt for mange forsøg. Brug skærmlåsen i stedet."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Du har brugt for mange forsøg. Brug skærmlåsen i stedet."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Fingeraftrykket kan ikke behandles. Prøv igen."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Der er ikke registreret et fingeraftryk"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Denne enhed har ingen fingeraftrykslæser"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensoren er midlertidigt deaktiveret"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Fingeraftrykssensoren kan ikke bruges. Få den repareret."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Der blev trykket på afbryderknappen"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Brug fingeraftryk"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 59c7d4a0d389..803b96720a01 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerabdruck wurde authentifiziert"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesicht authentifiziert"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesicht authentifiziert, bitte bestätigen"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerabdruck-Hardware nicht verfügbar"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Fingerabdruck konnte nicht eingerichtet werden"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Zeitüberschreitung bei Fingerabdruckeinrichtung. Versuch es noch einmal."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerabdruckvorgang abgebrochen"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerabdruckvorgang vom Nutzer abgebrochen"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Zu viele Versuche. Verwende stattdessen die Displaysperre."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Zu viele Versuche. Verwende stattdessen die Displaysperre."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Fingerabdruck kann nicht verarbeitet werden. Versuch es noch einmal."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Keine Fingerabdrücke registriert"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Dieses Gerät hat keinen Fingerabdrucksensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Der Sensor ist vorübergehend deaktiviert"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Fingerabdrucksensor kann nicht verwendet werden. Suche einen Reparaturdienstleister auf."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Ein-/Aus-Taste wurde gedrückt"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Fingerabdruck verwenden"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 762bd52bed0c..c030d25ecada 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Έγινε έλεγχος ταυτότητας προσώπου"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Ο εξοπλισμός δακτυλικού αποτυπώματος δεν είναι διαθέσιμος"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Δεν είναι δυνατή η ρύθμιση του δακτυλικού αποτυπώματος"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Λήξη χρονικού ορίου ρύθμισης δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Υπερβολικά πολλές προσπάθειες. Χρησιμοποιήστε εναλλακτικά το κλείδωμα οθόνης."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Υπερβολικά πολλές προσπάθειες. Χρησιμοποιήστε εναλλακτικά το κλείδωμα οθόνης."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Δεν είναι δυνατή η επεξεργασία του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Δεν έχουν καταχωριστεί δακτυλικά αποτυπώματα"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Ο αισθητήρας απενεργοποιήθηκε προσωρινά"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Δεν είναι δυνατή η χρήση του αισθητήρα δακτυλικών αποτυπωμάτων. Επισκεφτείτε έναν πάροχο υπηρεσιών επισκευής."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Το κουμπί λειτουργίας πατήθηκε"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Χρήση δακτυλικού αποτυπώματος"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 719c4232a52d..cecdce61f3e2 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerprint hardware not available"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerprint operation cancelled"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerprint operation cancelled by user"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No fingerprints enrolled"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"This device does not have a fingerprint sensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporarily disabled"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Can\'t use fingerprint sensor. Visit a repair provider."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Use fingerprint"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index e317067c53f9..c3cf40402b42 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated, please press confirm"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerprint hardware not available"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerprint operation canceled"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerprint operation canceled by user"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No fingerprints enrolled"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"This device does not have a fingerprint sensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporarily disabled"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Can’t use fingerprint sensor. Visit a repair provider."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Use fingerprint"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 0e58b1d17615..cda0168b4600 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerprint hardware not available"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerprint operation cancelled"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerprint operation cancelled by user"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No fingerprints enrolled"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"This device does not have a fingerprint sensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporarily disabled"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Can\'t use fingerprint sensor. Visit a repair provider."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Use fingerprint"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 3c6b6712b84b..f979e270448c 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerprint hardware not available"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerprint operation cancelled"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerprint operation cancelled by user"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No fingerprints enrolled"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"This device does not have a fingerprint sensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporarily disabled"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Can\'t use fingerprint sensor. Visit a repair provider."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Use fingerprint"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 34a020f4395a..e620c35f89ad 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated, please press confirm"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingerprint hardware not available"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingerprint operation canceled"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingerprint operation canceled by user"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No fingerprints enrolled"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"This device does not have a fingerprint sensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporarily disabled"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Can’t use fingerprint sensor. Visit a repair provider."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Use fingerprint"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 7fb0d1f446d1..da500d7d50eb 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Se autenticó la huella dactilar"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Se autenticó el rostro"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se autenticó el rostro; presiona Confirmar"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"El hardware de huella dactilar no está disponible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No se puede configurar la huella dactilar"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Se agotó el tiempo de espera para configurar la huella dactilar. Vuelve a intentarlo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Se canceló la operación de huella dactilar"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"El usuario canceló la operación de huella dactilar"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Demasiados intentos. Utiliza el bloqueo de pantalla en su lugar."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Utiliza el bloqueo de pantalla en su lugar."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"No se puede procesar la huella dactilar. Vuelve a intentarlo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No se inscribieron huellas dactilares"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Este dispositivo no tiene sensor de huellas dactilares"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Se inhabilitó temporalmente el sensor"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"No se puede usar el sensor de huellas dactilares. Consulta a un proveedor de reparaciones."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Se presionó el botón de encendido"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar huella dactilar"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 7d0c4e0318f4..35cd1ebe784f 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Se ha autenticado la huella digital"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se ha autenticado la cara, pulsa para confirmar"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Lector de huellas digitales no disponible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No se puede configurar la huella digital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Tiempo de espera para configurar la huella digital agotado. Inténtalo de nuevo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operación de huella digital cancelada"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"El usuario ha cancelado la operación de huella digital"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Demasiados intentos. Usa el bloqueo de pantalla."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Usa el bloqueo de pantalla."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"No se puede procesar la huella digital. Inténtalo de nuevo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"No se ha registrado ninguna huella digital"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"El dispositivo no tiene ningún sensor de huellas digitales"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor inhabilitado en estos momentos"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"No se puede usar el sensor de huellas digitales. Visita un proveedor de reparaciones."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Se ha pulsado el botón de encendido"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar huella digital"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 250341f07a82..24ee88437930 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sõrmejälg autenditi"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Nägu on autenditud"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Nägu on autenditud, vajutage käsku Kinnita"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Sõrmejälje riistvara pole saadaval"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Sõrmejälge ei saa seadistada"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Sõrmejälje seadistamine aegus. Proovige uuesti."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Sõrmejälje toiming tühistati"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Kasutaja tühistas sõrmejälje kasutamise"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Liiga palju katseid. Kasutage selle asemel ekraanilukku."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Liiga palju katseid. Kasutage selle asemel ekraanilukku."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Sõrmejälge ei õnnestu töödelda. Proovige uuesti."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ühtegi sõrmejälge pole registreeritud"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Selles seadmes pole sõrmejäljeandurit"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Andur on ajutiselt keelatud"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Sõrmejäljeandurit ei saa kasutada. Külastage remonditeenuse pakkujat."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Vajutati toitenuppu"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Sõrmejälg <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Sõrmejälje kasutamine"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 3c5377989497..583f8a995d43 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentifikatu da hatz-marka"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autentifikatu da aurpegia"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autentifikatu da aurpegia; sakatu Berretsi"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hatz-marken hardwarea ez dago erabilgarri"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ezin da konfiguratu hatz-marka"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Hatz-marka konfiguratzeko denbora-muga gainditu da. Saiatu berriro."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Bertan behera utzi da hatz-marka bidezko eragiketa"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Erabiltzaileak bertan behera utzi du hatz-marka bidezko eragiketa"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Saiakera gehiegi egin dira. Erabili pantailaren blokeoa."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Saiakera gehiegi egin dira. Erabili pantailaren blokeoa."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Ezin da prozesatu hatz-marka. Saiatu berriro."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ez dago hatz-markarik erregistratuta"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Gailu honek ez du hatz-marken sentsorerik"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sentsorea aldi baterako desgaitu da"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Ezin da erabili hatz-marken sentsorea. Joan konponketak egiten dituen hornitzaile baten webgunera edo dendara."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Etengailua sakatu da"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. hatza"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Erabili hatz-marka"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 640f93f73563..52de6dac5f28 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"اثر انگشت اصالتسنجی شد"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چهره اصالتسنجی شد"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره اصالتسنجی شد، لطفاً تأیید را فشار دهید"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"سختافزار اثر انگشت دردسترس نیست"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"اثر انگشت راهاندازی نشد"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"مهلت تنظیم اثر انگشت بهپایان رسید. دوباره امتحان کنید."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"عملکرد اثر انگشت لغو شد"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"کاربر عملیات اثر انگشت را لغو کرد"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"تلاشها از حد مجاز بیشتر شده است. بهجای آن از قفل صفحه استفاده کنید."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"تلاشهای بیشازحد. حالا از قفل صفحه استفاده کنید."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"اثر انگشت پردازش نشد. دوباره امتحان کنید."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"اثر انگشتی ثبت نشده است"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"این دستگاه حسگر اثر انگشت ندارد"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"حسگر موقتاً غیرفعال شده است"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"نمیتوان از حسگر اثر انگشت استفاده کرد. به ارائهدهنده خدمات تعمیر مراجعه کنید."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"دکمه روشن/خاموش فشار داده شد"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"استفاده از اثر انگشت"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 18b9ee2a5a64..20d4c14c8c86 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sormenjälki tunnistettu"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Kasvot tunnistettu"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Kasvot tunnistettu, valitse Vahvista"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Sormenjälkilaitteisto ei käytettävissä"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Sormenjälkeä ei voi ottaa käyttöön"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Sormenjäljen käyttöönotto aikakatkaistu. Yritä uudelleen."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Sormenjälkitoiminto peruttu"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Käyttäjä on perunut sormenjälkitoiminnon"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Liian monta yritystä. Käytä näytön lukituksen avaustapaa."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Liian monta yritystä. Käytä näytön lukituksen avaustapaa."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Sormenjälkeä ei voida käsitellä. Yritä uudelleen."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Sormenjälkiä ei ole lisätty"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Laitteessa ei ole sormenjälkitunnistinta."</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Tunnistin väliaikaisesti pois käytöstä"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Sormenjälkitunnistinta ei voi käyttää. Ota yhteys korjauspalveluun."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Virtapainiketta on painettu"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Sormi <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Käytä sormenjälkeä"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 1eb9eb21c842..b6349427b89c 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Lecteur d\'empreintes digitales non accessible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossible de configurer l\'empreinte digitale"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Délai dépassé pour configurer l\'empreinte digitale. Réessayez."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Opération d\'empreinte digitale annulée"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Empreinte digitale non traitable. Réessayez."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Aucune empreinte digitale enregistrée"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Cet appareil ne possède pas de capteur d\'empreintes digitales"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Capteur désactivé temporairement"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Impossible d\'utiliser le capteur d\'empreintes digitales. Visitez un fournisseur de services de réparation."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Vous avez appuyé sur l\'interrupteur"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utiliser l\'empreinte digitale"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index c349b1cf1774..f0ed3d6290b5 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -201,7 +201,7 @@ <string name="device_ownership_relinquished" msgid="4080886992183195724">"L\'administrateur a mis l\'appareil à disposition pour un usage personnel"</string> <string name="network_logging_notification_title" msgid="554983187553845004">"L\'appareil est géré"</string> <string name="network_logging_notification_text" msgid="1327373071132562512">"Votre organisation gère cet appareil et peut surveiller le trafic réseau. Appuyez ici pour obtenir plus d\'informations."</string> - <string name="location_changed_notification_title" msgid="3620158742816699316">"Des application peuvent accéder à votre position"</string> + <string name="location_changed_notification_title" msgid="3620158742816699316">"Des applications peuvent accéder à votre position"</string> <string name="location_changed_notification_text" msgid="7158423339982706912">"Contactez votre administrateur pour en savoir plus"</string> <string name="geofencing_service" msgid="3826902410740315456">"Service de géorepérage"</string> <string name="country_detector" msgid="7023275114706088854">"Détecteur de pays"</string> @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Lecteur d\'empreintes digitales indisponible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossible de configurer l\'empreinte"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Délai de configuration de l\'empreinte dépassé. Réessayez."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Opération d\'authentification par empreinte digitale annulée"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Impossible de reconnaître l\'empreinte digitale. Réessayez."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Aucune empreinte digitale enregistrée"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Aucun lecteur d\'empreinte digitale n\'est installé sur cet appareil"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Lecteur d\'empreintes temporairement désactivé"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Impossible d\'utiliser le lecteur d\'empreintes digitales. Contactez un réparateur."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Bouton Marche/Arrêt appuyé"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utiliser l\'empreinte digitale"</string> @@ -802,8 +796,8 @@ <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string> <string name="permlab_bindDreamService" msgid="4776175992848982706">"associer à un service d\'écran de veille interactif"</string> <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service d\'écran de veille interactif. Cette autorisation ne devrait jamais être nécessaire pour les applications standards."</string> - <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"faire appel à l\'application de configuration fournie par l\'opérateur"</string> - <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par l\'opérateur. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string> + <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoquer l\'appli de configuration fournie par l\'opérateur"</string> + <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Permet au titulaire d\'invoquer l\'appli de configuration fournie par l\'opérateur. Ne devrait pas être nécessaire pour les applis standards."</string> <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"détecter des observations sur les conditions du réseau"</string> <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Permet à une application de détecter des observations sur les conditions du réseau. Les applications standards ne devraient pas nécessiter cette autorisation."</string> <string name="permlab_setInputCalibration" msgid="932069700285223434">"modifier le calibrage du périphérique d\'entrée"</string> @@ -839,7 +833,7 @@ <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Contrôle le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouille votre appareil Android TV ou en efface toutes les données si le nombre maximal de mots de passe incorrects autorisé est dépassé."</string> <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le système d\'infoloisirs ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le téléphone ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string> - <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Contrôlez le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouillez la tablette ou effacez toutes les informations sur l\'utilisateur si le nombre maximal de mots de passe incorrects autorisés est dépassé."</string> + <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Contrôlez le nombre de mots de passe incorrects saisis pour déverrouiller l\'écran, et verrouillez la tablette ou effacez toutes les données de cet utilisateur si trop de mots de passe incorrects sont saisis."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Contrôle le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouille votre appareil Android TV ou efface toutes les données de cet utilisateur si le nombre maximal de mots de passe incorrects autorisé est dépassé."</string> <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le système d\'infoloisirs ou effacer toutes les données de ce profil si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Contrôlez le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouillez le téléphone ou effacez toutes les informations sur l\'utilisateur si le nombre maximal de mots de passe incorrects autorisés est dépassé."</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 2cc80d5cf9a7..da791af2ec3a 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autenticouse a impresión dixital"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autenticouse a cara"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autenticouse a cara, preme Confirmar"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"O hardware de impresión dixital non está dispoñible"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Non se puido configurar a impresión dixital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Esgotouse o tempo para configurar a impresión dixital. Téntao de novo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Cancelouse a operación de impresión dixital"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"O usuario cancelou a operación de impresión dixital"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Houbo demasiados intentos. Mellor usa o bloqueo de pantalla."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Mellor usa o bloqueo de pantalla."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Non se pode procesar a impresión dixital Téntao de novo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Non se rexistrou ningunha impresión dixital"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Este dispositivo non ten sensor de impresión dixital"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"O sensor está desactivado temporalmente"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Non se pode usar o sensor de impresión dixital. Vai a un servizo de reparación."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Premeuse o botón de acendido"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utilizar impresión dixital"</string> @@ -1003,7 +997,7 @@ <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Téntao de novo"</string> <string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloquea para gozar todas as funcións e datos"</string> <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Superouse o número máximo de intentos de desbloqueo facial"</string> - <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Non hai ningunha SIM"</string> + <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Non hai SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Non hai ningunha SIM na tableta."</string> <string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"Non hai ningunha SIM no dispositivo Android TV."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="6184187634180854181">"Non hai ningunha SIM no teléfono."</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 1ef8c4703205..8f6affa7a91e 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ચહેરા પ્રમાણિત"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ચહેરા પ્રમાણિત, કૃપા કરીને કન્ફર્મ કરો"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ફિંગરપ્રિન્ટનું સેટઅપ કરી શકતા નથી"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ફિંગરપ્રિન્ટનું સેટઅપ કરવાનો સમય સમાપ્ત થઈ ગયો. ફરી પ્રયાસ કરો."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"વપરાશકર્તાએ ફિંગરપ્રિન્ટ ચકાસવાની પ્રક્રિયા રદ કરી"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ઘણા બધા પ્રયાસો. તેને બદલે સ્ક્રીન લૉકનો ઉપયોગ કરો."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ઘણા બધા પ્રયાસો. વિકલ્પ તરીકે સ્ક્રીન લૉકનો ઉપયોગ કરો."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ફિંગરપ્રિન્ટની પ્રક્રિયા કરી શકતા નથી. ફરી પ્રયાસ કરો."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"કોઈ ફિંગરપ્રિન્ટની નોંધણી કરવામાં આવી નથી"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"આ ડિવાઇસમાં કોઈ ફિંગરપ્રિન્ટ સેન્સર નથી"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"સેન્સર હંગામી રીતે બંધ કર્યું છે"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ફિંગરપ્રિન્ટ સેન્સરનો ઉપયોગ કરી શકાતો નથી. રિપેર કરવાની સેવા આપતા પ્રદાતાની મુલાકાત લો."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"પાવર બટન દબાવવામાં આવ્યું"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"આંગળી <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index bd49843657a7..53b39ffed09b 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"फ़िंगरप्रिंट की पुष्टि हो गई"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरे की पहचान की गई"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"फ़िंगरप्रिंट को पहचानने वाला हार्डवेयर मौजूद नहीं है"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फ़िंगरप्रिंट सेट अप नहीं किया जा सका"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"फ़िंगरप्रिंट सेटअप करने का समय खत्म हो गया. फिर से कोशिश करें."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"फिंगरप्रिंट की पुष्टि से जुड़ी कार्रवाई रद्द कर दी गई है"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि से जुड़ी कार्रवाई रद्द कर दी है"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"कई बार कोशिश की जा चुकी है. इसके बजाय, स्क्रीन लॉक का इस्तेमाल करें."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"इससे ज़्यादा बार कोशिश नहीं की जा सकती. इसके बजाय, स्क्रीन लॉक का इस्तेमाल करें."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"फ़िंगरप्रिंट की पहचान नहीं की जा सकी. फिर से कोशिश करें."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"कोई फ़िंगरप्रिंट रजिस्टर नहीं किया गया है"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"इस डिवाइस में फ़िंगरप्रिंट सेंसर नहीं है"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"सेंसर कुछ समय के लिए बंद कर दिया गया है"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"फ़िंगरप्रिंट सेंसर इस्तेमाल नहीं किया जा सकता. फ़िंगरप्रिंट सेंसर को रिपेयर करने की सेवा देने वाली कंपनी से संपर्क करें."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"पावर बटन दबाने की वजह से गड़बड़ी हुई"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"फ़िंगरप्रिंट <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"फ़िंगरप्रिंट इस्तेमाल करें"</string> @@ -1171,7 +1165,7 @@ <string name="Midnight" msgid="8176019203622191377">"मध्यरात्रि"</string> <string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> - <string name="selectAll" msgid="1532369154488982046">"सभी को चुनें"</string> + <string name="selectAll" msgid="1532369154488982046">"पूरा टेक्स्ट चुनें"</string> <string name="cut" msgid="2561199725874745819">"काटें"</string> <string name="copy" msgid="5472512047143665218">"कॉपी करें"</string> <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"क्लिपबोर्ड पर कॉपी नहीं हो सका"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index f1e9bd6d0636..9af2496fadf1 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentificirano otiskom prsta"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je autentificirano"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je autentificirano, pritisnite Potvrdi"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardver za otisak prsta nije dostupan"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Postavljanje otiska prsta nije uspjelo"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Vrijeme za postavljanje otiska prsta je isteklo. Pokušajte ponovo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Radnja otiska prsta je otkazana"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Radnju s otiskom prsta otkazao je korisnik"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Previše pokušaja. Umjesto toga upotrijebite zaključavanje zaslona."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Umjesto toga upotrijebite zaključavanje zaslona."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nije registriran nijedan otisak prsta"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Ovaj uređaj nema senzor otiska prsta"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor je privremeno onemogućen"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Senzor otiska prsta ne može se koristiti. Posjetite servisera."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Pritisnuta je tipka za uključivanje/isključivanje"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Upotreba otiska prsta"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 26c607788ac1..17f80d12a1fe 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Ujjlenyomat hitelesítve"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Arc hitelesítve"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Arc hitelesítve; nyomja meg a Megerősítés lehetőséget"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Az ujjlenyomat-olvasó hardverhez nem lehet hozzáférni."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nem sikerült beállítani az ujjlenyomatot"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Lejárt az ujjlenyomat-beállítás időkorlátja. Próbálkozzon újra."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Ujjlenyomattal kapcsolatos művelet megszakítva."</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Az ujjlenyomattal kapcsolatos műveletet a felhasználó megszakította."</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Túl sokszor próbálkozott. Használja inkább a képernyőzárat."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Túl sok próbálkozás. Használja inkább a képernyőzárat."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nincsenek regisztrált ujjlenyomatok."</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Ez az eszköz nem rendelkezik ujjlenyomat-érzékelővel"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Az érzékelő átmenetileg le van tiltva."</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Nem lehet használni az ujjlenyomat-érzékelőt. Keresse fel a szervizt."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Bekapcsológomb megnyomva"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. ujj"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Ujjlenyomat használata"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index e82dc708de73..51d0dedbef5a 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Մատնահետքը նույնականացվեց"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Դեմքը ճանաչվեց"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Դեմքը ճանաչվեց: Սեղմեք «Հաստատել»:"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Մատնահետքերի սկաներն անհասանելի է"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Հնարավոր չէ կարգավորել մատնահետքը"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Մատնահետքի կարգավորման ժամանակը սպառվել է։ Նորից փորձեք։"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Մատնահետքի օգտագործմամբ գործողությունը չեղարկվել է"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Մատնահետքի օգտագործմամբ գործողությունը չեղարկվել է օգտատիրոջ կողմից"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Չափազանց շատ փորձեր են արվել։ Օգտագործեք էկրանի կողպումը։"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Չափազանց շատ փորձեր են արվել։ Օգտագործեք էկրանի կողպումը։"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Չի հաջողվում մշակել մատնահետքը։ Նորից փորձեք։"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Գրանցված մատնահետքեր չկան"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Սարքը չունի մատնահետքի սկաներ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Տվիչը ժամանակավորապես անջատված է"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Մատնահետքերի սկաները հնարավոր չէ օգտագործել։ Այցելեք սպասարկման կենտրոն։"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Սեղմվել է սնուցման կոճակը"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Օգտագործել մատնահետք"</string> @@ -1607,8 +1601,8 @@ <string name="storage_internal" msgid="8490227947584914460">"Ներքին ընդհանուր կրիչ"</string> <string name="storage_sd_card" msgid="3404740277075331881">"SD քարտ"</string> <string name="storage_sd_card_label" msgid="7526153141147470509">"SD քարտ <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string> - <string name="storage_usb_drive" msgid="448030813201444573">"USB սարքավար"</string> - <string name="storage_usb_drive_label" msgid="6631740655876540521">"USB սարքավար <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string> + <string name="storage_usb_drive" msgid="448030813201444573">"USB կրիչ"</string> + <string name="storage_usb_drive_label" msgid="6631740655876540521">"USB կրիչ <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string> <string name="storage_usb" msgid="2391213347883616886">"USB կրիչ"</string> <string name="extract_edit_menu_button" msgid="63954536535863040">"Խմբագրել"</string> <string name="data_usage_warning_title" msgid="9034893717078325845">"Զգուշացում թրաֆիկի օգտագործման մասին"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 52d1463c7e24..29dc27307f36 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sidik jari diautentikasi"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah diautentikasi"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah diautentikasi, silakan tekan konfirmasi"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware sidik jari tidak tersedia"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Tidak dapat menyiapkan sidik jari"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Waktu penyiapan sidik jari habis. Coba lagi."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operasi sidik jari dibatalkan"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operasi sidik jari dibatalkan oleh pengguna"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Terlalu banyak upaya gagal. Gunakan kunci layar."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Terlalu banyak upaya gagal. Gunakan kunci layar."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Tidak dapat memproses sidik jari. Coba lagi."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Tidak ada sidik jari yang terdaftar"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Perangkat ini tidak memiliki sensor sidik jari"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor dinonaktifkan untuk sementara"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Tidak dapat menggunakan sensor sidik jari. Kunjungi penyedia reparasi."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Tombol daya ditekan"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Gunakan sidik jari"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 81e5a62d5c38..ca702fa3e68c 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingrafar staðfest"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Andlit staðfest"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Andlit staðfest, ýttu til að staðfesta"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Fingrafarabúnaður er ekki til staðar"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ekki er hægt að setja upp fingrafar"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingrafarsuppsetning rann út á tíma. Reyndu aftur."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Hætt var við að nota fingrafar"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Notandi hætti við að nota fingrafar"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Of margar tilraunir. Notaðu skjálás í staðinn."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Of margar tilraunir. Notaðu skjálás í staðinn."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Ekki tekst að vinna úr fingrafari. Reyndu aftur."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Engin fingraför hafa verið skráð"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Þetta tæki er ekki með fingrafaralesara"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Slökkt var á lesara tímabundið"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Ekki er hægt að nota fingrafaralesara. Þú verður að fara á verkstæði."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Ýtt á aflrofa"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Fingur <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Nota fingrafar"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index e5a8b2506366..2cb3d3d9826d 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impronta autenticata"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Volto autenticato"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Volto autenticato, premi Conferma"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Lettore di impronte digitali non disponibile"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossibile configurare l\'impronta"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Timeout configurazione impronta. Riprova."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operazione associata all\'impronta annullata"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operazione di autenticazione dell\'impronta annullata dall\'utente"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Troppi tentativi. Usa il blocco schermo."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Troppi tentativi. Usa il blocco schermo."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Impossibile elaborare l\'impronta. Riprova."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nessuna impronta registrata"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Questo dispositivo non è dotato di sensore di impronte"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensore temporaneamente disattivato"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Impossibile usare il sensore di impronte digitali. Contatta un fornitore di servizi di riparazione."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Tasto di accensione premuto"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dito <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usa l\'impronta"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 1e040c19bd89..3e7c79e050de 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"טביעת האצבע אומתה"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"זיהוי הפנים בוצע"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"החומרה לזיהוי טביעות אצבע לא זמינה"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"לא ניתן להגדיר טביעת אצבע"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"הזמן שהוקצב להגדרה של טביעת האצבע פג. יש לנסות שוב."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"הפעולה של טביעת האצבע בוטלה"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"הפעולה של טביעת האצבע בוטלה על ידי המשתמש"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"בוצעו יותר מדי ניסיונות. יש להשתמש בנעילת המסך במקום זאת."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"בוצעו יותר מדי ניסיונות. יש להשתמש בנעילת המסך במקום זאת."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"לא ניתן לעבד את טביעת האצבע. יש לנסות שוב."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"לא נסרקו טביעות אצבע"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"במכשיר הזה אין חיישן טביעות אצבע"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"החיישן מושבת באופן זמני"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"לא ניתן להשתמש בחיישן טביעות האצבע. צריך ליצור קשר עם ספק תיקונים."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"לחצן ההפעלה נלחץ"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"שימוש בטביעת אצבע"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index f4382c4e2505..576a495fbdb9 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋認証を完了しました"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"顔を認証しました"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"顔を認証しました。[確認] を押してください"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"指紋認証ハードウェアは使用できません"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"指紋を設定できません"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋の設定がタイムアウトしました。もう一度お試しください。"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"指紋認証操作がキャンセルされました"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"指紋認証操作がユーザーによりキャンセルされました"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"指紋を処理できません。もう一度お試しください。"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"指紋が登録されていません"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"このデバイスには指紋認証センサーがありません"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"センサーが一時的に無効になっています"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"指紋認証センサーを使用できません。修理業者に調整を依頼してください。"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"電源ボタンが押されました"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"指紋 <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"指紋の使用"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 35f885b913f3..571ae42169c5 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"თითის ანაბეჭდი ავტორიზებულია"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"სახე ავტორიზებულია"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"სახე ავტორიზებულია, დააჭირეთ დადასტურებას"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"თითის ანაბეჭდის ამომცნობი მოწყობილობა მიუწვდომელია"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"თითის ანაბეჭდის დაყენება ვერ ხერხდება"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"თითის ანაბეჭდის დაყენების დრო ამოიწურა. ცადეთ ხელახლა."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"თითის ანაბეჭდის ოპერაცია გაუქმდა"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"თითის ანაბეჭდის ოპერაცია გააუქმა მომხმარებელმა"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"მეტისმეტად ბევრი მცდელობა იყო. სანაცვლოდ გამოიყენეთ ეკრანის დაბლოკვა."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"მეტისმეტად ბევრი მცდელობა იყო. სანაცვლოდ გამოიყენეთ ეკრანის დაბლოკვა."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"თითის ანაბეჭდის დამუშავება შეუძლებელია. ცადეთ ხელახლა."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"თითის ანაბეჭდები არ არის რეგისტრირებული"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ამ მოწყობილობას არ აქვს თითის ანაბეჭდის სენსორი"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"სენსორი დროებით გათიშულია"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"თითის ანაბეჭდის სენსორის გამოყენება შეუძლებელია. ეწვიეთ შეკეთების სერვისის პროვაიდერს."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"ჩართვის ღილაკზე დაეჭირა"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"თითი <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"გამოიყენეთ თითის ანაბეჭდი"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 1e7a73b7c57b..4f50140b34e6 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Саусақ ізі аутентификацияланды"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Бет танылды"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Бет танылды, \"Растау\" түймесін басыңыз"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Саусақ ізін тану жабдығы қолжетімді емес."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Саусақ ізін орнату мүмкін емес."</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Саусақ ізін реттеу уақыты өтіп кетті. Қайталап көріңіз."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Саусақ ізі операциясынан бас тартылды."</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Пайдаланушы саусақ ізі операциясынан бас тартты."</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Тым көп әрекет жасалды. Орнына экран құлпын пайдаланыңыз."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Тым көп әрекет жасалды. Орнына экран құлпын пайдаланыңыз."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Саусақ ізін өңдеу мүмкін емес. Қайталап көріңіз."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ешқандай саусақ іздері тіркелмеді."</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Бұл құрылғыда саусақ ізін оқу сканері жоқ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Датчик уақытша өшірулі."</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Саусақ ізін оқу сканерін пайдалану мүмкін емес. Жөндеу қызметіне барыңыз."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Қуат түймесі басулы."</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>-саусақ"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Саусақ ізін пайдалану"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 37a4f817fd13..8c33299df473 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"បានផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃ"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"បានផ្ទៀងផ្ទាត់មុខ"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"បានផ្ទៀងផ្ទាត់មុខ សូមចុចបញ្ជាក់"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"មិនអាចប្រើហាតវែរស្កេនស្នាមម្រាមដៃបានទេ"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"មិនអាចរៀបចំស្នាមម្រាមដៃបានទេ"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ការរៀបចំស្នាមម្រាមដៃបានអស់ម៉ោង។ សូមព្យាយាមម្ដងទៀត។"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ប្រតិបត្តិការស្នាមម្រាមដៃត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ព្យាយាមច្រើនដងពេក។ សូមប្រើការចាក់សោអេក្រង់ជំនួសវិញ។"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ព្យាយាមច្រើនដងពេក។ សូមប្រើការចាក់សោអេក្រង់ជំនួសវិញ។"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្ដងទៀត។"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"មិនមានការថតបញ្ចូលស្នាមម្រាមដៃទេ"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ឧបករណ៍នេះមិនមានឧបករណ៍ចាប់ស្នាមម្រាមដៃទេ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"បានបិទសេនស័រជាបណ្តោះអាសន្ន"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"មិនអាចប្រើសេនស័រចាប់ស្នាមម្រាមដៃបានទេ។ សូមទាក់ទងក្រុមហ៊ុនផ្ដល់ការជួសជុល។"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"បានចុចប៊ូតុងថាមពល"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ម្រាមដៃទី <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ប្រើស្នាមម្រាមដៃ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index db4bf180704a..e106f1692a1f 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆಟಪ್ ಮಾಡುವ ಅವಧಿ ಮುಗಿದಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ಬಳಕೆದಾರರು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಿದ್ದಾರೆ"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಬದಲಾಗಿ ಸ್ಕ್ರೀನ್ಲಾಕ್ ಬಳಸಿ."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಬದಲಾಗಿ ಪರದೆಲಾಕ್ ಬಳಸಿ."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ಯಾವುದೇ ಫಿಂಗರ್ಪ್ರಿಂಟ್ಗಳನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ಈ ಸಾಧನವು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಹೊಂದಿಲ್ಲ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ಸೆನ್ಸರ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಬಳಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ರಿಪೇರಿ ಮಾಡುವವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"ಪವರ್ ಬಟನ್ ಒತ್ತಲಾಗಿದೆ"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಬಳಸಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index e654eb2030f0..ff480c5428b4 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"지문이 인증됨"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"얼굴이 인증되었습니다"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"얼굴이 인증되었습니다. 확인을 누르세요"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"지문 인식 하드웨어를 사용할 수 없습니다."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"지문을 설정할 수 없음"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"지문 설정 시간이 초과되었습니다. 다시 시도해 주세요."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"지문 인식 작업이 취소되었습니다."</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"사용자가 지문 인식 작업을 취소했습니다."</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"시도 횟수가 너무 많습니다. 화면 잠금을 대신 사용하세요."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"시도 횟수가 너무 많습니다. 화면 잠금을 대신 사용하세요."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"지문을 처리할 수 없습니다. 다시 시도해 주세요."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"등록된 지문이 없습니다."</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"기기에 지문 센서가 없습니다."</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"센서가 일시적으로 사용 중지되었습니다."</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"지문 센서를 사용할 수 없습니다. 수리업체를 방문하세요."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"전원 버튼을 눌렀습니다."</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"손가락 <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"지문 사용"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 39ecc0260d9c..e44689d839cc 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Манжа изи текшерилди"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Жүздүн аныктыгы текшерилди"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Манжа издеринин сканери жеткиликтүү эмес"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Манжа изи жөндөлбөй жатат"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Манжа изин коюу убакыты бүтүп калды. Кайра аракет кылыңыз."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Манжа изи менен аныктыгын текшерүү жокко чыгарылды"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Манжа изи менен аныктыгын текшерүүнү колдонуучу жокко чыгарды"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Өтө көп жолу аракет кылдыңыз. Экранды кулпулоо функциясын колдонуңуз."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Өтө көп жолу аракет кылдыңыз. Экранды кулпулоо функциясын колдонуңуз."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Манжа изи иштетилген жок. Кайра аракет кылыңыз."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Бир да манжа изи катталган эмес"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Бул түзмөктө манжа изинин сенсору жок"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сенсор убактылуу өчүрүлгөн"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Манжа изинин сенсорун колдонууга болбойт. Тейлөө кызматына кайрылыңыз."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Кубат баскычы басылды"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>-манжа"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Манжа изин колдонуу"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 48d62d614976..1f6c1a1594a9 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ພິສູດຢືນຢັນລາຍນິ້ວມືແລ້ວ"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ, ກະລຸນາກົດຢືນຢັນ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ຮາດແວລາຍນິ້ວມືບໍ່ມີໃຫ້ໃຊ້"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ບໍ່ສາມາດຕັ້ງຄ່າລາຍນິ້ວມືໄດ້"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ໝົດເວລາຕັ້ງຄ່າລາຍນິ້ວມື. ກະລຸນາລອງໃໝ່."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ຍົກເລີກການເຮັດວຽກຂອງລາຍນິ້ວມືແລ້ວ"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ຜູ້ໃຊ້ໄດ້ຍົກເລີກການເຮັດວຽກຂອງລາຍນິ້ວມືແລ້ວ"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ກະລຸນາໃຊ້ການລອກໜ້າຈໍແທນ."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ກະລຸນາໃຊ້ການລອກໜ້າຈໍແທນ."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ບໍ່ສາມາດປະມວນຜົນລາຍນິ້ວມືໄດ້. ກະລຸນາລອງໃໝ່."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ບໍ່ມີການລົງທະບຽນລາຍນິ້ວມື"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ອຸປະກອນນີ້ບໍ່ມີເຊັນເຊີລາຍນິ້ວມື"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ປິດການເຮັດວຽກຂອງເຊັນເຊີໄວ້ຊົ່ຄາວແລ້ວ"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ບໍ່ສາມາດໃຊ້ເຊັນເຊີລາຍນິ້ວມືໄດ້. ກະລຸນາໄປຫາຜູ້ໃຫ້ບໍລິການສ້ອມແປງ."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"ກົດປຸ່ມເປີດປິດແລ້ວ"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ນີ້ວມື <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ໃຊ້ລາຍນິ້ວມື"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 38aa52a17b3e..0196351bacb4 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Piršto antspaudas autentifikuotas"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Veidas autentifikuotas"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Veidas autentifikuotas, paspauskite patvirtinimo mygtuką"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Piršto antspaudo aparatinė įranga nepasiekiama"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nepavyko nustatyti kontrolinio kodo"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Baigėsi piršto atspaudo sąrankos skirtasis laikas. Bandykite dar kartą."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Piršto antspaudo operacija atšaukta"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Piršto antspaudo operaciją atšaukė naudotojas"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Per daug bandymų. Naudokite ekrano užraktą."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Per daug bandymų. Naudokite ekrano užraktą."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nepavyko apdoroti kontrolinio kodo. Bandykite dar kartą."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Neužregistruota jokių pirštų atspaudų"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Šiame įrenginyje nėra piršto antspaudo jutiklio"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Jutiklis laikinai išjungtas"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Negalima naudoti piršto atspaudo jutiklio. Apsilankykite pas taisymo paslaugos teikėją."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Paspaustas maitinimo mygtukas"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> pirštas"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Naudoti kontrolinį kodą"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 165eccde23a4..46aae3f62458 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Pirksta nospiedums tika autentificēts."</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Seja autentificēta"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Seja ir autentificēta. Nospiediet pogu Apstiprināt."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Pirksta nospieduma aparatūra nav pieejama."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nevar iestatīt pirksta nospiedumu"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Iestatot pirksta nospiedumu, iestājās noildze. Mēģiniet vēlreiz."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Nospieduma darbība neizdevās."</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Lietotājs atcēla pirksta nospieduma darbību."</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Pārāk daudz mēģinājumu. Izmantojiet ekrāna bloķēšanu."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Pārāk daudz mēģinājumu. Izmantojiet ekrāna bloķēšanu."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nevar apstrādāt pirksta nospiedumu. Mēģiniet vēlreiz."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nav reģistrēts neviens pirksta nospiedums."</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Šajā ierīcē nav pirksta nospieduma sensora."</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensors ir īslaicīgi atspējots."</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Nevar izmantot pirksta nospieduma sensoru. Sazinieties ar remonta pakalpojumu sniedzēju."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Tika nospiesta barošanas poga"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. pirksts"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Pirksta nospieduma izmantošana"</string> @@ -1302,12 +1296,12 @@ <string name="new_app_action" msgid="547772182913269801">"Atvērt <xliff:g id="NEW_APP">%1$s</xliff:g>"</string> <string name="new_app_description" msgid="1958903080400806644">"Lietotne <xliff:g id="OLD_APP">%1$s</xliff:g> tiks aizvērta, neko nesaglabājot"</string> <string name="dump_heap_notification" msgid="5316644945404825032">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu."</string> - <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> kaudzes izraksts ir gatavs"</string> + <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> grēdas izraksts ir gatavs"</string> <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Apkopots kaudzes izraksts. Pieskarieties, lai kopīgotu."</string> - <string name="dump_heap_title" msgid="4367128917229233901">"Vai kopīgot kaudzes izrakstu?"</string> - <string name="dump_heap_text" msgid="1692649033835719336">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika vākts kaudzes izraksts, ko varat kopīgot ar procesa izstrādātāju. Ņemiet vērā: kaudzes izrakstā var būt ietverta jūsu personas informācija, kurai var piekļūt lietojumprogramma."</string> + <string name="dump_heap_title" msgid="4367128917229233901">"Vai kopīgot grēdas izrakstu?"</string> + <string name="dump_heap_text" msgid="1692649033835719336">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika vākts grēdas izraksts, ko varat kopīgot ar procesa izstrādātāju. Ņemiet vērā: grēdas izrakstā var būt ietverta jūsu personas informācija, kurai var piekļūt lietojumprogramma."</string> <string name="dump_heap_system_text" msgid="6805155514925350849">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika vākts kaudzes izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo kaudzes izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string> - <string name="dump_heap_ready_text" msgid="5849618132123045516">"Ir pieejams procesa <xliff:g id="PROC">%1$s</xliff:g> kaudzes izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo kaudzes izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string> + <string name="dump_heap_ready_text" msgid="5849618132123045516">"Ir pieejams procesa <xliff:g id="PROC">%1$s</xliff:g> grēdas izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo grēdas izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string> <string name="sendText" msgid="493003724401350724">"Izvēlieties darbību tekstam"</string> <string name="volume_ringtone" msgid="134784084629229029">"Zvanītāja skaļums"</string> <string name="volume_music" msgid="7727274216734955095">"Multivides skaļums"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index aa5645a30d4a..1c85e473fdb9 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатокот е проверен"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е проверено"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е проверено, притиснете го копчето „Потврди“"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Не е достапен хардвер за отпечаток"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не може да се постави отпечаток"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Времето за поставување отпечаток истече. Обидете се повторно."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Автентикацијата со отпечаток е откажана"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Корисникот ја откажа автентикацијата со отпечаток"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Премногу обиди. Користете заклучување екран."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Премногу обиди. Користете заклучување екран."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Не може да се обработи отпечатокот од прст. Обидете се повторно."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Не се регистрирани отпечатоци"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Уредов нема сензор за отпечатоци"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сензорот е привремено оневозможен"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Не може да се користи сензорот за отпечатоци. Однесете го уредот на поправка."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Притиснато е копчето за вклучување"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Користи отпечаток"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 0ef12814e3c9..9917448c1e0d 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിച്ചു"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ഫിംഗർപ്രിന്റ് ഹാർഡ്വെയർ ലഭ്യമല്ല"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ഫിംഗർപ്രിന്റ് സജ്ജീകരിക്കാനാകില്ല"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ഫിംഗർപ്രിന്റ് സജ്ജീകരണം ടൈംഔട്ടായി. വീണ്ടും ശ്രമിക്കുക."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ഫിംഗർപ്രിന്റിന്റെ പ്രവർത്തനം ഉപയോക്താവ് റദ്ദാക്കി"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"നിരവധി ശ്രമങ്ങൾ. പകരം സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"നിരവധി ശ്രമങ്ങൾ. പകരം സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ഫിംഗർപ്രിന്റ് പ്രോസസ് ചെയ്യാനാകില്ല. വീണ്ടും ശ്രമിക്കുക."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ഫിംഗർപ്രിന്റുകളൊന്നും എൻറോൾ ചെയ്തിട്ടില്ല"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസർ ഇല്ല"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"സെൻസർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കി"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ഫിംഗർപ്രിന്റ് സെൻസർ ഉപയോഗിക്കാനാകില്ല. റിപ്പയർ കേന്ദ്രം സന്ദർശിക്കുക."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"പവർ ബട്ടൺ അമർത്തി"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ഫിംഗർ <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index df4148ef296f..48d926ccf4e2 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Хурууны хээг нотолсон"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Царайг баталгаажууллаа"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Хурууны хээ таних техник хангамж боломжгүй"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Хурууны хээ тохируулах боломжгүй"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Хурууны хээний тохируулга завсарласан. Дахин оролдоно уу."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Хурууны хээний үйл ажиллагааг цуцалсан"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Хурууны хээний үйл ажиллагааг хэрэглэгч цуцалсан"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Хэт олон удаа оролдлоо. Оронд нь дэлгэцийн түгжээ ашиглана уу."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Хэт олон удаа оролдлоо. Оронд нь дэлгэцийн түгжээ ашиглана уу."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Хурууны хээг боловсруулах боломжгүй. Дахин оролдоно уу."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ямар ч хурууны хээ бүртгүүлээгүй"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Энэ төхөөрөмжид хурууны хээ мэдрэгч алга"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Мэдрэгчийг түр зуур идэвхгүй болгосон"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Хурууны хээ мэдрэгчийг ашиглах боломжгүй. Засварын үйлчилгээ үзүүлэгчид зочилно уу."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Асаах/Унтраах товчийг дарсан"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Хурууны хээ <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Хурууны хээ ашиглах"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 09c2ac3b2c48..8fb6b0f01960 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -453,7 +453,7 @@ <string name="permlab_getPackageSize" msgid="375391550792886641">"अॅप संचयन स्थान मोजा"</string> <string name="permdesc_getPackageSize" msgid="742743530909966782">"अॅप ला त्याचा कोड, डेटा आणि कॅशे आकार पुनर्प्राप्त करण्यासाठी अनुमती देते"</string> <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्टीम सेटिंग्ज सुधारित करा"</string> - <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपल्या सिस्टीमचे कॉंफिगरेशन दूषित करू शकतात."</string> + <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अॅपला अनुमती देते. दुर्भावनापूर्ण अॅप्स तुमच्या सिस्टीमचे कॉन्फिगरेशन दूषित करू शकतात."</string> <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"सुरूवातीस चालवा"</string> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः सुरू करण्यास अनुमती देते. यामुळे टॅबलेट सुरू करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर टॅबलेटला धीमे करण्यास अॅप ला अनुमती देते."</string> <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"सिस्टम बूट होणे संपल्यावर ॲपला स्वतः सुरू होण्याची अनुमती देते. यामुळे तुमच्या Android TV डिव्हाइसला सुरू होण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर डिव्हाइसलाच धीमे करण्याची अनुमती ॲपला देते."</string> @@ -582,9 +582,9 @@ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"फक्त तुमच्या Android TV डिव्हाइसलाच नाही, तर मल्टिकास्ट पत्ते वापरून एका वाय-फाय नेटवर्कवरील सर्व डिव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी ॲपला अनुमती देते. हे मल्टिकास्ट मोड नसताना वापरल्या जाणाऱ्या ऊर्जेपेक्षा अधिक उर्जा वापरते."</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या फोनवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string> <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"ब्लूटूथ सेटिंग्ज अॅक्सेस करा"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"स्थानिक ब्लूटूथ टॅबलेट कॉंफिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> - <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"तुमच्या Android TV डिव्हाइसवर ब्लूटूथ कॉंफिगर करण्याकरिता आणि पेअर केलेली आणि रीमोट डिव्हाइस शोधण्यासाठी ॲपला अनुमती देते."</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"स्थानिक ब्लूटूथ फोन कॉंफिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"स्थानिक ब्लूटूथ टॅबलेट कॉन्फिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"तुमच्या Android TV डिव्हाइसवर ब्लूटूथ कॉन्फिगर करण्याकरिता आणि पेअर केलेली आणि रीमोट डिव्हाइस शोधण्यासाठी ॲपला अनुमती देते."</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"स्थानिक ब्लूटूथ फोन कॉन्फिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX कनेक्ट करा आणि त्यावरून डिस्कनेक्ट करा"</string> <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या कोणत्याही WiMAX नेटवर्क विषयीची माहिती निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX स्थिती बदला"</string> @@ -592,9 +592,9 @@ <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"ॲपला तुमच्या Android TV डिव्हाइसशी कनेक्ट करण्याची आणि तुमचे Android TV डिव्हाइस WiMAX नेटवर्कवरून डिस्कनेक्ट करण्याची परवानगी देते."</string> <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"WiMAX नेटवर्कवर फोन कनेक्ट करण्यास आणि त्यावरून फोन डिस्कनेक्ट करण्यास अॅप ला अनुमती देते."</string> <string name="permlab_bluetooth" msgid="586333280736937209">"ब्लूटूथ डीव्हाइससह जोडा"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"टॅबलेटवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> - <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV डिव्हाइसवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन तयार करण्यासाठी आणि स्वीकारण्यासाठी, ॲपला अनुमती देते."</string> - <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"फोनवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"टॅबलेटवर ब्लूटूथचे कॉन्फिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डिव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅपला अनुमती देते."</string> + <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV डिव्हाइसवर ब्लूटूथ चे कॉन्फिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डिव्हाइससह कनेक्शन तयार करण्यासाठी आणि स्वीकारण्यासाठी, अॅपला अनुमती देते."</string> + <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"फोनवर ब्लूटूथचे कॉन्फिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डिव्हाइससह कनेक्शन इंस्टॉल करण्यासाठी आणि स्वीकारण्यासाठी, अॅपला अनुमती देते."</string> <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"जवळपासची ब्लूटूथ डिव्हाइस शोधा आणि ती पेअर करा"</string> <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"ॲपला जवळपासची ब्लूटूथ डिव्हाइस शोधण्यासाठी आणि ती पेअर करण्यासाठी अनुमती देते"</string> <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"पेअर केलेल्या ब्लूटूथ डिव्हाइसशी कनेक्ट करा"</string> @@ -665,25 +665,19 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string> <string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरा ऑथेंटिकेशन केलेला आहे"</string> - <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कंफर्म प्रेस करा"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कन्फर्म प्रेस करा"</string> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"फिंगरप्रिंट हार्डवेअर उपलब्ध नाही"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फिंगरप्रिंट सेट करता आली नाही"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"फिंगरप्रिंट सेट करण्याची वेळ संपली आहे. पुन्हा प्रयत्न करा."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"फिंगरप्रिंट ऑपरेशन रद्द करण्यात आले आहे"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले आहे"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"खूप जास्त प्रयत्न. त्याऐवजी स्क्रीन लॉक वापरा."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"खूप जास्त प्रयत्न. त्याऐवजी स्क्रीन लॉक वापरा."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"फिंगरप्रिंटवर प्रक्रिया करू शकत नाही. पुन्हा प्रयत्न करा."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"कोणत्याही फिंगरप्रिंटची नोंदणी करण्यात आली नाही"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"या डिव्हाइसवर फिंगरप्रिंट सेन्सर नाही"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"सेन्सर तात्पुरते बंद करण्यात आले आहे"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"फिंगरप्रिंट सेन्सर वापरू शकत नाही. दुरुस्तीच्या सेवा पुरवठादाराला भेट द्या."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"पॉवर बटण दाबले"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"फिंगरप्रिंट वापरा"</string> @@ -802,7 +796,7 @@ <string name="permlab_bindDreamService" msgid="4776175992848982706">"स्वप्न सेवेवर प्रतिबद्ध करा"</string> <string name="permdesc_bindDreamService" msgid="9129615743300572973">"होल्डरला स्वप्नसेवेच्या शीर्ष-स्तराच्या इंटरफेसशी प्रतिबद्ध करण्यास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यक नसते."</string> <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"वाहकाद्वारे-प्रदान केलेल्या कॉन्फिगरेशन अॅपची विनंती करा"</string> - <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"होल्डरला वाहकद्वारे-प्रदान केलेल्या कॉंफिगरेशन अॅपची विनंती करण्याची अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string> + <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"होल्डरला वाहकाद्वारे दिलेल्या कॉन्फिगरेशन अॅपची विनंती करण्याची अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string> <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"नेटवर्क स्थितींवरील निरीक्षणांसाठी ऐका"</string> <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"अनु्प्रयोगाला नेटवर्क स्थितींवरील निरीक्षणे ऐकण्यासाठी अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string> <string name="permlab_setInputCalibration" msgid="932069700285223434">"इनपुट डिव्हाइस कॅलिब्रेशन बदला"</string> @@ -818,7 +812,7 @@ <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"वाहक सेवांवर प्रतिबद्ध करा"</string> <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"वाहक सेवांवर प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्य ॲप्ससाठी कधीही आवश्यकता नसावी."</string> <string name="permlab_access_notification_policy" msgid="5524112842876975537">"व्यत्यय आणू नका अॅक्सेस करा"</string> - <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका कॉंफिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी ॲपला अनुमती देते."</string> + <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"व्यत्यय आणू नका हे कॉन्फिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी अॅपला अनुमती देते."</string> <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"व्ह्यू परवानगी वापर सुरू करा"</string> <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"धारकास अॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यकता नसते."</string> <string name="permlab_startReviewPermissionDecisions" msgid="8690578688476599284">"परवानगीशी संबंधित निर्णय पाहणे सुरू करा"</string> @@ -1425,8 +1419,8 @@ <string name="select_input_method" msgid="3971267998568587025">"इनपुट पद्धत निवडा"</string> <string name="show_ime" msgid="6406112007347443383">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string> <string name="hardware" msgid="3611039921284836033">"ऑन-स्क्रीन कीबोर्ड वापरा"</string> - <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कॉंफिगर करा"</string> - <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"वास्तविक कीबोर्ड कॉंफिगर करा"</string> + <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कॉन्फिगर करा"</string> + <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"वास्तविक कीबोर्ड कॉन्फिगर करा"</string> <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string> <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> @@ -2377,12 +2371,12 @@ <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"बॅटरी सेव्हर सुरू असल्यामुळे Dual Screen उपलब्ध नाही. तुम्ही हे सेटिंग्ज मध्ये बंद करू शकता."</string> <string name="device_state_notification_settings_button" msgid="691937505741872749">"सेटिंग्ज वर जा"</string> <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"बंद करा"</string> - <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कॉंफिगर केले आहे"</string> + <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कॉन्फिगर केले आहे"</string> <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"कीबोर्ड लेआउट <xliff:g id="LAYOUT_1">%s</xliff:g> वर सेट केला. बदलण्यासाठी टॅप करा."</string> <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"कीबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> वर सेट केला. बदलण्यासाठी टॅप करा."</string> <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"कीबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> वर सेट केला. बदलण्यासाठी टॅप करा."</string> <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"कीबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> वर सेट करा… बदलण्यासाठी टॅप करा."</string> - <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"वास्तविक कीबोर्ड कॉंफिगर केला"</string> + <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"वास्तविक कीबोर्ड कॉन्फिगर केला"</string> <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"कीबोर्ड पाहण्यासाठी टॅप करा"</string> <string name="profile_label_private" msgid="6463418670715290696">"खाजगी"</string> <string name="profile_label_clone" msgid="769106052210954285">"क्लोन"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 5018aa8fddc7..7112ed389f99 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Cap jari disahkan"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah disahkan"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah disahkan, sila tekan sahkan"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Perkakasan cap jari tidak tersedia"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Tidak dapat menyediakan cap jari"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Persediaan cap jari telah tamat masa. Cuba lagi."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Pengendalian cap jari dibatalkan"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Pengendalian cap jari dibatalkan oleh pengguna"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Terlalu banyak percubaan. Gunakan kunci skrin."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Terlalu banyak percubaan. Gunakan kunci skrin."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Tidak dapat memproses cap jari. Cuba lagi."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Tiada cap jari didaftarkan"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Peranti ini tiada penderia cap jari"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Penderia dilumpuhkan untuk sementara"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Tidak dapat menggunakan penderia cap jari. Lawati penyedia pembaikan."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Butang kuasa ditekan"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Gunakan cap jari"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 97121dd39f74..2c3e7b743afe 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"လက်ဗွေစက် မရနိုင်ပါ"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"လက်ဗွေကို စနစ်ထည့်သွင်း၍ မရပါ"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"လက်ဗွေစနစ်ထည့်သွင်းချိန် ကုန်သွားပါပြီ။ ထပ်စမ်းကြည့်ပါ။"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"လက်ဗွေဖြင့် လုပ်ဆောင်ခြင်းကို ပယ်ဖျက်လိုက်သည်"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"လက်ဗွေဖြင့် လုပ်ဆောင်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်လိုက်သည်"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ကြိုးပမ်းမှုအကြိမ်ရေ များလွန်းသည်။ ဖန်သားပြင်လော့ခ်ချခြင်းကို အစားထိုးသုံးပါ။"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ကြိုးပမ်းမှုအကြိမ်ရေ များလွန်းသည်။ ဖန်သားပြင်လော့ခ်ချခြင်းကို အစားထိုးသုံးပါ။"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"လက်ဗွေကို လုပ်ဆောင်နိုင်ခြင်းမရှိပါ။ ထပ်စမ်းကြည့်ပါ။"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"မည်သည့်လက်ဗွေကိုမျှ ထည့်သွင်းမထားပါ"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ဤစက်ပစ္စည်းတွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"အာရုံခံကိရိယာကို ယာယီပိတ်ထားသည်"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"လက်ဗွေ အာရုံခံကိရိယာကို သုံး၍မရပါ။ ပြုပြင်ရေး ဝန်ဆောင်မှုပေးသူထံသို့ သွားပါ။"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"ဖွင့်ပိတ်ခလုတ် နှိပ်ထားသည်"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"လက်ဗွေ သုံးခြင်း"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index ca6df0e02195..541e1b540570 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrykket er godkjent"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet er autentisert"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet er autentisert. Trykk på Bekreft"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Maskinvare for fingeravtrykk er ikke tilgjengelig"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan ikke konfigurere fingeravtrykk"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Konfigureringen av fingeravtrykk er tidsavbrutt. Prøv på nytt."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingeravtrykk-operasjonen ble avbrutt"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingeravtrykk-operasjonen ble avbrutt av brukeren"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"For mange forsøk. Bruk skjermlås i stedet."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"For mange forsøk. Bruk skjermlås i stedet."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Kan ikke behandle fingeravtrykket. Prøv på nytt."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ingen fingeravtrykk er registrert"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Denne enheten har ikke fingeravtrykkssensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensoren er midlertidig slått av"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Kan ikke bruke fingeravtrykkssensoren. Gå til en reparasjonsleverandør."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Av/på-knappen ble trykket"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Bruk fingeravtrykk"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index fd31ac4b6dbe..8c951e0a9dab 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"अनुहार प्रमाणीकरण गरियो"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"फिंगरप्रिन्ट हार्डवेयर उपलब्ध छैन"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फिंगरप्रिन्ट सेटअप गर्न सकिएन"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"फिंगरप्रिन्ट सेट अप गर्ने समय सकियो। फेरि प्रयास गर्नुहोस्।"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गरियो"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"निकै धेरै पटक प्रयास गरिसकिएको छ। बरु स्क्रिन लक प्रयोग गर्नुहोस्।"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"निकै धेरै पटक प्रयास गरिसकिएको छ। बरु स्क्रिन लक प्रयोग गर्नुहोस्।"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"फिंगरप्रिन्ट पहिचान गर्ने प्रक्रिया अघि बढाउन सकिएन। फेरि प्रयास गर्नुहोस्।"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"कुनै पनि फिंगरप्रिन्ट दर्ता गरिएको छैन"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"यो डिभाइसमा कुनै फिंगरप्रिन्ट सेन्सर छैन"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"केही समयका लागि सेन्सर अफ गरियो"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"फिंगरप्रिन्ट सेन्सर प्रयोग गर्न सकिएन। फिंगरप्रिन्ट सेन्सर मर्मत गर्ने सेवा प्रदायक कम्पनीमा सम्पर्क गर्नुहोस्।"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"पावर बटन थिचियो"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"औंला <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index e68947e8ed42..bbcc2aa88440 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk geverifieerd"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gezicht geverifieerd"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gezicht geverifieerd. Druk op Bevestigen."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware voor vingerafdruk niet beschikbaar"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan vingerafdruk niet instellen"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Time-out bij instellen van vingerafdruk. Probeer het opnieuw."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Vingerafdrukbewerking geannuleerd"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Vingerafdrukverificatie geannuleerd door gebruiker"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Te veel pogingen. Gebruik in plaats daarvan de schermvergrendeling."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Te veel pogingen. Gebruik in plaats daarvan de schermvergrendeling."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Geen vingerafdrukken geregistreerd"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Dit apparaat heeft geen vingerafdruksensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor tijdelijk uitgezet"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Kan vingerafdruksensor niet gebruiken. Ga naar een reparateur."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Aan/uit-knop ingedrukt"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Vingerafdruk gebruiken"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 45b49d373588..d8bcbd10f5f5 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ଟିପଚିହ୍ନ ପ୍ରମାଣିତ ହେଲା"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ଟିପଚିହ୍ନକୁ ସେଟ୍ ଅପ୍ କରାଯାଇପାରିବ ନାହିଁ"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ଫିଙ୍ଗରପ୍ରିଣ୍ଟ ସେଟଅପର ସମୟସୀମା ସମାପ୍ତ ହୋଇଯାଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ଟିପଚିହ୍ନ ଅପରେସନକୁ ବାତିଲ କରାଯାଇଛି"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ୟୁଜରଙ୍କ ଦ୍ୱାରା ଟିପଚିହ୍ନ ଅପରେସନକୁ ବାତିଲ କରାଯାଇଛି"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ଅନେକଗୁଡ଼ିଏ ପ୍ରଚେଷ୍ଟା। ଏହା ପରିବର୍ତ୍ତେ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରନ୍ତୁ।"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ଅନେକଗୁଡ଼ିଏ ପ୍ରଚେଷ୍ଟା। ଏହା ପରିବର୍ତ୍ତେ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରନ୍ତୁ।"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ଟିପଚିହ୍ନକୁ ପ୍ରକ୍ରିୟାନ୍ୱିତ କରାଯାଇପାରିବ ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"କୌଣସି ଟିପଚିହ୍ନକୁ ପଞ୍ଜିକରଣ କରାଯାଇନାହିଁ"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ଏହି ଡିଭାଇସ୍ରେ ଟିପଚିହ୍ନ ସେନସର୍ ନାହିଁ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ସେନ୍ସରକୁ ଅସ୍ଥାୟୀ ଭାବେ ଅକ୍ଷମ କରାଯାଇଛି"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଏକ ମରାମତି କେନ୍ଦ୍ରକୁ ଭିଜିଟ୍ କରନ୍ତୁ।"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"ପାୱାର ବଟନ ଦବାଯାଇଛି"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ଆଙ୍ଗୁଠି <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 2abe228d6733..b762d6621d92 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਸਮਾਂ ਸਮਾਪਤ ਹੋਇਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਬੰਧੀ ਕਾਰਵਾਈ ਰੱਦ ਕੀਤੀ ਗਈ"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਬੰਧੀ ਕਾਰਵਾਈ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤੀ ਗਈ"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸਦੀ ਬਜਾਏ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ।"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸਦੀ ਬਜਾਏ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ।"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ਫਿੰਗਰਪ੍ਰਿੰਟ \'ਤੇ ਪ੍ਰਕਿਰਿਆ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ਕੋਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਰਜ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨਹੀਂ ਹੈ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"ਸੈਂਸਰ ਕੁਝ ਸਮੇਂ ਲਈ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਮੁਰੰਮਤ ਕਰਨ ਵਾਲੇ ਪ੍ਰਦਾਨਕ ਕੋਲ ਜਾਓ।"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"\'ਪਾਵਰ\' ਬਟਨ ਦਬਾਇਆ ਗਿਆ"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 06bff2aaad55..5f3e683d8053 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Uwierzytelniono odciskiem palca"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Twarz rozpoznana"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Twarz rozpoznana, kliknij Potwierdź"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Czytnik linii papilarnych nie jest dostępny"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nie można skonfigurować odcisku palca"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Upłynął limit czasu konfiguracji odcisku palca. Spróbuj ponownie."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Odczyt odcisku palca został anulowany"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Odczyt odcisku palca został anulowany przez użytkownika"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Zbyt wiele prób. Użyj blokady ekranu."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Zbyt wiele prób. Użyj blokady ekranu."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nie udało się przetworzyć odcisku palca. Spróbuj ponownie."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nie zarejestrowano odcisków palców"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"To urządzenie nie jest wyposażone w czytnik linii papilarnych"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Czujnik tymczasowo wyłączony"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Nie można użyć czytnika linii papilarnych. Odwiedź serwis."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Naciśnięto przycisk zasilania"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Odcisk palca <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Używaj odcisku palca"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 43cdfa205162..9887bf6d5db6 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware de impressão digital indisponível"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não foi possível configurar a impressão digital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Tempo de configuração esgotado. Tente de novo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operação de impressão digital cancelada"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operação de impressão digital cancelada pelo usuário"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Excesso de tentativas. Use o bloqueio de tela."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Excesso de tentativas. Use o bloqueio de tela."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Não foi possível processar a impressão digital. Tente de novo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nenhuma impressão digital registrada"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Este dispositivo não tem um sensor de impressão digital"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor desativado temporariamente"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Não foi possível usar o sensor de impressão digital. Entre em contato com uma assistência técnica."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Botão liga/desliga pressionado"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar impressão digital"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 74df1872a970..9903acb3a4ab 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"A impressão digital foi autenticada."</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado."</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado. Prima Confirmar."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware de impressão digital não disponível"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não é possível configurar a impressão digital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"A configuração da impressão digital expirou. Tente novamente."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operação de impressão digital cancelada"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operação de impressão digital cancelada pelo utilizador"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Demasiadas tentativas. Em alternativa, use o bloqueio de ecrã."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiadas tentativas. Em alternativa, use o bloqueio de ecrã."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Não é possível processar a impressão digital. Tente novamente."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nenhuma impressão digital configurada"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Este dispositivo não tem sensor de impressões digitais."</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor temporariamente desativado"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Não é possível usar o sensor de impressões digitais. Visite um fornecedor de serviços de reparação."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Botão ligar/desligar premido"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar a impressão digital"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 43cdfa205162..9887bf6d5db6 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware de impressão digital indisponível"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não foi possível configurar a impressão digital"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Tempo de configuração esgotado. Tente de novo."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operação de impressão digital cancelada"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operação de impressão digital cancelada pelo usuário"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Excesso de tentativas. Use o bloqueio de tela."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Excesso de tentativas. Use o bloqueio de tela."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Não foi possível processar a impressão digital. Tente de novo."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nenhuma impressão digital registrada"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Este dispositivo não tem um sensor de impressão digital"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensor desativado temporariamente"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Não foi possível usar o sensor de impressão digital. Entre em contato com uma assistência técnica."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Botão liga/desliga pressionado"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar impressão digital"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 67ade37b2756..73d92fbe6fd6 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Amprentă autentificată"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Chip autentificat"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Chip autentificat, apasă pe Confirmă"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardware-ul pentru amprentă nu este disponibil"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nu se poate configura amprenta"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Configurarea amprentei a expirat. Încearcă din nou."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operațiunea privind amprenta a fost anulată"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Operațiunea privind amprenta a fost anulată de utilizator"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Prea multe încercări. Folosește blocarea ecranului."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Prea multe încercări. Folosește blocarea ecranului."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Nu putem procesa amprenta. Încearcă din nou."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nu au fost înregistrate amprente"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Acest dispozitiv nu are senzor de amprentă"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor dezactivat temporar"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Nu se poate folosi senzorul de amprentă. Vizitează un furnizor de servicii de reparații."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"A fost apăsat butonul de pornire"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Degetul <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Folosește amprenta"</string> @@ -1172,7 +1166,7 @@ <string name="Midnight" msgid="8176019203622191377">"Miezul nopții"</string> <string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> - <string name="selectAll" msgid="1532369154488982046">"Selectează-le pe toate"</string> + <string name="selectAll" msgid="1532369154488982046">"Selectează tot"</string> <string name="cut" msgid="2561199725874745819">"Decupează"</string> <string name="copy" msgid="5472512047143665218">"Copiază"</string> <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"Eroare la copierea în clipboard"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 7e8df9ff23ff..5b434a56f8ec 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечаток пальца проверен"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицо распознано"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицо распознано, нажмите кнопку \"Подтвердить\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Сканер отпечатков пальцев недоступен."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не удалось сохранить отпечаток."</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Время настройки отпечатка пальца истекло. Повторите попытку."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Операция с отпечатком пальца отменена."</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Пользователь отменил операцию с отпечатком пальца."</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Слишком много попыток. Используйте другой способ разблокировки экрана."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Слишком много попыток. Используйте другой способ разблокировки экрана."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Не удалось распознать отпечаток пальца. Повторите попытку."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Отпечатки пальцев не добавлены."</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"На этом устройстве нет сканера отпечатков пальцев"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сканер временно отключен."</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Невозможно использовать сканер отпечатков пальцев. Обратитесь в сервисный центр."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Нажата кнопка питания."</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Отпечаток <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Использовать отпечаток пальца"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index db7fb6d13b94..5a271180499f 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ඇඟිලි සලකුණ සත්යාපනය කරන ලදී"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"මුහුණ සත්යාපනය කරන ලදී"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"මුහුණ සත්යාපනය කරන ලදී, කරුණාකර තහවුරු කරන්න ඔබන්න"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ඇඟිලි සලකුණු දෘඪාංගය ලද නොහැක"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ඇඟිලි සලකුණ පිහිටුවිය නොහැකිය"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"ඇඟිලි සලකුණු පිහිටුවීම කාලය නිමා විය. නැවත උත්සාහ කරන්න."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදි"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"පරිශීලක විසින් ඇඟිලි සලකුණු මෙහෙයුම අවසන් කරන ලදි"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"උත්සාහ ගණන ඉතා වැඩියි. ඒ වෙනුවට තිර අගුල භාවිත කරන්න."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"උත්සාහ ගණන ඉතා වැඩියි. ඒ වෙනුවට තිර අගුල භාවිත කරන්න."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ඇඟිලි සලකුණ සැකසීමට නොහැක. නැවත උත්සාහ කරන්න."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ඇඟිලි සලකුණු ඇතුළත් කර නොමැත"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"මෙම උපාංගයේ ඇඟිලි සලකුණු සංවේදකයක් නොමැත"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"සංවේදකය තාවකාලිකව අබල කර ඇත"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ඇඟිලි සලකුණු සංවේදකය භාවිත කළ නොහැක. අලුත්වැඩියා සැපයුම්කරුවෙකු වෙත පැමිණෙන්න."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"බල බොත්තම ඔබා ඇත"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"ඇඟිලි <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ඇඟිලි සලකුණ භාවිත කරන්න"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index e199235ac19a..16a56d3156f1 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Odtlačok prsta bol overený"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Tvár bola overená"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardvér na odtlačky prstov nie je k dispozícii"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Odtlačok prsta sa nedá nastaviť"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Nastavenie odtlačku prsta vypršalo. Skúste to znova."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Overenie odtlačku prsta zrušil používateľ"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Príliš veľa pokusov. Použite radšej zámku obrazovky."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Príliš veľa pokusov. Použite radšej zámku obrazovky."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Odtlačok prsta sa nedá spracovať. Skúste to znova."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nie sú registrované žiadne odtlačky prstov"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Toto zariadenie nemá senzor odtlačkov prstov"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Senzor je dočasne vypnutý"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Senzor odtlačkov prstov nie je možné používať. Navštívte opravára."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Bol stlačený vypínač"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst: <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Použiť odtlačok prsta"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 305e3903397d..79a275ca7089 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Pristnost prstnega odtisa je preverjena"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Pristnost obraza je potrjena"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Pristnost obraza je preverjena. Pritisnite gumb »Potrdi«."</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Strojna oprema za prstne odtise ni na voljo"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Prstnega odtisa ni mogoče nastaviti."</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Čas za nastavitev prstnega odtisa je potekel. Poskusite znova."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Dejanje s prstnim odtisom je bilo preklicano"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Dejanje s prstnim odtisom je preklical uporabnik"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Preveč poskusov. Odklenite z načinom za zaklepanje zaslona."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Preveč poskusov. Odklenite z zaklepanjem zaslona."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Prstnega odtisa ni mogoče obdelati. Poskusite znova."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Ni prijavljenih prstnih odtisov"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Ta naprava nima tipala prstnih odtisov"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Tipalo je začasno onemogočeno"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Tipala prstnih odtisov ni mogoče uporabiti. Obiščite ponudnika popravil."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Gumb za vklop je pritisnjen."</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Uporaba prstnega odtisa"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index c6fdb8f9440c..fc2e71590b9a 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Gjurma e gishtit u vërtetua"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Fytyra u vërtetua"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Fytyra u vërtetua, shtyp \"Konfirmo\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hardueri i gjurmës së gishtit nuk ofrohet"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nuk mund të konfigurohet gjurma e gishtit"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Konfigurimi i gjurmës së gishtit skadoi. Provo përsëri."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Veprimi i gjurmës së gishtit u anulua"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Veprimi i gjurmës së gishtit u anulua nga përdoruesi"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Shumë përpjekje. Përdor më mirë kyçjen e ekranit."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Shumë përpjekje. Përdor më mirë kyçjen e ekranit."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Gjurma e gishtit nuk mund të përpunohet. Provo përsëri."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Nuk ka asnjë gjurmë gishti të regjistruar"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Kjo pajisje nuk ka sensor të gjurmës së gishtit"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensori është çaktivizuar përkohësisht"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Sensori i gjurmës së gishtit nuk mund të përdoret. Vizito një ofrues të shërbimit të riparimit."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Butoni i energjisë u shtyp"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Përdor gjurmën e gishtit"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 194e48957a02..4f9ce47d4a90 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -667,24 +667,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отисак прста је потврђен"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лице је потврђено"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лице је потврђено. Притисните Потврди"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Хардвер за отисак прста није доступан"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Подешавање отиска прста није успело"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Време за подешавање отиска прста је истекло. Пробајте поново."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Радња са отиском прста је отказана"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Корисник је отказао радњу са отиском прста"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Превише покушаја. Користите закључавање екрана уместо тога."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Превише покушаја. Користите закључавање екрана уместо тога."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Обрађивање отиска прста није успело. Пробајте поново."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Није регистрован ниједан отисак прста"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Овај уређај нема сензор за отисак прста"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сензор је привремено онемогућен"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Не можете да користите сензор за отисак прста. Посетите сервис."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Притиснуто је дугме за укључивање"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Користите отисак прста"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 25109b80a77a..7f0a2014b5f0 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrycket har autentiserats"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet har autentiserats"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet har autentiserats. Tryck på Bekräfta"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Det finns ingen maskinvara för fingeravtryck"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Det gick inte att konfigurera fingeravtryck"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Tiden för fingeravtrycksinställning gick ut. Försök igen."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Fingeravtrycksåtgärden avbröts"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Fingeravtrycksåtgärden avbröts av användaren"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"För många försök. Använd låsskärmen i stället."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"För många försök. Använd låsskärmen i stället."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Det finns inga registrerade fingeravtryck"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Enheten har ingen fingeravtryckssensor"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensorn har tillfälligt inaktiverats"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Det går inte att använda fingeravtryckssensorn. Besök ett reparationsställe."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Av/på-knappen nedtryckt"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Använd ditt fingeravtryck"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 8819f2707593..4d004402a6ba 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Imethibitisha alama ya kidole"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Uso umethibitishwa"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Maunzi ya kutambua alama ya kidole hayapatikani"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Imeshindwa kuweka mipangilio ya alama ya kidole"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Muda wa kuweka alama ya kidole umeisha. Jaribu tena."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Mchakato wa alama ya kidole umeachwa"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Mtumiaji ameacha mchakato wa uthibitishaji wa alama ya kidole"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Umejaribu mara nyingi mno. Badala yake, tumia mbinu ya kufunga skrini."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Umejaribu mara nyingi mno. Badala yake, tumia mbinu ya kufunga skrini."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Imeshindwa kutambua alama ya kidole. Jaribu tena."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Hakuna alama za vidole zilizojumuishwa"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Kifaa hiki hakina kitambua alama ya kidole"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Kitambuzi kimezimwa kwa muda"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Imeshindwa kutumia kitambuzi cha alama ya kidole. Tembelea mtoa huduma za urekebishaji."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Kitufe cha kuwasha au kuzima kimebonyezwa"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Kidole cha <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Tumia alama ya kidole"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 24307fa95389..f962728c8b30 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"கைரேகை அங்கீகரிக்கப்பட்டது"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"முகம் அங்கீகரிக்கப்பட்டது"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"முகம் அங்கீகரிக்கப்பட்டது. ’உறுதிப்படுத்துக’ என்பதை அழுத்துக"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"கைரேகை பாகம் இல்லை"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"கைரேகையை அமைக்க முடியவில்லை"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"கைரேகை அமைவுக்கான நேரம் முடிந்துவிட்டது. மீண்டும் முயலவும்."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"கைரேகைச் செயல்பாடு ரத்துசெய்யப்பட்டது"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"கைரேகைச் செயல்பாடு பயனரால் ரத்துசெய்யப்பட்டது"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"பலமுறை முயன்றுவிட்டீர்கள். இதற்குப் பதிலாகத் திரைப்பூட்டைப் பயன்படுத்தவும்."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"பலமுறை முயன்றுவிட்டீர்கள். இதற்குப் பதிலாகத் திரைப்பூட்டைப் பயன்படுத்தவும்."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"கைரேகைகள் எதுவும் பதிவுசெய்யப்படவில்லை"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"இந்தச் சாதனத்தில் கைரேகை சென்சார் இல்லை"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"சென்சார் தற்காலிகமாக முடக்கப்பட்டுள்ளது"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"கைரேகை சென்சாரைப் பயன்படுத்த முடியவில்லை. பழுதுபார்ப்புச் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"பவர் பட்டன் அழுத்தப்பட்டுள்ளது"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"கைரேகை <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"கைரேகையைப் பயன்படுத்து"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 28b7d2804681..30c28129e8c5 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"వేలిముద్ర ప్రమాణీకరించబడింది"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ముఖం ప్రమాణీకరించబడింది"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ముఖం ప్రమాణీకరించబడింది, దయచేసి ధృవీకరించును నొక్కండి"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"వేలిముద్ర హార్డ్వేర్ అందుబాటులో లేదు"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"వేలిముద్రను సెటప్ చేయడం సాధ్యం కాదు"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"వేలిముద్ర సెటప్ సమయం ముగిసింది. మళ్లీ ట్రై చేయండి."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"వేలిముద్ర ఆపరేషన్ రద్దయింది"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"వేలిముద్ర ఆపరేషన్ను యూజర్ రద్దు చేశారు"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"చాలా ఎక్కువ సార్లు ప్రయత్నించారు. బదులుగా స్క్రీన్ లాక్ను ఉపయోగించండి."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"చాలా ఎక్కువ సార్లు ప్రయత్నించారు. బదులుగా స్క్రీన్ లాక్ను ఉపయోగించండి."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడదు. మళ్లీ ట్రై చేయండి."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"వేలిముద్రలు ఏవీ ఎన్రోల్ అవలేదు"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"ఈ పరికరంలో వేలిముద్ర సెన్సార్ లేదు"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"సెన్సార్ తాత్కాలికంగా డిజేబుల్ అయ్యింది"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"వేలిముద్ర సెన్సార్ను ఉపయోగించడం సాధ్యం కాదు. రిపెయిర్ ప్రొవైడర్ను చూడండి."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Power button pressed"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>వ వేలు"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"వేలిముద్రను ఉపయోగించండి"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 94fe59d18549..c92d6139147b 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"ตรวจสอบสิทธิ์ลายนิ้วมือแล้ว"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ตรวจสอบสิทธิ์ใบหน้าแล้ว โปรดกดยืนยัน"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"ฮาร์ดแวร์อ่านลายนิ้วมือไม่พร้อมใช้งาน"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ตั้งค่าลายนิ้วมือไม่ได้"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"การตั้งค่าลายนิ้วมือหมดเวลา โปรดลองอีกครั้ง"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"การทำงานของลายนิ้วมือถูกยกเลิก"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"ผู้ใช้ยกเลิกการทำงานของลายนิ้วมือ"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"ลองหลายครั้งเกินไป ใช้การล็อกหน้าจอแทน"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ลองหลายครั้งเกินไป ใช้การล็อกหน้าจอแทน"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"ประมวลผลลายนิ้วมือไม่ได้ โปรดลองอีกครั้ง"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"ไม่มีลายนิ้วมือที่ลงทะเบียน"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"อุปกรณ์นี้ไม่มีเซ็นเซอร์ลายนิ้วมือ"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"เซ็นเซอร์ถูกปิดใช้ชั่วคราว"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"ใช้เซ็นเซอร์ลายนิ้วมือไม่ได้ โปรดติดต่อผู้ให้บริการซ่อม"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"กดปุ่มเปิด/ปิดแล้ว"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"นิ้วมือ <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ใช้ลายนิ้วมือ"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 57c6b2ab3b46..d9443349d691 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Na-authenticate ang fingerprint"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Na-authenticate ang mukha"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Na-authenticate ang mukha, pakipindot ang kumpirmahin"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Hindi available ang hardware na ginagamitan ng fingerprint"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Hindi ma-set up ang fingerprint"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Nag-time out ang pag-set up ng fingerprint. Subukan ulit."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Nakansela ang operasyon sa fingerprint"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Kinansela ng user ang operasyon sa fingerprint"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Masyadong maraming pagsubok. Gamitin na lang ang lock ng screen."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Masyadong maraming pagsubok. Gamitin na lang ang lock ng screen."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Hindi maproseso ang fingerprint. Subukan ulit."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Walang naka-enroll na fingerprint"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Walang sensor para sa fingerprint ang device na ito"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Pansamantalang na-disable ang sensor"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Hindi magamit ang sensor para sa fingerprint. Bumisita sa provider ng pag-aayos."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Napindot ang power button"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Daliri <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Gumamit ng fingerprint"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index af18dacc05c2..dfae3016beb3 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Parmak izi kimlik doğrulaması yapıldı"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yüz kimliği doğrulandı"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yüz kimliği doğrulandı, lütfen onayla\'ya basın"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Parmak izi donanımı kullanılamıyor"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Parmak izi ayarlanamıyor"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Parmak izi kurulumu zaman aşımına uğradı. Tekrar deneyin."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Parmak izi işlemi iptal edildi"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Parmak izi işlemi kullanıcı tarafından iptal edildi"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Çok fazla deneme yapıldı. Bunun yerine ekran kilidini kullanın."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Çok fazla deneme yapıldı. Bunun yerine ekran kilidini kullanın."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Parmak izi işlenemiyor. Tekrar deneyin."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Parmak izi kaydedilmedi"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Bu cihazda parmak izi sensörü yok"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Sensör geçici olarak devre dışı bırakıldı"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Parmak izi sensörü kullanılamıyor. Bir onarım hizmeti sağlayıcıyı ziyaret edin."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Güç düğmesine basıldı"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"<xliff:g id="FINGERID">%d</xliff:g>. parmak"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Parmak izi kullan"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 5b645db69daa..c8fa2108e6d3 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -668,24 +668,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Відбиток пальця автентифіковано"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Обличчя автентифіковано"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Сканер відбитків пальців недоступний"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не вдалося створити відбиток пальця"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Час очікування для налаштування відбитка пальця минув. Повторіть спробу."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Дію з відбитком пальця скасовано"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Користувач скасував дію з відбитком пальця"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Забагато спроб. Використайте натомість розблокування екрана."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Забагато спроб. Використайте натомість розблокування екрана."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Не вдалось обробити відбиток пальця. Повторіть спробу."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Відбитки пальців не зареєстровано"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"На цьому пристрої немає сканера відбитків пальців"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Сканер тимчасово вимкнено"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Не вдається скористатися сканером відбитків пальців. Зверніться до постачальника послуг із ремонту."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Натиснуто кнопку живлення"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Відбиток пальця <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Доступ за відбитком пальця"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 1c9275293cca..5ad1f1832077 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"فنگر پرنٹ کی تصدیق ہو گئی"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چہرے کی تصدیق ہو گئی"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چہرے کی تصدیق ہو گئی، براہ کرم \'تصدیق کریں\' کو دبائيں"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"فنگر پرنٹ کو سیٹ اپ نہیں کیا جا سکا"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"فنگر پرنٹ کے سیٹ اپ کا وقت ختم ہو گیا۔ دوبارہ کوشش کریں۔"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"صارف نے فنگر پرنٹ کی کارروائی منسوخ کر دی"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"کافی زیادہ کوششیں۔ اس کے بجائے اسکرین لاک کا استعمال کریں۔"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"کافی زیادہ کوششیں۔ اس کے بجائے اسکرین لاک کا استعمال کریں۔"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"فنگر پرنٹ پروسیس نہیں ہو سکتا۔ دوبارہ کوشش کریں۔"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"کوئی فنگر پرنٹ مندرج نہیں ہے"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"اس آلہ میں فنگر پرنٹ سینسر نہیں ہے"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"سینسر عارضی طور غیر فعال ہے"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"فنگر پرنٹ سینسر کو استعمال نہیں کیا جا سکتا۔ مرمت فراہم کنندہ کو ملاحظہ کریں۔"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"پاور بٹن دبایا گیا"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"فنگر پرنٹ استعمال کریں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 828f391345f0..a3ffb9c62ad5 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmoq izi tekshirildi"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yuzingiz aniqlandi"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yuzingiz aniqlandi, tasdiqlash uchun bosing"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Barmoq izi skaneri ish holatida emas"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Barmoq izi sozlanmadi"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Barmoq izini sozlash vaqti tugadi. Qayta urining."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Barmoq izi amali bekor qilindi"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Barmoq izi amali foydalanuvchi tomonidan bekor qilindi"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Juda koʻp urinildi. Ekran qulfi orqali urining."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Juda koʻp urinildi. Ekran qulfi orqali urining."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Barmoq izi tekshirilmadi. Qayta urining."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Hech qanday barmoq izi qayd qilinmagan"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Bu qurilmada barmoq izi skaneri yo‘q"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Skaner vaqtincha faol emas"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Barmoq izi skaneridan foydalanish imkonsiz. Xizmat koʻrsatish markaziga murojaat qiling."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Quvvat tugmasi bosildi"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Barmoq izi ishlatish"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 2e57cafaec1f..8f52be0cb10d 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Đã xác thực vân tay"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Đã xác thực khuôn mặt"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Đã xác thực khuôn mặt, vui lòng nhấn để xác nhận"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Không có phần cứng xử lý vân tay"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Không thể thiết lập vân tay"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Hết thời gian chờ thiết lập vân tay. Hãy thử lại."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Đã huỷ thao tác dùng vân tay"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Người dùng đã huỷ thao tác sử dụng vân tay"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Bạn đã thử quá nhiều lần. Hãy dùng phương thức khoá màn hình."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Bạn đã thử quá nhiều lần. Hãy dùng phương thức khoá màn hình."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Không xử lý được vân tay. Hãy thử lại."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Chưa đăng ký vân tay"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Thiết bị này không có cảm biến vân tay"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Đã tắt tạm thời cảm biến"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Không dùng được cảm biến vân tay. Hãy liên hệ với một nhà cung cấp dịch vụ sửa chữa."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Đã nhấn nút nguồn"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Ngón tay <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Dùng vân tay"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 0d49373867fb..28f563d2f170 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"已验证指纹"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已验证"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已验证,请按确认按钮"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"无法使用指纹硬件"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"无法设置指纹"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指纹设置已超时,请重试。"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"已取消指纹操作"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"用户取消了指纹操作"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"尝试次数过多,请通过屏幕锁定功能解锁。"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"尝试次数过多,请通过屏幕锁定功能解锁。"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"无法处理指纹,请重试。"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"未注册任何指纹"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"此设备没有指纹传感器"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"已暂时停用传感器"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"无法使用指纹传感器。请联系维修服务提供商。"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"已按下电源按钮"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"使用指纹"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index cce19905c2ff..59a2abd442eb 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"驗證咗指紋"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已經驗證"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已經驗證,請㩒一下 [確認]"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"無法使用指紋硬件"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"無法設定指紋"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋設定逾時,請再試一次。"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"指紋操作已取消"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"使用者已取消指紋操作"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"嘗試次數過多,請改用螢幕鎖定功能。"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"嘗試次數過多,請改用螢幕鎖定功能。"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"無法處理指紋,請再試一次。"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"尚未註冊任何指紋"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"此裝置沒有指紋感應器"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"感應器已暫時停用"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"指紋感應器無法使用,請諮詢維修服務供應商。"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"已按下開關按鈕"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"使用指紋鎖定"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index ff31b74fbea2..2233668ba404 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋驗證成功"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"臉孔驗證成功"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"臉孔驗證成功,請按下 [確認] 按鈕"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"指紋辨識硬體無法使用"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"無法設定指紋"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋設定逾時,請再試一次。"</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"指紋作業已取消"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"使用者已取消指紋驗證作業"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"嘗試次數過多,請改用螢幕鎖定功能。"</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"嘗試次數過多,請改用螢幕鎖定功能。"</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"無法處理指紋,請再試一次。"</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"未登錄任何指紋"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"這個裝置沒有指紋感應器"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"感應器已暫時停用"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"指紋感應器無法使用,請洽詢維修供應商。"</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"已按下電源鍵"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"使用指紋"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 5112da966e7f..176c3743825d 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -666,24 +666,18 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Izigxivizo zeminwe zigunyaziwe"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ubuso bufakazelwe ubuqiniso"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string> - <!-- no translation found for fingerprint_error_hw_not_available (7755729484334001137) --> - <skip /> + <string name="fingerprint_error_hw_not_available" msgid="7755729484334001137">"Izingxenyekazi zekhompuyutha zezigxivizo zeminwe azitholakali"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ayikwazi ukusetha izigxivizo zeminwe"</string> <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Ukusethwa kwesigxivizo somunwe kuphelelwe yisikhathi Zama futhi."</string> - <!-- no translation found for fingerprint_error_canceled (5541771463159727513) --> - <skip /> - <!-- no translation found for fingerprint_error_user_canceled (2017941773466506863) --> - <skip /> + <string name="fingerprint_error_canceled" msgid="5541771463159727513">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe"</string> + <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"Umsebenzi wezigxivizo zeminwe ukhanselwe umsebenzisi"</string> <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Imizamo eminingi kakhulu. Sebenzisa ukukhiya isikrini kunalokho."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Imizamo eminingi kakhulu. Sebenzisa ukukhiya isikrini kunalokho."</string> <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Ayikwazi ukucubungula isigxivizo somunwe. Zama futhi."</string> - <!-- no translation found for fingerprint_error_no_fingerprints (3144806556204061862) --> - <skip /> + <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"Azikho izigxivizo zeminwe ezibhalisiwe"</string> <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"Le divayisi ayinayo inzwa yezigxivizo zeminwe"</string> - <!-- no translation found for fingerprint_error_security_update_required (8440349108169661934) --> - <skip /> - <!-- no translation found for fingerprint_error_bad_calibration (6770614925736183528) --> - <skip /> + <string name="fingerprint_error_security_update_required" msgid="8440349108169661934">"Inzwa ikhutshazwe okwesikhashana"</string> + <string name="fingerprint_error_bad_calibration" msgid="6770614925736183528">"Ayikwazi ukusebenzisa inzwa yesigxivizo somunwe. Vakashela umhlinzeki wokulungisa."</string> <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Inkinobho yamandla icindezelwe"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Umunwe ongu-<xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Sebenzisa izigxivizo zeminwe"</string> diff --git a/core/res/res/values/config_battery_saver.xml b/core/res/res/values/config_battery_saver.xml index e1b0ef4bd0a7..551cd0a87867 100644 --- a/core/res/res/values/config_battery_saver.xml +++ b/core/res/res/values/config_battery_saver.xml @@ -33,6 +33,9 @@ <!-- Whether or not battery saver should be "sticky" when manually enabled. --> <bool name="config_batterySaverStickyBehaviourDisabled">false</bool> + <!-- Whether to enable "Battery Saver turned off" notification. --> + <bool name="config_batterySaverTurnedOffNotificationEnabled">true</bool> + <!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. --> <integer name="config_dynamicPowerSavingsDefaultDisableThreshold">80</integer> diff --git a/core/res/res/values/config_display.xml b/core/res/res/values/config_display.xml new file mode 100644 index 000000000000..2e66060926fd --- /dev/null +++ b/core/res/res/values/config_display.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright (C) 2024 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- Resources used in DisplayManager. + + These resources are around just to allow their values to be customized + for different hardware and product builds. Do not translate. + + NOTE: The naming convention is "config_camelCaseValue". --> + + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Whether even dimmer feature is enabled. --> + <bool name="config_evenDimmerEnabled">false</bool> + +</resources> diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml index 104b7cd5450b..c87b7cdb1e8e 100644 --- a/core/res/res/values/config_telephony.xml +++ b/core/res/res/values/config_telephony.xml @@ -73,6 +73,11 @@ <bool name="auto_data_switch_ping_test_before_switch">true</bool> <java-symbol type="bool" name="auto_data_switch_ping_test_before_switch" /> + <!-- TODO: remove after V --> + <!-- Boolean indicating whether allow to use a roaming nonDDS if user enabled its roaming. --> + <bool name="auto_data_switch_allow_roaming">true</bool> + <java-symbol type="bool" name="auto_data_switch_allow_roaming" /> + <!-- Define the tolerated gap of score for auto data switch decision, larger than which the device will switch to the SIM with higher score. The score is used in conjunction with the score table defined in diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index adf8d9f95b52..5945f81704c5 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1468,7 +1468,7 @@ please see styles_device_defaults.xml. <item name="pointerIconHand">@drawable/pointer_hand_vector_icon</item> <item name="pointerIconContextMenu">@drawable/pointer_context_menu_vector_icon</item> <item name="pointerIconHelp">@drawable/pointer_help_vector_icon</item> - <item name="pointerIconWait">@drawable/pointer_wait_icon</item> + <item name="pointerIconWait">@drawable/pointer_wait_vector_icon</item> <item name="pointerIconCell">@drawable/pointer_cell_vector_icon</item> <item name="pointerIconCrosshair">@drawable/pointer_crosshair_vector_icon</item> <item name="pointerIconText">@drawable/pointer_text_vector_icon</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3284791ef384..b36b1d63cbf2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4123,6 +4123,7 @@ <java-symbol type="bool" name="config_batterySaverSupported" /> <java-symbol type="string" name="config_batterySaverDeviceSpecificConfig" /> <java-symbol type="bool" name="config_batterySaverStickyBehaviourDisabled" /> + <java-symbol type="bool" name="config_batterySaverTurnedOffNotificationEnabled" /> <java-symbol type="integer" name="config_dynamicPowerSavingsDefaultDisableThreshold" /> <java-symbol type="string" name="config_batterySaverScheduleProvider" /> <java-symbol type="string" name="config_powerSaveModeChangedListenerPackage" /> @@ -5363,5 +5364,8 @@ <java-symbol type="string" name="satellite_notification_how_it_works" /> <java-symbol type="drawable" name="ic_satellite_alt_24px" /> + <!-- DisplayManager configs. --> + <java-symbol type="bool" name="config_evenDimmerEnabled" /> + <java-symbol type="bool" name="config_watchlistUseFileHashesCache" /> </resources> diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index a7d083cbc399..d95834fc0f4a 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -65,6 +65,7 @@ import android.util.DisplayMetrics; import android.util.MergedConfiguration; import android.view.Display; import android.view.View; +import android.window.ActivityWindowInfo; import android.window.WindowContextInfo; import android.window.WindowTokenClientController; @@ -839,7 +840,7 @@ public class ActivityThreadTest { final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain( activity.getActivityToken(), null, null, 0, new MergedConfiguration(currentConfig, currentConfig), - false /* preserveWindow */); + false /* preserveWindow */, new ActivityWindowInfo()); final ResumeActivityItem resumeStateRequest = ResumeActivityItem.obtain(activity.getActivityToken(), true /* isForward */, false /* shouldSendCompatFakeFocus*/); diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java index b5e8203c51ed..30545f994f01 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java +++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java @@ -40,6 +40,7 @@ import android.util.ArrayMap; import android.util.MergedConfiguration; import android.view.IWindow; import android.view.InsetsState; +import android.window.ActivityWindowInfo; import android.window.ClientWindowFrames; import android.window.WindowContext; import android.window.WindowContextInfo; @@ -116,7 +117,8 @@ public class ClientTransactionItemTest { public void testActivityRelaunchItem_getContextToUpdate() { final ActivityRelaunchItem item = ActivityRelaunchItem .obtain(mActivityToken, null /* pendingResults */, null /* pendingNewIntents */, - 0 /* configChange */, mMergedConfiguration, false /* preserveWindow */); + 0 /* configChange */, mMergedConfiguration, false /* preserveWindow */, + new ActivityWindowInfo()); final Context context = item.getContextToUpdate(mHandler); assertEquals(mActivity, context); diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index c6447be71855..a8466bb092c8 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -39,6 +39,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; import android.platform.test.annotations.Presubmit; +import android.window.ActivityWindowInfo; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -124,6 +125,7 @@ public class ObjectPoolTests { final int deviceId = 3; final IBinder taskFragmentToken = new Binder(); final IBinder initialCallerInfoAccessToken = new Binder(); + final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo(); testRecycle(() -> new LaunchActivityItemBuilder( activityToken, intent, activityInfo) @@ -142,13 +144,15 @@ public class ObjectPoolTests { .setTaskFragmentToken(taskFragmentToken) .setDeviceId(deviceId) .setInitialCallerInfoAccessToken(initialCallerInfoAccessToken) + .setActivityWindowInfo(activityWindowInfo) .build()); } @Test public void testRecycleActivityRelaunchItem() { testRecycle(() -> ActivityRelaunchItem.obtain(mActivityToken, - resultInfoList(), referrerIntentList(), 42, mergedConfig(), true)); + resultInfoList(), referrerIntentList(), 42, mergedConfig(), true, + new ActivityWindowInfo())); } @Test diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index d641659e6a5f..c1b9efda4652 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; import android.util.MergedConfiguration; +import android.window.ActivityWindowInfo; import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; @@ -134,6 +135,8 @@ class TestUtils { private IBinder mTaskFragmentToken; @Nullable private IBinder mInitialCallerInfoAccessToken; + @NonNull + private ActivityWindowInfo mActivityWindowInfo = new ActivityWindowInfo(); LaunchActivityItemBuilder(@NonNull IBinder activityToken, @NonNull Intent intent, @NonNull ActivityInfo info) { @@ -260,6 +263,13 @@ class TestUtils { } @NonNull + LaunchActivityItemBuilder setActivityWindowInfo( + @NonNull ActivityWindowInfo activityWindowInfo) { + mActivityWindowInfo.set(activityWindowInfo); + return this; + } + + @NonNull LaunchActivityItem build() { return LaunchActivityItem.obtain(mActivityToken, mIntent, mIdent, mInfo, mCurConfig, mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor, @@ -267,7 +277,7 @@ class TestUtils { mActivityOptions != null ? mActivityOptions.getSceneTransitionInfo() : null, mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */, mShareableActivityToken, mLaunchedFromBubble, mTaskFragmentToken, - mInitialCallerInfoAccessToken); + mInitialCallerInfoAccessToken, mActivityWindowInfo); } } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index aa8001310008..9743e84b9349 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -32,6 +32,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; +import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -40,6 +41,7 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; +import android.window.ActivityWindowInfo; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -180,6 +182,9 @@ public class TransactionParcelTests { bundle.putParcelable("data", new ParcelableData(1)); final PersistableBundle persistableBundle = new PersistableBundle(); persistableBundle.putInt("k", 4); + final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo(); + activityWindowInfo.set(true /* isEmbedded */, new Rect(0, 0, 500, 1000), + new Rect(0, 0, 500, 500)); final LaunchActivityItem item = new LaunchActivityItemBuilder( activityToken, intent, activityInfo) @@ -198,6 +203,7 @@ public class TransactionParcelTests { .setShareableActivityToken(new Binder()) .setTaskFragmentToken(new Binder()) .setInitialCallerInfoAccessToken(new Binder()) + .setActivityWindowInfo(activityWindowInfo) .build(); writeAndPrepareForReading(item); @@ -214,8 +220,11 @@ public class TransactionParcelTests { // Write to parcel Configuration overrideConfig = new Configuration(); overrideConfig.assetsSeq = 5; + final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo(); + activityWindowInfo.set(true /* isEmbedded */, new Rect(0, 0, 500, 1000), + new Rect(0, 0, 500, 500)); ActivityRelaunchItem item = ActivityRelaunchItem.obtain(mActivityToken, resultInfoList(), - referrerIntentList(), 35, mergedConfig(), true); + referrerIntentList(), 35, mergedConfig(), true, activityWindowInfo); writeAndPrepareForReading(item); // Read from parcel and assert diff --git a/core/tests/coretests/src/android/os/WakeLockStatsTest.java b/core/tests/coretests/src/android/os/WakeLockStatsTest.java index 2675ba07d2f7..f3b18c8bd9bb 100644 --- a/core/tests/coretests/src/android/os/WakeLockStatsTest.java +++ b/core/tests/coretests/src/android/os/WakeLockStatsTest.java @@ -29,10 +29,114 @@ import java.util.List; public class WakeLockStatsTest { @Test + public void isDataValidOfWakeLockData_invalid_returnFalse() { + WakeLockStats.WakeLockData wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 0, /* totalTimeHeldMs= */ 10, /* timeHeldMs= */ 0); + assertThat(wakeLockData.isDataValid()).isFalse(); + + wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 1, /* totalTimeHeldMs= */ 0, /* timeHeldMs= */ 0); + assertThat(wakeLockData.isDataValid()).isFalse(); + + wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 1, /* totalTimeHeldMs= */ 10, /* timeHeldMs= */ -10); + assertThat(wakeLockData.isDataValid()).isFalse(); + + wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 1, /* totalTimeHeldMs= */ 10, /* timeHeldMs= */ 20); + assertThat(wakeLockData.isDataValid()).isFalse(); + } + + @Test + public void isDataValidOfWakeLockData_empty_returnTrue() { + final WakeLockStats.WakeLockData wakeLockData = WakeLockStats.WakeLockData.EMPTY; + assertThat(wakeLockData.isDataValid()).isTrue(); + } + + @Test + public void isDataValidOfWakeLockData_valid_returnTrue() { + WakeLockStats.WakeLockData wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 1, /* totalTimeHeldMs= */ 10, /* timeHeldMs= */ 5); + assertThat(wakeLockData.isDataValid()).isTrue(); + } + + @Test + public void isDataValidOfWakeLock_zeroTotalHeldMs_returnFalse() { + final WakeLockStats.WakeLockData wakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 0, /* totalTimeHeldMs= */ 0, /* timeHeldMs= */ 0); + + assertThat(WakeLockStats.WakeLock.isDataValid(wakeLockData, wakeLockData)).isFalse(); + } + + @Test + public void isDataValidOfWakeLock_invalidData_returnFalse() { + final WakeLockStats.WakeLockData totalWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 6, /* totalTimeHeldMs= */ 60, /* timeHeldMs= */ 20); + final WakeLockStats.WakeLockData backgroundWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 0, /* totalTimeHeldMs= */ 10, /* timeHeldMs= */ 0); + + assertThat(WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)) + .isFalse(); + } + + @Test + public void isDataValidOfWakeLock_totalSmallerThanBackground_returnFalse() { + final WakeLockStats.WakeLockData totalWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 10, /* totalTimeHeldMs= */ 60, /* timeHeldMs= */ 50); + final WakeLockStats.WakeLockData backgroundWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 6, /* totalTimeHeldMs= */ 100, /* timeHeldMs= */ 30); + + assertThat(WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)) + .isFalse(); + } + + @Test + public void isDataValidOfWakeLock_returnTrue() { + final WakeLockStats.WakeLockData totalWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 10, /* totalTimeHeldMs= */ 100, /* timeHeldMs= */ 50); + final WakeLockStats.WakeLockData backgroundWakeLockData = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 6, /* totalTimeHeldMs= */ 60, /* timeHeldMs= */ 20); + + assertThat(WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)) + .isTrue(); + } + + @Test public void parcelablity() { + final WakeLockStats.WakeLockData totalWakeLockData1 = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 10, /* totalTimeHeldMs= */ 60, /* timeHeldMs= */ 50); + final WakeLockStats.WakeLockData backgroundWakeLockData1 = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 6, /* totalTimeHeldMs= */ 100, /* timeHeldMs= */ 30); + final WakeLockStats.WakeLock wakeLock1 = + new WakeLockStats.WakeLock( + 1, "foo", /* isAggregated= */ false, totalWakeLockData1, + backgroundWakeLockData1); + final WakeLockStats.WakeLockData totalWakeLockData2 = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 20, /* totalTimeHeldMs= */ 80, /* timeHeldMs= */ 30); + final WakeLockStats.WakeLockData backgroundWakeLockData2 = + new WakeLockStats.WakeLockData( + /* timesAcquired= */ 1, /* totalTimeHeldMs= */ 100, /* timeHeldMs= */ 30); + final WakeLockStats.WakeLock wakeLock2 = + new WakeLockStats.WakeLock( + 2, "bar", /* isAggregated= */ true, totalWakeLockData2, + backgroundWakeLockData2); WakeLockStats wakeLockStats = new WakeLockStats( - List.of(new WakeLockStats.WakeLock(1, "foo", 200, 3000, 40000), - new WakeLockStats.WakeLock(2, "bar", 500, 6000, 70000))); + List.of(wakeLock1), List.of(wakeLock2)); Parcel parcel = Parcel.obtain(); wakeLockStats.writeToParcel(parcel, 0); @@ -44,15 +148,28 @@ public class WakeLockStatsTest { parcel.setDataPosition(0); WakeLockStats actual = WakeLockStats.CREATOR.createFromParcel(parcel); - assertThat(actual.getWakeLocks()).hasSize(2); - WakeLockStats.WakeLock wl1 = actual.getWakeLocks().get(0); - assertThat(wl1.uid).isEqualTo(1); - assertThat(wl1.name).isEqualTo("foo"); - assertThat(wl1.timesAcquired).isEqualTo(200); - assertThat(wl1.totalTimeHeldMs).isEqualTo(3000); - assertThat(wl1.timeHeldMs).isEqualTo(40000); - - WakeLockStats.WakeLock wl2 = actual.getWakeLocks().get(1); - assertThat(wl2.uid).isEqualTo(2); - } -} + assertThat(actual.getWakeLocks()).hasSize(1); + WakeLockStats.WakeLock actualWakelock = actual.getWakeLocks().get(0); + assertThat(actualWakelock.uid).isEqualTo(1); + assertThat(actualWakelock.name).isEqualTo("foo"); + assertThat(actualWakelock.isAggregated).isFalse(); + assertThat(actualWakelock.totalWakeLockData.timesAcquired).isEqualTo(10); + assertThat(actualWakelock.totalWakeLockData.totalTimeHeldMs).isEqualTo(60); + assertThat(actualWakelock.totalWakeLockData.timeHeldMs).isEqualTo(50); + assertThat(actualWakelock.backgroundWakeLockData.timesAcquired).isEqualTo(6); + assertThat(actualWakelock.backgroundWakeLockData.totalTimeHeldMs).isEqualTo(100); + assertThat(actualWakelock.backgroundWakeLockData.timeHeldMs).isEqualTo(30); + + assertThat(actual.getAggregatedWakeLocks()).hasSize(1); + WakeLockStats.WakeLock actualAggregatedWakelock = actual.getAggregatedWakeLocks().get(0); + assertThat(actualAggregatedWakelock.uid).isEqualTo(2); + assertThat(actualAggregatedWakelock.name).isEqualTo("bar"); + assertThat(actualAggregatedWakelock.isAggregated).isTrue(); + assertThat(actualAggregatedWakelock.totalWakeLockData.timesAcquired).isEqualTo(20); + assertThat(actualAggregatedWakelock.totalWakeLockData.totalTimeHeldMs).isEqualTo(80); + assertThat(actualAggregatedWakelock.totalWakeLockData.timeHeldMs).isEqualTo(30); + assertThat(actualAggregatedWakelock.backgroundWakeLockData.timesAcquired).isEqualTo(1); + assertThat(actualAggregatedWakelock.backgroundWakeLockData.totalTimeHeldMs).isEqualTo(100); + assertThat(actualAggregatedWakelock.backgroundWakeLockData.timeHeldMs).isEqualTo(30); + } +}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java index 5649e7118fd5..f60eff69690a 100644 --- a/core/tests/coretests/src/android/text/LayoutTest.java +++ b/core/tests/coretests/src/android/text/LayoutTest.java @@ -16,6 +16,11 @@ package android.text; +import static com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -26,11 +31,16 @@ import static org.junit.Assert.fail; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.text.Layout.Alignment; import android.text.style.StrikethroughSpan; @@ -38,6 +48,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,6 +60,9 @@ import java.util.Locale; @SmallTest @RunWith(AndroidJUnit4.class) public class LayoutTest { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + private static final int LINE_COUNT = 5; private static final int LINE_HEIGHT = 12; private static final int LINE_DESCENT = 4; @@ -638,22 +652,268 @@ public class LayoutTest { } } - private final class MockCanvas extends Canvas { + @Test + @RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void highContrastTextEnabled_testDrawSelectionAndHighlight_drawsHighContrastSelectionAndHighlight() { + Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, + mAlign, mSpacingMult, mSpacingAdd); + + List<Path> highlightPaths = new ArrayList<>(); + List<Paint> highlightPaints = new ArrayList<>(); + + Path selectionPath = new Path(); + RectF selectionRect = new RectF(0f, 0f, mWidth / 2f, LINE_HEIGHT); + selectionPath.addRect(selectionRect, Path.Direction.CW); + highlightPaths.add(selectionPath); + + Paint selectionPaint = new Paint(); + selectionPaint.setColor(Color.CYAN); + highlightPaints.add(selectionPaint); + + final int width = 256; + final int height = 256; + MockCanvas c = new MockCanvas(width, height); + c.setHighContrastTextEnabled(true); + layout.draw(c, highlightPaths, highlightPaints, selectionPath, selectionPaint, + /* cursorOffsetVertical= */ 0); + List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands(); + var textsDrawn = LINE_COUNT; + var highlightsDrawn = 2; + assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn); + + var highlightsFound = 0; + var curLineIndex = 0; + for (int i = 0; i < drawCommands.size(); i++) { + MockCanvas.DrawCommand drawCommand = drawCommands.get(i); + + if (drawCommand.path != null) { + assertThat(drawCommand.path).isEqualTo(selectionPath); + assertThat(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW); + assertThat(drawCommand.paint.getBlendMode()).isNotNull(); + highlightsFound++; + } else if (drawCommand.text != null) { + int start = layout.getLineStart(curLineIndex); + int end = layout.getLineEnd(curLineIndex); + assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text); + curLineIndex++; + + assertWithMessage("highlight is drawn on top of text") + .that(highlightsFound).isEqualTo(0); + } + } + + assertThat(highlightsFound).isEqualTo(2); + } + + @Test + @RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void highContrastTextEnabled_testDrawHighlight_drawsHighContrastHighlight() { + Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, + mAlign, mSpacingMult, mSpacingAdd); + + List<Path> highlightPaths = new ArrayList<>(); + List<Paint> highlightPaints = new ArrayList<>(); + + Path selectionPath = new Path(); + RectF selectionRect = new RectF(0f, 0f, mWidth / 2f, LINE_HEIGHT); + selectionPath.addRect(selectionRect, Path.Direction.CW); + highlightPaths.add(selectionPath); + + Paint selectionPaint = new Paint(); + selectionPaint.setColor(Color.CYAN); + highlightPaints.add(selectionPaint); + + final int width = 256; + final int height = 256; + MockCanvas c = new MockCanvas(width, height); + c.setHighContrastTextEnabled(true); + layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null, + /* selectionPaint= */ null, /* cursorOffsetVertical= */ 0); + List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands(); + var textsDrawn = LINE_COUNT; + var highlightsDrawn = 1; + assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn); + + var highlightsFound = 0; + var curLineIndex = 0; + for (int i = 0; i < drawCommands.size(); i++) { + MockCanvas.DrawCommand drawCommand = drawCommands.get(i); + + if (drawCommand.path != null) { + assertThat(drawCommand.path).isEqualTo(selectionPath); + assertThat(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW); + assertThat(drawCommand.paint.getBlendMode()).isNotNull(); + highlightsFound++; + } else if (drawCommand.text != null) { + int start = layout.getLineStart(curLineIndex); + int end = layout.getLineEnd(curLineIndex); + assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text); + curLineIndex++; + + assertWithMessage("highlight is drawn on top of text") + .that(highlightsFound).isEqualTo(0); + } + } + + assertThat(highlightsFound).isEqualTo(1); + } + + @Test + @RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void highContrastTextDisabledByDefault_testDrawHighlight_drawsNormalHighlightBehind() { + Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, + mAlign, mSpacingMult, mSpacingAdd); + + List<Path> highlightPaths = new ArrayList<>(); + List<Paint> highlightPaints = new ArrayList<>(); + + Path selectionPath = new Path(); + RectF selectionRect = new RectF(0f, 0f, mWidth / 2f, LINE_HEIGHT); + selectionPath.addRect(selectionRect, Path.Direction.CW); + highlightPaths.add(selectionPath); + + Paint selectionPaint = new Paint(); + selectionPaint.setColor(Color.CYAN); + highlightPaints.add(selectionPaint); + + final int width = 256; + final int height = 256; + MockCanvas c = new MockCanvas(width, height); + layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null, + /* selectionPaint= */ null, /* cursorOffsetVertical= */ 0); + List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands(); + var textsDrawn = LINE_COUNT; + var highlightsDrawn = 1; + assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn); + + var highlightsFound = 0; + var curLineIndex = 0; + for (int i = 0; i < drawCommands.size(); i++) { + MockCanvas.DrawCommand drawCommand = drawCommands.get(i); + + if (drawCommand.path != null) { + assertThat(drawCommand.path).isEqualTo(selectionPath); + assertThat(drawCommand.paint.getColor()).isEqualTo(Color.CYAN); + assertThat(drawCommand.paint.getBlendMode()).isNull(); + highlightsFound++; + } else if (drawCommand.text != null) { + int start = layout.getLineStart(curLineIndex); + int end = layout.getLineEnd(curLineIndex); + assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text); + curLineIndex++; + + assertWithMessage("highlight is drawn behind text") + .that(highlightsFound).isGreaterThan(0); + } + } + + assertThat(highlightsFound).isEqualTo(1); + } + + @Test + @RequiresFlagsDisabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void highContrastTextEnabledButFlagOff_testDrawHighlight_drawsNormalHighlightBehind() { + Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, + mAlign, mSpacingMult, mSpacingAdd); + + List<Path> highlightPaths = new ArrayList<>(); + List<Paint> highlightPaints = new ArrayList<>(); + + Path selectionPath = new Path(); + RectF selectionRect = new RectF(0f, 0f, mWidth / 2f, LINE_HEIGHT); + selectionPath.addRect(selectionRect, Path.Direction.CW); + highlightPaths.add(selectionPath); + + Paint selectionPaint = new Paint(); + selectionPaint.setColor(Color.CYAN); + highlightPaints.add(selectionPaint); + + final int width = 256; + final int height = 256; + MockCanvas c = new MockCanvas(width, height); + c.setHighContrastTextEnabled(true); + layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null, + /* selectionPaint= */ null, /* cursorOffsetVertical= */ 0); + List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands(); + var textsDrawn = LINE_COUNT; + var highlightsDrawn = 1; + assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn); - class DrawCommand { + var highlightsFound = 0; + var curLineIndex = 0; + for (int i = 0; i < drawCommands.size(); i++) { + MockCanvas.DrawCommand drawCommand = drawCommands.get(i); + + if (drawCommand.path != null) { + assertThat(drawCommand.path).isEqualTo(selectionPath); + assertThat(drawCommand.paint.getColor()).isEqualTo(Color.CYAN); + assertThat(drawCommand.paint.getBlendMode()).isNull(); + highlightsFound++; + } else if (drawCommand.text != null) { + int start = layout.getLineStart(curLineIndex); + int end = layout.getLineEnd(curLineIndex); + assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text); + curLineIndex++; + + assertWithMessage("highlight is drawn behind text") + .that(highlightsFound).isGreaterThan(0); + } + } + + assertThat(highlightsFound).isEqualTo(1); + } + + @Test + public void mockCanvasHighContrastOverridesCorrectly() { + var canvas = new MockCanvas(100, 100); + + assertThat(canvas.isHighContrastTextEnabled()).isFalse(); + canvas.setHighContrastTextEnabled(true); + assertThat(canvas.isHighContrastTextEnabled()).isTrue(); + canvas.setHighContrastTextEnabled(false); + assertThat(canvas.isHighContrastTextEnabled()).isFalse(); + } + + private static final class MockCanvas extends Canvas { + + static class DrawCommand { public final String text; public final float x; public final float y; + public final Path path; + public final Paint paint; - DrawCommand(String text, float x, float y) { + DrawCommand(String text, float x, float y, Paint paint) { this.text = text; this.x = x; this.y = y; + this.paint = paint; + path = null; + } + + DrawCommand(Path path, Paint paint) { + this.path = path; + this.paint = paint; + y = 0; + x = 0; + text = null; } } List<DrawCommand> mDrawCommands; + private Boolean mIsHighContrastTextOverride = null; + + public void setHighContrastTextEnabled(boolean enabled) { + mIsHighContrastTextOverride = enabled; + } + + @Override + public boolean isHighContrastTextEnabled() { + return mIsHighContrastTextOverride == null ? super.isHighContrastTextEnabled() + : mIsHighContrastTextOverride; + } + MockCanvas(int width, int height) { super(); mDrawCommands = new ArrayList<>(); @@ -666,7 +926,7 @@ public class LayoutTest { @Override public void drawText(String text, int start, int end, float x, float y, Paint p) { - mDrawCommands.add(new DrawCommand(text.substring(start, end), x, y)); + mDrawCommands.add(new DrawCommand(text.substring(start, end), x, y, p)); } @Override @@ -676,7 +936,7 @@ public class LayoutTest { @Override public void drawText(char[] text, int index, int count, float x, float y, Paint p) { - mDrawCommands.add(new DrawCommand(new String(text, index, count), x, y)); + mDrawCommands.add(new DrawCommand(new String(text, index, count), x, y, p)); } @Override @@ -691,6 +951,11 @@ public class LayoutTest { drawText(text, index, count, x, y, paint); } + @Override + public void drawPath(Path path, Paint p) { + mDrawCommands.add(new DrawCommand(path, p)); + } + List<DrawCommand> getDrawCommands() { return mDrawCommands; } diff --git a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java index d57f1fcc6da1..030d420d4b65 100644 --- a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java +++ b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java @@ -24,15 +24,15 @@ import static java.io.File.createTempFile; import static java.nio.file.Files.createTempDirectory; import android.internal.perfetto.protos.PerfettoTrace; -import android.tools.common.ScenarioBuilder; -import android.tools.common.Tag; -import android.tools.common.io.TraceType; -import android.tools.device.traces.TraceConfig; -import android.tools.device.traces.TraceConfigs; -import android.tools.device.traces.io.ResultReader; -import android.tools.device.traces.io.ResultWriter; -import android.tools.device.traces.monitors.PerfettoTraceMonitor; -import android.tools.device.traces.monitors.TraceMonitor; +import android.tools.ScenarioBuilder; +import android.tools.Tag; +import android.tools.io.TraceType; +import android.tools.traces.TraceConfig; +import android.tools.traces.TraceConfigs; +import android.tools.traces.io.ResultReader; +import android.tools.traces.io.ResultWriter; +import android.tools.traces.monitors.PerfettoTraceMonitor; +import android.tools.traces.monitors.TraceMonitor; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index 038c00e3823c..7c58de67ded6 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -24,6 +24,8 @@ import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT; import static android.view.Surface.FRAME_RATE_CATEGORY_LOW; import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL; import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE; +import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE; +import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE; import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; @@ -705,17 +707,51 @@ public class ViewRootImplTest { public void votePreferredFrameRate_voteFrameRate_aggregate() { View view = new View(sContext); attachViewToWindow(view); + ViewRootImpl viewRootImpl = view.getViewRootImpl(); sInstrumentation.runOnMainSync(() -> { - ViewRootImpl viewRootImpl = view.getViewRootImpl(); assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1); - viewRootImpl.votePreferredFrameRate(24); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_GTE); assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1); - viewRootImpl.votePreferredFrameRate(30); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_GTE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(30, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); assertEquals(viewRootImpl.getPreferredFrameRate(), 30, 0.1); - viewRootImpl.votePreferredFrameRate(60); + // If there is a conflict, then set compatibility to + // FRAME_RATE_COMPATIBILITY_FIXED_SOURCE + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + // Should be true since there is a conflict between 24 and 30. + assertEquals(viewRootImpl.isFrameRateConflicted(), true); + view.invalidate(); + }); + sInstrumentation.waitForIdleSync(); + + sInstrumentation.runOnMainSync(() -> { + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE); assertEquals(viewRootImpl.getPreferredFrameRate(), 60, 0.1); - viewRootImpl.votePreferredFrameRate(120); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_GTE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(120, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.getPreferredFrameRate(), 120, 0.1); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + // Should be false since 60 is a divisor of 120. + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE); assertEquals(viewRootImpl.getPreferredFrameRate(), 120, 0.1); + // compatibility should be remained the same (FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) + // since the frame rate 60 is smaller than 120. + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + // Should be false since 60 is a divisor of 120. + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + }); } @@ -842,14 +878,26 @@ public class ViewRootImplTest { sInstrumentation.runOnMainSync(() -> { assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1); - viewRootImpl.votePreferredFrameRate(24); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); + viewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); view.invalidate(); assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); }); Thread.sleep(delay); assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1); + assertEquals(viewRootImpl.getFrameRateCompatibility(), + FRAME_RATE_COMPATIBILITY_FIXED_SOURCE); + assertEquals(viewRootImpl.isFrameRateConflicted(), false); } /** @@ -969,6 +1017,60 @@ public class ViewRootImplTest { assertEquals(viewRootImpl.isFrameRatePowerSavingsBalanced(), true); } + /** + * Test the TextureView heuristic: + * 1. Store the last 3 invalidates time - FT1, FT2, FT3. + * 2. If FT2-FT1 > 15ms && FT3-FT2 > 15ms -> vote for NORMAL category + */ + @Test + @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void votePreferredFrameRate_applyTextureViewHeuristic() throws InterruptedException { + final long delay = 30L; + + TextureView view = new TextureView(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(() -> { + assertEquals(viewRootImpl.getPreferredFrameRateCategory(), + FRAME_RATE_CATEGORY_NO_PREFERENCE); + view.invalidate(); + assertEquals(viewRootImpl.getPreferredFrameRateCategory(), + FRAME_RATE_CATEGORY_HIGH); + }); + + // reset the frame rate category counts + for (int i = 0; i < 5; i++) { + Thread.sleep(delay); + sInstrumentation.runOnMainSync(() -> { + view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE); + view.invalidate(); + }); + sInstrumentation.waitForIdleSync(); + } + + Thread.sleep(delay); + sInstrumentation.runOnMainSync(() -> { + view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT); + view.invalidate(); + assertEquals(viewRootImpl.getPreferredFrameRateCategory(), + FRAME_RATE_CATEGORY_NORMAL); + }); + } + @Test public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() { mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR); diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 39cb616b1ed9..66be05ff233c 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -61,6 +61,7 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.testing.PollingCheck; import android.view.WindowManagerGlobal; +import android.window.ActivityWindowInfo; import android.window.SizeConfigurationBuckets; import androidx.test.annotation.UiThreadTest; @@ -354,7 +355,7 @@ public class ActivityThreadClientTest { null /* activityOptions */, true /* isForward */, null /* profilerInfo */, mThread /* client */, null /* asssitToken */, null /* shareableActivityToken */, false /* launchedFromBubble */, null /* taskfragmentToken */, - null /* initialCallerInfoAccessToken */); + null /* initialCallerInfoAccessToken */, new ActivityWindowInfo()); } @Override diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 1fd10031a129..238a3e10f058 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -199,3 +199,8 @@ filegroup { name: "services.core.protolog.json", srcs: ["services.core.protolog.json"], } + +filegroup { + name: "file-core.protolog.pb", + srcs: ["core.protolog.pb"], +} diff --git a/data/etc/core.protolog.pb b/data/etc/core.protolog.pb Binary files differnew file mode 100644 index 000000000000..0415e44af72a --- /dev/null +++ b/data/etc/core.protolog.pb diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 42e3387e3eb5..e8c7a53ddcff 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1,4715 +1,4709 @@ { "version": "1.0.0", "messages": { - "-2127842445": { - "message": "Clearing startingData for token=%s", + "7286191062634870297": { + "message": "Binding proc %s with config %s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/am\/ActivityManagerService.java" + }, + "-4921282642721622589": { + "message": "Report configuration: %s %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityClientController.java" + }, + "-1597980207704427048": { + "message": "Frontmost changed immersion: %s", + "level": "DEBUG", + "group": "WM_DEBUG_IMMERSIVE", + "at": "com\/android\/server\/wm\/ActivityClientController.java" + }, + "-6509265758887333864": { + "message": "Can't report activity moved to display - client not running, activityRecord=%s, displayId=%d", + "level": "WARN", + "group": "WM_DEBUG_SWITCH", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2121056984": { - "message": "%s", + "-4183059578873561863": { + "message": "Reporting activity moved to display, activityRecord=%s, displayId=%d, config=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_SWITCH", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "7435279034964784633": { + "message": "Can't report activity configuration update - client not running, activityRecord=%s", "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2111539867": { - "message": "remove IME snapshot, caller=%s", - "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-7418876140361338495": { + "message": "Sending new config to %s, config: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2109936758": { - "message": "removeAppToken make exiting: %s", + "-4284934398288119962": { + "message": "Can't report activity position update - client not running, activityRecord=%s", + "level": "WARN", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "7244227111034368231": { + "message": "Sending position change to %s, onTop: %b", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", + "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2109864870": { - "message": "app-release(): mOuter=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "338586566486930495": { + "message": "Checking theme of starting window: 0x%x", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2107721178": { - "message": "grantEmbeddedWindowFocus win=%s grantFocus=%s", + "-2561793317091789573": { + "message": "Translucent=%s Floating=%s ShowWallpaper=%s Disable=%s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2101985723": { - "message": "Failed looking up window session=%s callers=%s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7269690012594027154": { + "message": "Creating SplashScreenStartingData", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2093859262": { - "message": "setClientVisible: %s clientVisible=%b Callers=%s", + "-3432060893368468911": { + "message": "Creating SnapshotStartingData", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowToken.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2088209279": { - "message": "Notified TransitionController that the display is ready.", + "1789854065584848502": { + "message": "startingData was nulled out before handling mAddStartingWindow: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2074882083": { - "message": "Content Recording: Unable to retrieve task to start recording for display %d", + "5659016061937922595": { + "message": "Add starting %s: startingData=%s", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2072089308": { - "message": "Attempted to add window with token that is a sub-window: %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-9066702108316454290": { + "message": "Aborted starting %s: startingData=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2072029833": { - "message": "Content Recording: Found no matching mirror display for id=%d for DEFAULT_DISPLAY. Nothing to mirror.", - "level": "WARN", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "7506106334102501360": { + "message": "Added starting %s: startingWindow=%s startingView=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2054442123": { - "message": "Setting Intent of %s to %s", + "1048048288756547220": { + "message": "Surface returned was null: %s", "level": "VERBOSE", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/Task.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2052051397": { - "message": "Clear animatingExit: reason=destroySurface win=%s", - "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "-1298801500610545721": { + "message": "Cleaning splash screen token=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2049725903": { - "message": "Task back pressed on root taskId=%d", + "-1948849214526113495": { + "message": "Clearing startingData for token=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2039580386": { - "message": "Attempted to add input method window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "5545923784327902026": { + "message": "Schedule remove starting %s startingWindow=%s animate=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2036671725": { - "message": " SKIP: is wallpaper", + "-5150982660941074218": { + "message": "startingWindow was set but startingSurface==null, couldn't remove", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2024464438": { - "message": "app-onAnimationFinished(): mOuter=%s", + "-2178757341169633804": { + "message": "Tried to remove starting window but startingWindow was null: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "5521236266092347335": { + "message": "reparent: moving activity=%s to new task fragment in task=%d at %d", + "level": "INFO", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "-9024836052864189016": { + "message": "moveFocusableActivityToTop: unfocusable activity=%s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2014162875": { - "message": "Could not register window container listener token=%s, container=%s", - "level": "ERROR", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowContextListenerController.java" + "134255351804410010": { + "message": "moveFocusableActivityToTop: already on top and focused, activity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2012562539": { - "message": "startAnimation(): Notify animation start:", + "-1058622321669556178": { + "message": "moveFocusableActivityToTop: set focused, activity=%s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-2010331310": { - "message": "resumeTopActivity: Top activity resumed (dontWaitForPause) %s", + "731006689098152100": { + "message": "moveFocusableActivityToTop: activity=%s", "level": "DEBUG", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "3707721620395081349": { + "message": "Finishing activity r=%s, result=%d, data=%s, reason=%s", + "level": "VERBOSE", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1980468143": { - "message": "DisplayArea appeared name=%s", + "-3691592300155948194": { + "message": "Finish needs to pause: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1979455254": { - "message": "Launch on display check: allow launch for caller present on the display", + "5813636479397543744": { + "message": "Finish waiting for pause of: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "-2989211291975863399": { + "message": "destroyIfPossible: r=%s destroy returned removed=%s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_CONTAINERS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1976930686": { - "message": "Attempted to add Accessibility overlay window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3169053633576517098": { + "message": "Enqueueing pending finish: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1973119651": { - "message": "SyncGroup %d: Adding to group: %s", + "9050478058743283018": { + "message": "activity %s already destroying, skipping request with reason:%s", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1969928125": { - "message": "Animation start for %s, anim=%s", - "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + "5672598223877126839": { + "message": "Moving to DESTROYING: %s (destroy requested)", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1963461591": { - "message": "Removing %s from %s", + "-1834399855266808961": { + "message": "Moving to DESTROYED: %s (destroy skipped)", "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "3282063745558462269": { + "message": "Moving to DESTROYED: %s (no app)", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "8836546031252812807": { + "message": "Removing activity %s, reason= %s callers=%s", + "level": "INFO", "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1963363332": { - "message": "Restart top activity process of Task taskId=%d", + "8348126473928520781": { + "message": "Moving to DESTROYED: %s (removed from history)", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1961637874": { - "message": "DeferredDisplayUpdater: applying DisplayInfo immediately", + "-8001673213497887656": { + "message": "activityDestroyedLocked: r=%s", "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" + "group": "WM_DEBUG_CONTAINERS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1949279037": { - "message": "Attempted to add input method window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "587363723665813898": { + "message": "Removing activity %s hasSavedState=%b stateNotNeeded=%s finishing=%b state=%s callers=%s", + "level": "INFO", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1939861963": { - "message": "Create root task displayId=%d winMode=%d", + "-1842512343787359105": { + "message": "Removing app token: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1938839202": { - "message": "SURFACE LEAK DESTROY: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "5548174277852675449": { + "message": "Removing app %s delayed=%b animation=%s animating=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "-601582700132879947": { + "message": "removeAppToken: %s delayed=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "3478214322581157355": { + "message": "removeAppToken make exiting: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1938204785": { + "-7226216420432530281": { + "message": "Removing focused app token:%s displayId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "8361394136152947990": { "message": "Moving existing starting %s from %s to %s", "level": "VERBOSE", "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1933723759": { - "message": "Clear animatingExit: reason=relayoutVisibleWindow win=%s", - "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "-3450064502566932331": { + "message": "Removing starting %s from %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1924376693": { - "message": " Setting Ready-group to %b. group=%s from %s", + "8639603536400037285": { + "message": "Moving pending starting from %s to %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1918702467": { - "message": "onSyncFinishedDrawing %s", + "-3452055378690362514": { + "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1915280162": { - "message": "Attempted to add wallpaper window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "1728033820691545386": { + "message": "No longer Stopped: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1906387645": { - "message": "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "5062176994575790703": { + "message": "TRANSIT_FLAG_OPEN_BEHIND, adding %s to mOpeningApps", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1905191109": { - "message": "SyncGroup %d: Finished!", + "-477271988506706928": { + "message": "commitVisibility: %s: visible=%b visibleRequested=%b, isInTransition=%b, runningAnimation=%b, caller=%s", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1895337367": { - "message": "Delete root task display=%d winMode=%d", + "-6873410057142191118": { + "message": "State movement: %s from:%s to:%s reason:%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1886145147": { - "message": "resumeTopActivity: Going to sleep and all paused", - "level": "DEBUG", + "4437231720834282527": { + "message": "State unchanged from:%s", + "level": "VERBOSE", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1885450608": { - "message": "Content Recording: Successfully created a ContentRecordingSession for displayId=%d to mirror content from displayId=%d", + "926038819327785799": { + "message": "notifyAppResumed: wasStopped=%b %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1884933373": { - "message": "enableScreenAfterBoot: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "1734586111478674085": { + "message": "Resumed activity; dropping state of: %s", "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "-1872288685": { - "message": "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1868518158": { - "message": "Pending back animation due to another animation is running", - "level": "WARN", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "-69666241054231397": { + "message": "Refreshed activity: %s", + "level": "INFO", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1868124841": { - "message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b", + "1256300416726217367": { + "message": "Activity paused: token=%s, timeout=%b", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1868048288": { - "message": "Updating to new configuration after starting activity.", + "6879640870754727133": { + "message": "Moving to PAUSED: %s %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityStarter.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1862269827": { - "message": "applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s", + "2737811012914917932": { + "message": "Executing finish of failed to pause activity: %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1844540996": { - "message": " Initial targets: %s", + "-2566496855129705006": { + "message": "Waiting for pause to complete...", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1838803135": { - "message": "Attempted to set windowing mode to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7498807658620137882": { + "message": "no-history finish of %s", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1834214907": { - "message": "createNonAppWindowAnimations()", + "3207149655622038378": { + "message": "Not finishing noHistory %s on stop because we're just sleeping", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1828118576": { - "message": "SyncGroup %d: Started %sfor listener: %s", + "-2530718588485487045": { + "message": "Moving to STOPPING: %s (stop requested)", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1824578273": { - "message": "Reporting new frame to %s: %s", + "-8424334454318351870": { + "message": "Stop failed; moving to STOPPED: %s", "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "-1818910559": { - "message": "DeferredDisplayUpdater: applied DisplayInfo after deferring", - "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1814361639": { - "message": "Set IME snapshot position: (%d, %d)", + "-4913512058893421188": { + "message": "Saving icicle of %s: %s", "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1812743677": { - "message": "Display id=%d is ignoring all orientation requests, camera is active and the top activity is eligible for force rotation, return %s,portrait activity: %b, is natural orientation portrait: %b.", + "7613353074402340933": { + "message": "Moving to STOPPED: %s (stop complete)", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1810446914": { - "message": "Trying to update display configuration for system\/invalid process.", - "level": "WARN", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "3981777934616509782": { + "message": "Scheduling idle now: forceIdle=%b immediate=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1800899273": { - "message": "applyAnimation: anim=%s transit=%s Callers=%s", + "1083992181663415298": { + "message": "Skipping set freeze of %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1792633344": { - "message": "Register task organizer=%s uid=%d", + "3713860954819212080": { + "message": "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, + "7696002120820208745": { + "message": "Clear freezing of %s force=%b", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1791031393": { - "message": "Ensuring correct configuration: %s", + "-8387262166329116492": { + "message": "No longer freezing: %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", + "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1782453012": { - "message": "Checking theme of starting window: 0x%x", + "-6965298896142649709": { + "message": "Finish starting %s: first real window is shown, no animation", "level": "VERBOSE", "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1777196134": { - "message": "goodToGo(): No apps to animate, mPendingAnimations=%d", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "3235691043029201724": { + "message": "Setting mOrientationChangeComplete=true because wtoken %s numInteresting=%d numDrawn=%d", + "level": "INFO", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1777010776": { - "message": "create IME snapshot for %s, buff width=%s, height=%s", + "5991628884266137609": { + "message": "Creating animation bounds layer", "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1768557332": { - "message": "removeWallpaperAnimation()", + "-1836789237982086339": { + "message": "No thumbnail header bitmap for: %s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1764792832": { - "message": "Start collecting in Transition: %s", + "-8809523216004991008": { + "message": "Animation done in %s: reportedVisible=%b okToDisplay=%b okToAnimate=%b startingDisplayed=%b", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" - }, - "-1750206390": { - "message": "Exception thrown when creating surface for client %s (%s). %s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1747461042": { - "message": "set mOrientationChanging of %s", + "-9178011226407552682": { + "message": "Setting requested orientation %s for %s", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowState.java" + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1740512980": { - "message": "Stopping %s: nowVisible=%b animating=%b finishing=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "-1963190756391505590": { + "message": "Sandbox max bounds for uid %s to bounds %s. config to never sandbox = %s, config to always sandbox = %s, letterboxing from mismatch with parent bounds = %s, has mCompatDisplayInsets = %s, should create compatDisplayInsets = %s", + "level": "DEBUG", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1730156332": { - "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d", + "2612201759169917322": { + "message": "Pausing configuration dispatch for %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1728919185": { - "message": " unrelated invisible sibling %s", + "5153784493059555057": { + "message": "Resuming configuration dispatch for %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1710206702": { - "message": "Display id=%d is frozen while keyguard locked, return %d", + "-8630021188868292872": { + "message": "Skipping config check (will change): %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1707370822": { - "message": "Ready to stop: %s", + "-3976984054291875926": { + "message": "Configuration doesn't matter in finishing %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" - }, - "-1704402370": { - "message": "resetTaskIntendedTask: calling finishActivity on %s", - "level": "WARN", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1700778361": { - "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s", + "-1036762753077003128": { + "message": "Skipping config check in destroyed state %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" - }, - "-1699018375": { - "message": "Adding activity %s to task %s callers: %s", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/Task.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1679411993": { - "message": "setVr2dDisplayId called for: %d", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "-6543078196636665108": { + "message": "Skipping config check invisible: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1671601441": { - "message": "attachWindowContextToDisplayContent: calling from non-existing process pid=%d uid=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-3588725633248053181": { + "message": "Ensuring correct configuration: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1670695197": { - "message": "Attempted to add presentation window to a non-suitable display. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "4672360193194734037": { + "message": "Configuration & display unchanged in %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1647332198": { - "message": "remove RecentTask %s when finishing user %d", - "level": "INFO", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RecentTasks.java" + "-8624278141553396410": { + "message": "Skipping config check for initializing activity: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1643780158": { - "message": "Saving original orientation before camera compat, last orientation is %d", + "2485365009287691179": { + "message": "Configuration no differences in %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1639406696": { - "message": "NOSENSOR override detected", + "-8909639363543223474": { + "message": "Configuration changes for %s, allChanges=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1638958146": { - "message": "Removing activity %s from task=%s adding to task=%s Callers=%s", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + "-8048404379899908050": { + "message": "Configuration doesn't matter not running %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1633115609": { - "message": "Key dispatch not paused for screen off", + "4979286847769557939": { + "message": "Checking to restart %s: changed=0x%s, handles=0x%s, mLastReportedConfiguration=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1632122349": { - "message": "Changing surface while display frozen: %s", + "6779426581354721909": { + "message": "Config is relaunching %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1631991057": { - "message": "Display id=%d is notified that Camera %s is closed but activity is still refreshing. Rescheduling an update.", + "8969401915706456725": { + "message": "Config is relaunching invisible activity %s called by %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1630752478": { - "message": "removeLockedTask: removed %s", - "level": "DEBUG", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "328802837600679598": { + "message": "Moving to %s Relaunching %s callers=%s", + "level": "INFO", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1598452494": { - "message": "activityDestroyedLocked: r=%s", + "-3997125892953197985": { + "message": "Resumed after relaunch %s", "level": "DEBUG", - "group": "WM_DEBUG_CONTAINERS", + "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1596995693": { - "message": "startAnimation", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "1665699123574159131": { + "message": "Starting activity when config will change = %b", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityStarter.java" }, - "-1585311008": { + "4748139468532105082": { + "message": "Updating to new configuration after starting activity.", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityStarter.java" + }, + "-2867366986304729": { "message": "Bring to front target: %s from %s", "level": "DEBUG", "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityStarter.java" }, - "-1583619037": { - "message": "Failed to register MediaProjectionWatcherCallback", - "level": "ERROR", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/ScreenRecordingCallbackController.java" + "-2190454940975874759": { + "message": "Starting new activity %s in new task %s", + "level": "VERBOSE", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityStarter.java" }, - "-1582845629": { - "message": "Starting animation on %s", + "5445799252721678675": { + "message": "Initial config: %s", "level": "VERBOSE", - "group": "WM_DEBUG_DIMMER", - "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1575977269": { - "message": "Skipping %s: mismatch root %s", + "-3811526397232923712": { + "message": "Cannot launch dream activity due to invalid state. dream component: %s packageName: %s", + "level": "ERROR", + "group": "WM_DEBUG_DREAM", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + }, + "-6981899770129924827": { + "message": "Dream packageName does not match active dream. Package %s does not match %s", + "level": "ERROR", + "group": "WM_DEBUG_DREAM", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + }, + "6075150529915862250": { + "message": "Applying new update lock state '%s' for %s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_IMMERSIVE", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1568331821": { - "message": "Enabling listeners", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "-4356952232698761083": { + "message": "setFocusedRootTask: taskId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1567866547": { - "message": "Collecting in transition %d: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "301842347780487555": { + "message": "setFocusedTask: taskId=%d touchedActivity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1564228464": { - "message": "App died while pausing: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "7095858131234795548": { + "message": "moveTaskToFront: moving taskId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1559645910": { - "message": "Looking for task of type=%s, taskAffinity=%s, intent=%s, info=%s, preferredTDA=%s", + "-4458288191054594222": { + "message": "Could not find task for id: %d", "level": "DEBUG", "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1558137010": { - "message": "Config is relaunching invisible activity %s called by %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-1136891560663761442": { + "message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1554521902": { - "message": "showInsets(ime) was requested by different window: %s ", + "6954122272402912822": { + "message": "startLockTaskMode: %s", "level": "WARN", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1545962566": { - "message": "View server did not start", + "-829638795650515884": { + "message": "Allowlisting %d:%s", "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1539974875": { - "message": "removeAppToken: %s delayed=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "893763316922465955": { + "message": "moveRootTaskToDisplay: moving taskId=%d to displayId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1526645239": { - "message": "Timeout waiting for drawn: undrawn=%s", + "8392804603924461448": { + "message": "%s: caller %d is using old GET_TASKS but privileged; allowing", "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1518132958": { - "message": "fractionRendered boundsOverSource=%f", - "level": "VERBOSE", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "4303745325174700522": { + "message": "%s: caller %d does not hold REAL_GET_TASKS; limiting output", + "level": "WARN", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1517908912": { - "message": "requestScrollCapture: caught exception dispatching to window.token=%s", + "-559595900417262876": { + "message": "Allowing features %d:0x%s", "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1501564055": { - "message": "Organized TaskFragment is not ready= %s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "2008996027621913637": { + "message": "Updating global configuration to: %s", + "level": "INFO", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1499134947": { - "message": "Removing starting %s from %s", + "-6404059840638143757": { + "message": "Update process config of %s to new config %s", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "-1497837552": { - "message": "onAnimationFinished(): mPendingAnimations=%d", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1495062622": { - "message": "Can't report activity moved to display - client not running, activityRecord=%s, displayId=%d", + "2959074735946674755": { + "message": "Trying to update display configuration for system\/invalid process.", "level": "WARN", - "group": "WM_DEBUG_SWITCH", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1492881555": { - "message": "Starting activity when config will change = %b", - "level": "VERBOSE", + "5668810920995272206": { + "message": "Trying to update display configuration for invalid process, pid=%d", + "level": "WARN", "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityStarter.java" + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1483435730": { - "message": "InsetsSource setWin %s for type %s", + "-1123414663662718691": { + "message": "setVr2dDisplayId called for: %d", "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "-1480918485": { - "message": "Refreshed activity: %s", - "level": "INFO", + "7803197981786977817": { + "message": "no-history finish of %s on new resume", + "level": "DEBUG", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1480772131": { - "message": "No app or window is requesting an orientation, return %d for display id=%d", + "4094852138446437211": { + "message": "realStartActivityLocked: Skipping start of r=%s some activities pausing...", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1478175541": { - "message": "No longer animating wallpaper targets!", + "1045761390992110034": { + "message": "Moving to PAUSED: %s (starting in paused state)", "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "-8529426827020190143": { + "message": "Launch on display check: displayId=%d callingPid=%d callingUid=%d", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1474602871": { + "9147909968067116569": { + "message": "Launch on display check: no caller info, skip check", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "4781135167649953680": { + "message": "Launch on display check: allow launch any on display", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "7828411869729995271": { "message": "Launch on display check: disallow launch on virtual display for not-embedded activity.", "level": "DEBUG", "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1474292612": { - "message": "Could not find task for id: %d", + "-2215878620906309682": { + "message": "Launch on display check: disallow activity embedding without permission.", "level": "DEBUG", "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1471518109": { - "message": "Set animatingExit: reason=onAppVisibilityChanged win=%s", + "986565579776405555": { + "message": "Launch on display check: %s launch for userId=%d on displayId=%d", "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1468740466": { - "message": "Moving to PAUSED: %s (starting in paused state)", + "-2201418325681949201": { + "message": "Launch on display check: allow launch for owner of the display", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "-4258279435559028377": { + "message": "Launch on display check: allow launch for caller present on the display", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "1496536241884839051": { + "message": "Stopping %s: nowVisible=%b animating=%b finishing=%s", "level": "VERBOSE", "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1452274694": { - "message": " CAN PROMOTE: promoting to parent %s", + "5677125188685281770": { + "message": "Ready to stop: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, - "-1449515133": { - "message": "Content Recording: stopping active projection for display %d", + "3604633008357193496": { + "message": "Waiting for top state to be released by %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "3997062844427155487": { + "message": "Top resumed state released %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + }, + "-4049608245387511746": { + "message": "applyAnimation: override requested, but it is prohibited by policy.", "level": "ERROR", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1443029505": { - "message": "SAFE MODE ENABLED (menu=%d s=%d dpad=%d trackball=%d)", - "level": "INFO", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-2133100418670643322": { + "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1442613680": { - "message": " Creating Ready-group for Transition %d with root=%s", + "6121116119545820299": { + "message": "applyAnimation: anim=%s transit=%s Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1438175584": { - "message": "Input focus has changed to %s display=%d", + "-8382864384468306610": { + "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s isEntrance=%b Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/InputMonitor.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1434147454": { - "message": "cleanupAnimation(): Notify animation finished mPendingAnimations=%d reorderMode=%d", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "222576013987954454": { + "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE transit=%s Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1432963966": { - "message": "Moving to DESTROYING: %s (destroy requested)", + "4808089291562562413": { + "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL transit=%s Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1427184084": { - "message": "addWindow: New client %s: window=%s Callers=%s", + "-1463563572526433695": { + "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1421296808": { - "message": "Moving to RESUMED: %s (in existing)", + "-8749850292010208926": { + "message": "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1419762046": { - "message": "moveRootTaskToDisplay: moving taskId=%d to displayId=%d", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "5939232373291430513": { + "message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1419461256": { - "message": "resumeTopActivity: Resumed %s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "9082776604722675018": { + "message": "applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1413901262": { - "message": "startRecentsActivity(): intent=%s", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "-1218632020771063497": { + "message": "applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b canCustomizeAppTransition=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1410260105": { - "message": "Schedule IME show for %s", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "6217525691846442213": { + "message": "Override pending remote transitionSet=%b adapter=%s", + "level": "INFO", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1397175017": { - "message": "Other orientation overrides are in place: not reverting", + "5233255302148535928": { + "message": "*** APP TRANSITION TIMEOUT. displayId=%d isTransitionSet()=%b mOpeningApps.size()=%d mClosingApps.size()=%d mChangingApps.size()=%d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransition.java" }, - "-1394745488": { - "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s", - "level": "INFO", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + "-5726018006883159788": { + "message": "Delaying app transition for recents animation to finish", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1391944764": { - "message": "SURFACE DESTROY: %s. %s", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "6514556033257323299": { + "message": "**** GOOD TO GO", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1389772804": { - "message": "Attempted to add voice interaction window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3518082157667760495": { + "message": "handleAppTransitionReady: displayId=%d appTransition={%s} openingApps=[%s] closingApps=[%s] transit=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1383884640": { - "message": " allReady query: used=%b override=%b defer=%d states=[%s]", + "-2503124388387340567": { + "message": "Wallpaper animation!", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1376035390": { - "message": "No task found", + "855146509305002043": { + "message": "We don't support remote animation for Task with multiple TaskFragmentOrganizers.", + "level": "ERROR", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" + }, + "59396412370137517": { + "message": "Override with TaskFragment remote animation for transit=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" + }, + "2280055488397326910": { + "message": "Task=%d contains embedded TaskFragment. Disabled all input during TaskFragment remote animation.", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1364754753": { - "message": "Task vanished taskId=%d", + "-3156084190956669377": { + "message": "Changing app %s visible=%b performLayout=%b", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1352076759": { - "message": "Removing app token: %s", + "-8226278785414579647": { + "message": "getAnimationTarget in=%s, out=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/AppTransitionController.java" + }, + "4418653408751596915": { + "message": "Now opening app %s", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1350198040": { - "message": "hideBootMessagesLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-8367738619313176909": { + "message": "Now closing app %s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1340540100": { - "message": "Creating SnapshotStartingData", + "1855459282905873641": { + "message": "Now changing app %s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1325565952": { - "message": "Attempted to get home support flag of a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "2951634988136738868": { + "message": "Checking %d opening apps (frozen=%b timeout=%b)...", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1323783276": { - "message": "performEnableScreen: bootFinished() failed.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "4963754906024950916": { + "message": "Delaying app transition for screen rotation animation to finish", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1318478129": { - "message": "applyAnimation: win=%s anim=%d attr=0x%x a=%s transit=%d type=%d isEntrance=%b Callers %s", + "5073676463280304697": { + "message": "Check opening app=%s: allDrawn=%b startingDisplayed=%b startingMoved=%b isRelaunching()=%b startingWindow=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1311436264": { - "message": "Unregister task fragment organizer=%s uid=%d pid=%d", + "3437142041296647115": { + "message": "isFetchingAppTransitionSpecs=true", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1305966693": { - "message": "Sending position change to %s, onTop: %b", + "1461079689316480707": { + "message": "unknownApps is not empty: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1305791032": { - "message": "Moving to STOPPED: %s (stop complete)", + "3579533288018884842": { + "message": "Organized TaskFragment is not ready= %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-1305755880": { - "message": "Initial config: %s", + "495867940519492701": { + "message": "SyncGroup %d: onSurfacePlacement checking %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1304806505": { - "message": "Starting new activity %s in new task %s", + "8452501904614439940": { + "message": "SyncGroup %d: Unfinished dependencies: %s", "level": "VERBOSE", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityStarter.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1303628829": { - "message": "**** STARTING EXIT", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/DisplayPolicy.java" + "616739530932040800": { + "message": "SyncGroup %d: Unfinished container: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1292329638": { - "message": "Added starting %s: startingWindow=%s startingView=%s", + "6649777898123506907": { + "message": "SyncGroup %d: Finished!", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1288007399": { - "message": "performShowLocked: mDrawState=HAS_DRAWN in %s", + "4174320302463990554": { + "message": "PendingStartTransaction found", "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1277068810": { - "message": "startBackNavigation currentTask=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "6310906192788668020": { + "message": "SyncGroup %d: Set ready %b", + "level": "VERBOSE", + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1263316010": { - "message": "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and oldRotation=%s (%d)", + "-476337038362199951": { + "message": "SyncGroup %d: Adding to group: %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1259022216": { - "message": "SURFACE HIDE ( %s ): %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + "-2978812352001196863": { + "message": "SyncGroup %d: Started %sfor listener: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, - "-1258739769": { - "message": "onTransactionReady, opening: %s, closing: %s, animating: %s, match: %b", - "level": "DEBUG", + "-699215053676660941": { + "message": "No focused window, defaulting to top current task's window", + "level": "WARN", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1257821162": { - "message": "OUT SURFACE %s: copied", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "-1256520588": { - "message": "performEnableScreen: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "-1253056469": { - "message": "Launch on display check: %s launch for userId=%d on displayId=%d", + "-1459414342866553129": { + "message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1248645819": { - "message": "\tAdd container=%s", + "2881085074175114605": { + "message": "Focused window didn't have a valid surface drawn.", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, - "-1243510456": { - "message": "Dim animation requested: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_DIMMER", - "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1237827119": { - "message": "Schedule remove starting %s startingWindow=%s animate=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-6183551796617134986": { + "message": "Focus window is closing.", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1228653755": { - "message": "Launch on display check: displayId=%d callingPid=%d callingUid=%d", + "4039315468791789889": { + "message": "startBackNavigation currentTask=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1219773477": { - "message": "setInputConsumerEnabled(%s): mCanceled=%b", + "8456834061534378653": { + "message": "Previous Destination is Activity:%s Task:%s removedContainer:%s, backType=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1217596375": { - "message": "Content Recording: Display %d has no content and is on, so start recording for state %d", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "4900967164780429209": { + "message": "Pending back animation due to another animation is running", + "level": "WARN", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1209762265": { - "message": "Registering listener=%s with id=%d for window=%s with %s", + "-6431452312492819825": { + "message": "onTransactionReady, opening: %s, closing: %s, animating: %s, match: %b", "level": "DEBUG", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1209252064": { - "message": "Clear animatingExit: reason=clearAnimatingFlags win=%s", + "-4051770154814262074": { + "message": "Handling the deferred animation after transition finished", "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1207757583": { - "message": "startAnimation(): Notify animation start: %s", + "2077221835543623088": { + "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1204565480": { - "message": "Adding display switch to existing collecting transition", + "-4442170697458371588": { + "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s", "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/PhysicalDisplaySwitchTransitionLauncher.java" - }, - "-1198579104": { - "message": "Pushing next activity %s out to target's task %s", - "level": "VERBOSE", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1193946201": { - "message": "Can't report activity position update - client not running, activityRecord=%s", - "level": "WARN", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "267946503010201613": { + "message": "onBackNavigationDone backType=%s, triggerBack=%b", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" }, - "-1187377055": { - "message": "Enqueue pending stop if needed: %s wasStopping=%b visibleRequested=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "-2963535976860666511": { + "message": " BLACK %s: CREATE layer=%d", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/BlackFrame.java" }, - "-1185473319": { - "message": "ControlAdapter startAnimation mSource: %s controlTarget: %s", + "-5633771912572750947": { + "message": " BLACK %s: DESTROY", "level": "INFO", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/BlackFrame.java" }, - "-1164930508": { - "message": "Moving to RESUMED: %s (starting new instance) callers=%s", + "-74949168947384056": { + "message": "Sending to proc %s new compat %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/Task.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/CompatModePackages.java" }, - "-1156314529": { + "-6620483833570774987": { "message": "Content Recording: Unexpectedly null window container; unable to update recording for display %d", "level": "VERBOSE", "group": "WM_DEBUG_CONTENT_RECORDING", "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1156118957": { - "message": "Updated config=%s", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" - }, - "-1153814764": { - "message": "onAnimationCancelled", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" - }, - "-1152771606": { + "7226080178642957768": { "message": "Content Recording: Display %d was already recording, but pause capture since the task is in PIP", "level": "VERBOSE", "group": "WM_DEBUG_CONTENT_RECORDING", "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1145384901": { - "message": "shouldWaitAnimatingExit: isTransition: %s", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowState.java" + "-311001578548807570": { + "message": "Content Recording: Display %d was already recording, so apply transformations if necessary", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1142279614": { - "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", + "2350883351096538149": { + "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1136734598": { - "message": "Content Recording: Ignoring session on same display %d, with an existing session %s", + "8446758574558556540": { + "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s, since the surface is not available.", "level": "VERBOSE", "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1136467585": { - "message": "The listener does not exist.", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowContextListenerController.java" + "-4320004054011530388": { + "message": "Content Recording: Display %d has content (%b) so pause recording", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1136139407": { - "message": "no-history finish of %s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "5951434375221687741": { + "message": "Content Recording: Stop MediaProjection on virtual display %d", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1130891072": { - "message": "Orientation continue waiting for draw in %s", + "-3395581813971405090": { + "message": "Content Recording: waiting to record, so do nothing", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1130868271": { - "message": "Resizing %s WITH DRAW PENDING", - "level": "INFO", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowState.java" + "6779858226066635065": { + "message": "Content Recording: Display %d should start recording, but don't yet since the task is in PIP", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1117599386": { - "message": "Deferring rotation, display is not enabled.", + "7051210836345306671": { + "message": "Content Recording: Unable to start recording for display %d since the surface is not available.", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1115019498": { - "message": "Configuration & display unchanged in %s", + "2255758299558330282": { + "message": "Content Recording: Display %d has no content and is on, so start recording for state %d", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1113134997": { - "message": "Attempted to add application window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "2269158922723670768": { + "message": "Unable to retrieve window container to start recording for display %d", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1108775960": { - "message": "%s is requesting orientation %d (%s)", + "-2177493963028285555": { + "message": "Content Recording: Unable to start recording due to null token for display %d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1104347731": { - "message": "Setting requested orientation %s for %s", + "-928577038848872043": { + "message": "Content Recording: Unable to retrieve task to start recording for display %d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1103716954": { - "message": "Not removing %s due to exit animation", + "-3564317873468917405": { + "message": "Content Recording: Unable to start recording due to invalid region for display %d", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1103115659": { - "message": "Performing post-rotate rotation", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "1100676037289065396": { + "message": "Content Recording: Apply transformations of shift %d x %d, scale %f x %f, crop (aka recorded content size) %d x %d for display %d; display has size %d x %d; surface has size %d x %d", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1101551167": { - "message": "Auto-PIP allowed, entering PIP mode directly: %s, didAutoPip: %b", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "2330946591287751995": { + "message": "Content Recording: Provided surface for recording on display %d is not present, so do not update the surface", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1097851684": { - "message": "Content Recording: Unable to start recording due to null token for display %d", + "7993045936648632984": { + "message": "Content Recording: Recorded task is removed, so stop recording on display %d", "level": "VERBOSE", "group": "WM_DEBUG_CONTENT_RECORDING", "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1089874824": { - "message": "SURFACE SHOW (performLayout): %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + "3197882223327917085": { + "message": "Content Recording: stopping active projection for display %d", + "level": "ERROR", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1075136930": { - "message": "startLockTaskMode: Can't lock due to auth", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "4391984931064789228": { + "message": "Content Recording: Unable to tell MediaProjectionManagerService to stop the active projection for display %d: %s", + "level": "ERROR", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1069336896": { - "message": "onRootTaskOrderChanged(): rootTask=%s", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "6721270269112237694": { + "message": "Content Recording: Unable to tell MediaProjectionManagerService about resizing the active projection: %s", + "level": "ERROR", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" }, - "-1060529098": { - "message": " Skipping post-transition snapshot for task %d", + "1600318776990120244": { + "message": "Content Recording: Unable to tell MediaProjectionManagerService about visibility change on the active projection: %s", + "level": "ERROR", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" + }, + "-1451477179301743956": { + "message": "Content Recording: Unable to tell log windowing mode change: %s", + "level": "ERROR", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" + }, + "-225319884529912382": { + "message": "Content Recording: Accept session updating same display %d with granted consent, with an existing session %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecordingController.java" }, - "-1060365734": { - "message": "Attempted to add QS dialog window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-5981322449150461244": { + "message": "Content Recording: Ignoring session on same display %d, with an existing session %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecordingController.java" }, - "-1047945589": { - "message": "Remove client=%x, surfaceController=%s Callers=%s", + "4226710957373144819": { + "message": "Content Recording: Handle incoming session on display %d, with a pre-existing session %s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecordingController.java" }, - "-1043981272": { - "message": "Reverting orientation. Rotating to %s from %s rather than %s.", + "-1415855962859555663": { + "message": "Content Recording: Incoming session on display %d can't be set since it is already null; the corresponding VirtualDisplay must have already been removed.", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecordingController.java" }, - "-1042574499": { - "message": "Attempted to add Accessibility overlay window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-5750232782380780139": { + "message": "Content Recording: Pause the recording session on display %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecordingController.java" }, - "-1033630971": { - "message": "onBackNavigationDone backType=%s, triggerBack=%b", + "-8058211784911995417": { + "message": "DeferredDisplayUpdater: applying DisplayInfo immediately", "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" }, - "-1028213464": { - "message": "%s skipping animation and directly setting alpha=%f, blur=%d", + "1944392458089872195": { + "message": "DeferredDisplayUpdater: partially applying DisplayInfo immediately", "level": "DEBUG", - "group": "WM_DEBUG_DIMMER", - "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" }, - "-1022146708": { - "message": "Skipping %s: mismatch activity type", + "8391643185322408089": { + "message": "DeferredDisplayUpdater: deferring DisplayInfo update", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" }, - "-1016578046": { - "message": "Moving to %s Relaunching %s callers=%s", - "level": "INFO", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-915675022936690176": { + "message": "DeferredDisplayUpdater: applied DisplayInfo after deferring", + "level": "DEBUG", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" }, - "-1009117329": { - "message": "isFetchingAppTransitionSpecs=true", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "3778139410556664218": { + "message": "%s skipping animation and directly setting alpha=%f, blur=%d", + "level": "DEBUG", + "group": "WM_DEBUG_DIMMER", + "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, - "-1005167552": { - "message": "Playing #%d in parallel on track #%d", + "-6357087772993832060": { + "message": "Starting animation on %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_DIMMER", + "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, - "-1003678883": { - "message": "Cleaning splash screen token=%s", + "-1187783168730646350": { + "message": "Dim animation requested: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_DIMMER", + "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, - "-1003060523": { - "message": "Finish needs to pause: %s", + "2230151187668089583": { + "message": "%s forcing orientation to %d for display id=%d", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayArea.java" }, - "-993378225": { - "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", + "3968604152682328317": { + "message": "Register display organizer=%s uid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_DRAW", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-986746907": { - "message": "Starting window removed %s", - "level": "DEBUG", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/WindowState.java" + "-3066370283926570943": { + "message": "Don't organize or trigger events for untrusted displayId=%d", + "level": "WARN", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-962760979": { - "message": "thawRotation: mRotation=%d, caller=%s", + "-943497726140336963": { + "message": "Unregister display organizer=%s uid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-961053385": { - "message": "attachWindowContextToDisplayArea: calling from non-existing process pid=%d uid=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "5147103403966149923": { + "message": "Create TaskDisplayArea uid=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-957060823": { - "message": "Moving to PAUSING: %s", + "-1659480097203667175": { + "message": "Delete TaskDisplayArea uid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-951939129": { - "message": "Unregister task organizer=%s uid=%d", + "-4514772405648277945": { + "message": "DisplayArea appeared name=%s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-948446688": { - "message": "Create TaskDisplayArea uid=%d", + "995846188225477231": { + "message": "DisplayArea vanished name=%s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-938271693": { - "message": "allResumedActivitiesIdle: rootTask=%d %s not idle", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-1007032390526684388": { + "message": "DisplayArea info changed name=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, - "-937498525": { - "message": "Executing finish of failed to pause activity: %s", + "4917824058925068521": { + "message": "The TaskDisplayArea with %s does not exist.", + "level": "WARN", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/DisplayAreaPolicyBuilder.java" + }, + "1432179297701477868": { + "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-930893991": { - "message": "Set sync ready, syncId=%d", + "-1998969924927409574": { + "message": "findFocusedWindow: focusedApp=null using new focus @ %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/WindowOrganizerController.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-929676529": { - "message": "Configuration changes for %s, allChanges=%s", + "-1513212297283619351": { + "message": "findFocusedWindow: focusedApp windows not focusable using new focus @ %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-927199900": { - "message": "Updating global configuration to: %s", - "level": "INFO", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "271075236829935631": { + "message": "findFocusedWindow: Reached focused app=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-926231510": { - "message": "State unchanged from:%s", + "3066566560703920191": { + "message": "findFocusedWindow: Found new focus @ %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-921346089": { - "message": "Content Recording: Unable to tell MediaProjectionManagerService to stop the active projection for display %d: %s", - "level": "ERROR", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "-8667452489821572603": { + "message": "First draw done in potential wallpaper target %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-917215012": { - "message": "%s: caller %d is using old GET_TASKS but privileged; allowing", - "level": "WARN", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "6283995720623600346": { + "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s", + "level": "DEBUG", + "group": "WM_DEBUG_KEEP_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-916108501": { - "message": "Adding %s to %s", + "1959209522588955826": { + "message": "Acquiring screen wakelock due to %s", + "level": "DEBUG", + "group": "WM_DEBUG_KEEP_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "352937214222086717": { + "message": "Releasing screen wakelock, obscured by %s", + "level": "DEBUG", + "group": "WM_DEBUG_KEEP_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "2632363530212357762": { + "message": "Set mOrientationChanging of %s", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-914253865": { - "message": "Attempted to add voice interaction window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-9191821315942566105": { + "message": "Display id=%d is frozen while keyguard locked, return %d", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-894942237": { - "message": "Force Playing Transition: %d", + "-74384795669614579": { + "message": "Display id=%d is ignoring orientation request for %d, return %d following a per-app override for %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-888703350": { - "message": "Skipping %s", + "-3395592185328682328": { + "message": "Display id=%d is ignoring orientation request for %d, return %d", "level": "VERBOSE", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-883738232": { - "message": "Adding more than one toast window for UID at a time.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3438870491084701232": { + "message": "No app or window is requesting an orientation, return %d for display id=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-877494781": { - "message": "Start pushing activity %s out to bottom task %s", + "-1123818872155982592": { + "message": "findFocusedWindow: No focusable windows, display=%d", "level": "VERBOSE", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-874888131": { - "message": "Set transition ready=%b %d", + "-2192125645150932161": { + "message": "Current transition prevents automatic focus change", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-874446906": { - "message": "showBootMessage: msg=%s always=%b mAllowBootMessages=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "3101160328044493048": { + "message": "Changing focus from %s to %s displayId=%d Callers=%s", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "7634130879993688940": { + "message": "setFocusedApp %s displayId=%d Callers=%s", "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-874087484": { - "message": "SyncGroup %d: Set ready %b", - "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "-4130402450005935184": { + "message": "SURFACE LEAK DESTROY: %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-869242375": { - "message": "Content Recording: Unable to start recording due to invalid region for display %d", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "4464269036743635127": { + "message": "setInputMethodTarget %s", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-863438038": { - "message": "Aborting Transition: %d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "4835192778854186097": { + "message": "create IME snapshot for %s, buff width=%s, height=%s", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-861859917": { - "message": "Attempted to add window to a display that does not exist: %d. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "2408509162360028352": { + "message": "Set IME snapshot position: (%d, %d)", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-861707633": { - "message": "Destroying surface %s called by %s", + "2005731931732324688": { + "message": "remove IME snapshot, caller=%s", "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-856750101": { - "message": "Launch on display check: allow launch for owner of the display", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "-6495118720675662641": { + "message": "show IME snapshot, ime target=%s, callers=%s", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-856590985": { - "message": "dcTarget: %s mImeRequester: %s", - "level": "DEBUG", + "-4354595179162289537": { + "message": "setInputMethodInputTarget %s", + "level": "INFO", "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-853404763": { - "message": "\twallpaper=%s", + "2432701541536053712": { + "message": "DisplayContent: boot is waiting for window of type %d to be drawn", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-853226675": { - "message": "Attempted to add window with exiting application token .%s Aborting.", + "5683557566110711213": { + "message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b", + "level": "INFO", + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "-124113386733162358": { + "message": "onWindowAnimationFinished, wc=%s, type=%s, imeSnapshot=%s, target=%s", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "-1556099709547629010": { + "message": "ImeContainer just became organized. Reparenting under parent. imeParentSurfaceControl=%s", + "level": "INFO", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "1119786654111970652": { + "message": "ImeContainer just became organized but it doesn't have a parent or the parent doesn't have a surface control. mSurfaceControl=%s imeParentSurfaceControl=%s", + "level": "ERROR", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "7019634211809476510": { + "message": "Execute app transition: %s, displayId: %d Callers=%s", "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-846931068": { - "message": "Update camera compat control state to %s for taskId=%d", + "-3219913508985161450": { + "message": "Wallpaper layer changed: assigning layers + relayout", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-846078709": { - "message": "Configuration doesn't matter in finishing %s", + "-8165317816061445169": { + "message": "Content Recording: Display %d state was (%d), is now (%d), so update recording?", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-814760297": { - "message": "Looking for task of %s in %s", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "4162342172327950908": { + "message": "Content Recording: Attempting to mirror self on %d", + "level": "WARN", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-809771899": { - "message": "findFocusedWindow: Reached focused app=%s", + "5489691866309868814": { + "message": "Content Recording: Found no matching mirror display for id=%d for DEFAULT_DISPLAY. Nothing to mirror.", + "level": "WARN", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "-39794010824230928": { + "message": "Content Recording: Attempting to mirror %d from %d but no DisplayContent associated. Changing to mirror default display.", + "level": "WARN", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, + "6545352723229848841": { + "message": "Content Recording: Successfully created a ContentRecordingSession for displayId=%d to mirror content from displayId=%d", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", + "group": "WM_DEBUG_CONTENT_RECORDING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "-804217032": { - "message": "Skipping config check (will change): %s", + "-6228339285356824882": { + "message": "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, mScreenOnFully=%b, mKeyguardDrawComplete=%b, mWindowManagerDrawComplete=%b", + "level": "DEBUG", + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayPolicy.java" + }, + "-6028033043540330282": { + "message": "Finished screen turning on...", + "level": "INFO", + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/DisplayPolicy.java" + }, + "-7427596081878257508": { + "message": "selectAnimation in %s: transit=%d", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/DisplayPolicy.java" + }, + "-6269658847003264525": { + "message": "**** STARTING EXIT", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/DisplayPolicy.java" + }, + "-6776561147903919733": { + "message": "Deferring rotation, rotation is paused.", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-799396645": { - "message": "Display id=%d is notified that Camera %s is closed, updating rotation.", + "7439675997626642740": { + "message": "Deferring rotation, animation in progress.", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-787664727": { - "message": "Cannot launch dream activity due to invalid state. dream component: %s packageName: %s", - "level": "ERROR", - "group": "WM_DEBUG_DREAM", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "1104181226551849840": { + "message": "Deferring rotation, still finishing previous rotation", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-784959154": { - "message": "Attempted to add private presentation window to a non-private display. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-2222079183499215612": { + "message": "Deferring rotation, display is not enabled.", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-783405930": { - "message": "Performing post-rotate rotation", - "level": "DEBUG", + "662988298513100908": { + "message": "Reverting orientation. Rotating to %s from %s rather than %s.", + "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-779535710": { - "message": "Transition %d: Set %s as transient-launch", + "-7113483678655694375": { + "message": "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and oldRotation=%s (%d)", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-779095785": { - "message": " sibling is a participant with mode %s", + "-8809129029906317617": { + "message": "Display id=%d selected orientation %s (%d), got rotation %s (%d)", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-778347463": { - "message": "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b mDisplayFrozen=%b callers=%s", + "6753221849083491323": { + "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-775004869": { - "message": "Not a match: %s", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-1216224951455892544": { + "message": "Performing post-rotate rotation after seamless rotation", + "level": "INFO", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-774908272": { - "message": "Marking #%d animation as SYNC.", + "-7672508047849737424": { + "message": "selectRotationAnimation topFullscreen=%s rotationAnimation=%d forceJumpcut=%b", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/DisplayRotation.java" + }, + "-2426404033822048710": { + "message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-771177730": { - "message": "Removing focused app token:%s displayId=%d", + "7339471241580327852": { + "message": "rotationForOrientation(orient=%s (%d), last=%s (%d)); user=%s (%d) %s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-767091913": { - "message": "Content Recording: Handle incoming session on display %d, with a pre-existing session %s", + "5325136615007859122": { + "message": "Invalid surface rotation angle in config_deviceTabletopRotations: %d", + "level": "ERROR", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" + }, + "4616480353797749295": { + "message": "config_deviceTabletopRotations is not defined. Half-fold letterboxing will work inconsistently.", + "level": "WARN", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" + }, + "8852346340572084230": { + "message": "foldStateChanged: displayId %d, halfFoldStateChanged %s, saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, mLastOrientation: %d, mRotation: %d", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-766059044": { - "message": "Display id=%d selected orientation %s (%d), got rotation %s (%d)", + "-8674269704471038429": { + "message": "onProposedRotationChanged, rotation=%d", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-760801764": { - "message": "onAnimationCancelled", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" + "418312772547457152": { + "message": "Enabling listeners", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-760764543": { - "message": "Focus not requested for window=%s because it has no surface or is not focusable.", + "4641814558273780952": { + "message": "Disabling listeners", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/InputMonitor.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-754503024": { - "message": "Relayout %s: oldVis=%d newVis=%d. %s", - "level": "INFO", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7429138692709430028": { + "message": "Display id=%d is ignoring all orientation requests, camera is active and the top activity is eligible for force rotation, return %s,portrait activity: %b, is natural orientation portrait: %b.", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-743856570": { - "message": "shouldWaitAnimatingExit: isAnimating: %s", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowState.java" + "-7756685416834187936": { + "message": "Refreshing activity for camera compatibility treatment, activityRecord=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-743431900": { - "message": "Configuration no differences in %s", + "-5176775281239247368": { + "message": "Reverting orientation after camera compat force rotation", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-732715767": { - "message": "Unable to retrieve window container to start recording for display %d", + "-2188976047008497712": { + "message": "Saving original orientation before camera compat, last orientation is %d", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-729530161": { - "message": "Moving to DESTROYED: %s (no app)", + "-8302211458579221117": { + "message": "Display id=%d is notified that Camera %s is open for package %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-711194343": { - "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "-1534784331886673955": { + "message": "DisplayRotationCompatPolicy: Multi-window toast not shown as package '%s' cannot be found.", + "level": "ERROR", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-706481945": { - "message": "TaskFragment parent info changed name=%s parentTaskId=%d", + "1797195804376906831": { + "message": "Display id=%d is notified that Camera %s is closed, scheduling rotation update.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-705939410": { - "message": "Waiting for pause to complete...", + "-8746776274432739264": { + "message": "Display id=%d is notified that Camera %s is closed but activity is still refreshing. Rescheduling an update.", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-703543418": { - "message": " check sibling %s", + "3622181214422515679": { + "message": "Display id=%d is notified that Camera %s is closed, updating rotation.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" }, - "-702650156": { - "message": "Override with TaskFragment remote animation for transit=%s", + "-6949326633913532620": { + "message": "NOSENSOR override detected", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" }, - "-701167286": { - "message": "applyAnimation: transit=%s, enter=%b, wc=%s", + "-2060428960792625366": { + "message": "NOSENSOR override is absent: reverting", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" + }, + "-4296736202875980050": { + "message": "Other orientation overrides are in place: not reverting", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" }, - "-694710814": { + "7928129513685401229": { "message": "Pausing rotation during drag", "level": "DEBUG", "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DragState.java" }, - "-692907078": { - "message": "Handling the deferred animation after transition finished", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, - "-677449371": { - "message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b", + "8231481023986546563": { + "message": "Resuming rotation after drag", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" - }, - "-672355406": { - "message": " Rejecting as no-op: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DragState.java" }, - "-668956537": { - "message": " THUMBNAIL %s: CREATE", + "12662399232325663": { + "message": "DRAG %s: pos=(%d,%d)", "level": "INFO", "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/SurfaceFreezer.java" + "at": "com\/android\/server\/wm\/DragState.java" }, - "-666510420": { - "message": "With display frozen, orientationChangeComplete=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-1797662102094201628": { + "message": "Attempt to transfer touch gesture with non-existent embedded window", + "level": "WARN", + "group": "WM_DEBUG_EMBEDDED_WINDOWS", + "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" }, - "-658964693": { - "message": "onWindowAnimationFinished, wc=%s, type=%s, imeSnapshot=%s, target=%s", - "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "929964979835124721": { + "message": "Attempt to transfer touch gesture using embedded window with no associated host", + "level": "WARN", + "group": "WM_DEBUG_EMBEDDED_WINDOWS", + "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" }, - "-655104359": { - "message": "Frontmost changed immersion: %s", - "level": "DEBUG", - "group": "WM_DEBUG_IMMERSIVE", - "at": "com\/android\/server\/wm\/ActivityClientController.java" + "676191989331669410": { + "message": "Attempt to transfer touch gesture with host window not associated with embedded window", + "level": "WARN", + "group": "WM_DEBUG_EMBEDDED_WINDOWS", + "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" }, - "-653156702": { - "message": "createAppAnimations()", + "553249487221306249": { + "message": "Attempt to transfer touch gesture using embedded window that has no input channel", + "level": "WARN", + "group": "WM_DEBUG_EMBEDDED_WINDOWS", + "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + }, + "-8678904073078032058": { + "message": "Attempt to transfer touch gesture using a host window with no input channel", + "level": "WARN", + "group": "WM_DEBUG_EMBEDDED_WINDOWS", + "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + }, + "-786355099910065121": { + "message": "IME target changed within ActivityRecord", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-648891906": { - "message": "Activity not running or entered PiP, resuming next.", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "2634707843050913730": { + "message": "Schedule IME show for %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-641258376": { - "message": "realStartActivityLocked: Skipping start of r=%s some activities pausing...", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "8923821958256605927": { + "message": "Run showImeRunner", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-639217716": { - "message": "setFocusedApp %s displayId=%d Callers=%s", + "-3529253275087521638": { + "message": "call showInsets(ime) on %s", "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-637815408": { - "message": "Invalid surface rotation angle in config_deviceTabletopRotations: %d", - "level": "ERROR", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "7927729210300708186": { + "message": "showInsets(ime) was requested by different window: %s ", + "level": "WARN", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-636553602": { - "message": "commitVisibility: %s: visible=%b visibleRequested=%b, isInTransition=%b, runningAnimation=%b, caller=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-6529782994356455131": { + "message": "abortShowImePostLayout", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-635082269": { - "message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b", - "level": "INFO", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-6629998049460863403": { + "message": "dcTarget: %s mImeRequester: %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" }, - "-627759820": { - "message": "Display id=%d is notified that Camera %s is open for package %s", + "-8553129529717081823": { + "message": "Input focus has changed to %s display=%d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" }, - "-622997754": { - "message": "postWindowRemoveCleanupLocked: %s", + "4027486077547983902": { + "message": "App %s is focused, but the window is not ready. Start a transaction to remove focus from the window of non-focused apps.", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" }, - "-622017164": { - "message": "Finish Transition: %s", + "-8537908614386667236": { + "message": "Focus not requested for window=%s because it has no surface or is not focusable.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" }, - "-597091183": { - "message": "Delete TaskDisplayArea uid=%d", + "-6346673514571615151": { + "message": "Focus requested for window=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" }, - "-593535526": { - "message": "Binding proc %s with config %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/am\/ActivityManagerService.java" + "1522894362518893789": { + "message": "InsetsSource setWin %s for type %s", + "level": "DEBUG", + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" }, - "-584061725": { - "message": "Content Recording: Accept session updating same display %d with granted consent, with an existing session %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" + "6243049416211184258": { + "message": "InsetsSource Control %s for target %s", + "level": "DEBUG", + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" }, - "-583031528": { - "message": "%s", + "-8234068212532234206": { + "message": "InsetsSource updateVisibility for %s, serverVisible: %s clientVisible: %s", + "level": "DEBUG", + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + }, + "-8601070090234611338": { + "message": "ControlAdapter startAnimation mSource: %s controlTarget: %s", "level": "INFO", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" }, - "-576070986": { - "message": "Performing post-rotate rotation after seamless rotation", + "-6857870589074001153": { + "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s", "level": "INFO", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" }, - "-567946587": { - "message": "Requested redraw for orientation change: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowState.java" + "-6684172224226118673": { + "message": "onImeControlTargetChanged %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/InsetsStateController.java" }, - "-561092364": { - "message": "onPointerDownOutsideFocusLocked called on %s", + "8891808212671675155": { + "message": "clearLockedTasks: %s", "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-549028919": { - "message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "8970634498594714645": { + "message": "removeLockedTask: removed %s", + "level": "DEBUG", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-548282316": { - "message": "setLockTaskMode: Locking to %s Callers=%s", + "8735562128135241598": { + "message": "removeLockedTask: task=%s last task, reverting locktask mode. Callers=%s", + "level": "DEBUG", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" + }, + "737192738184050156": { + "message": "startLockTaskMode: Can't lock due to auth", "level": "WARN", "group": "WM_DEBUG_LOCKTASK", "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-547111355": { - "message": "hideIme Control target: %s ", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-7119521978513736788": { + "message": "Mode default, asking user", + "level": "WARN", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-545190927": { - "message": "<<< CLOSE TRANSACTION animate", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowAnimator.java" + "-1557441750657584614": { + "message": "%s", + "level": "WARN", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-542756093": { - "message": "TaskFragment vanished name=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "-4314079913933391851": { + "message": "setLockTaskMode: Can't lock due to auth", + "level": "WARN", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-532081937": { - "message": " Commit activity becoming invisible: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "3321878763832425380": { + "message": "setLockTaskMode: Locking to %s Callers=%s", + "level": "WARN", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-529187878": { - "message": "Reverting orientation after camera compat force rotation", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "-4819015209006579825": { + "message": "onLockTaskPackagesUpdated: removing %s mLockTaskAuth()=%s", + "level": "DEBUG", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-521613870": { - "message": "App died during pause, not stopping: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "2119751067469297845": { + "message": "onLockTaskPackagesUpdated: starting new locktask task=%s", + "level": "DEBUG", + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/LockTaskController.java" }, - "-519504830": { - "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s isEntrance=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "3788905348567806832": { + "message": "startAnimation", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" }, - "-517666355": { - "message": "Content Recording: Display %d has content (%b) so pause recording", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "705955074330737483": { + "message": "onAnimationCancelled", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" }, - "-509601642": { - "message": " checking %s", - "level": "VERBOSE", + "5106303602270682056": { + "message": "Adding display switch to existing collecting transition", + "level": "DEBUG", "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" - }, - "-507657818": { - "message": "Window %s is already added", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "at": "com\/android\/server\/wm\/PhysicalDisplaySwitchTransitionLauncher.java" }, - "-503656156": { - "message": "Update process config of %s to new config %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "3308140128142966415": { + "message": "remove RecentTask %s when finishing user %d", + "level": "INFO", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RecentTasks.java" }, - "-497620140": { - "message": "Transaction ready, syncId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/WindowOrganizerController.java" + "-3758280623533049031": { + "message": "Preload recents with %s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-496681057": { - "message": "Attempted to get remove mode of a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-3365656764099317101": { + "message": "Updated config=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-484194149": { - "message": "no-history finish of %s on new resume", + "-7165162073742035900": { + "message": "Real start recents", "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-483957611": { - "message": "Resuming configuration dispatch for %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-3403665718306852375": { + "message": "startRecentsActivity(): intent=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-481924678": { - "message": "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w.isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d", + "-8325607672707336373": { + "message": "No root task above target root task=%s", "level": "DEBUG", - "group": "WM_DEBUG_KEEP_SCREEN_ON", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-479665533": { - "message": "DisplayRotationCompatPolicy: Multi-window toast not shown as package '%s' cannot be found.", - "level": "ERROR", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "-7278356485797757819": { + "message": "Moved rootTask=%s behind rootTask=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-464564167": { - "message": "Current transition prevents automatic focus change", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "1012359606301505741": { + "message": "Started intent=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-463348344": { - "message": "Removing and adding activity %s to root task at top callers=%s", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/Task.java" + "5474198007669537235": { + "message": "onAnimationFinished(): controller=%s reorderMode=%d", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-451552570": { - "message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.", + "3525834288436624965": { + "message": "onAnimationFinished(): targetRootTask=%s targetActivity=%s mRestoreTargetBehindRootTask=%s", "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-449118559": { - "message": "Trying to update display configuration for invalid process, pid=%d", + "-5961176083217302671": { + "message": "Expected target rootTask=%s to be top most but found rootTask=%s", "level": "WARN", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" + }, + "-5893976429537642045": { + "message": "Expected target rootTask=%s to restored behind rootTask=%s but it is behind rootTask=%s", + "level": "WARN", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-445944810": { + "4515487264815398694": { + "message": "onRootTaskOrderChanged(): rootTask=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimation.java" + }, + "6530904107141905844": { + "message": "screenshotTask(%d): mCanceled=%b", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + }, + "-3286551982713129633": { + "message": "setFinishTaskTransaction(%d): transaction=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + }, + "5187133389446459984": { "message": "finish(%b): mCanceled=%b", "level": "DEBUG", "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-443173857": { - "message": "Moving pending starting from %s to %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "6879496555046975661": { + "message": "setInputConsumerEnabled(%s): mCanceled=%b", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-439951996": { - "message": "Disabling listeners", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "-5305978958548091997": { + "message": "setHomeApp(%s)", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-436553282": { - "message": "Remove sleep token: tag=%s, displayId=%d", + "-3801497203749932106": { + "message": "addAnimation(%s)", "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-417730399": { - "message": "Preparing to sync a window that was already in the sync, so try dropping buffer. win=%s", + "3721473589747203697": { + "message": "removeAnimation(%d)", "level": "DEBUG", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-415865166": { - "message": "findFocusedWindow: Found new focus @ %s", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "5156407755139006078": { + "message": "removeWallpaperAnimation()", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-415346336": { - "message": "DeferredDisplayUpdater: partially applying DisplayInfo immediately", + "-1997836523186474317": { + "message": "startAnimation(): mPendingStart=%b mCanceled=%b", "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-401282500": { - "message": "destroyIfPossible: r=%s destroy returned removed=%s", + "-7532294363367395195": { + "message": "startAnimation(): Notify animation start: %s", "level": "DEBUG", - "group": "WM_DEBUG_CONTAINERS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-401029526": { - "message": "%s: caller %d does not hold REAL_GET_TASKS; limiting output", - "level": "WARN", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "-1336603089105439710": { + "message": "collectTaskRemoteAnimations, target: %s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-399343789": { - "message": "Skipping %s: different user", + "2547528895718568379": { + "message": "createWallpaperAnimations()", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-393505149": { - "message": "unable to update pointer icon", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "5444932814080651576": { + "message": "cancelAnimation(): reason=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-386552155": { - "message": "Attempted to set system decors flag to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "622027757443954945": { + "message": "cleanupAnimation(): Notify animation finished mPendingAnimations=%d reorderMode=%d", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "-384639879": { - "message": "Acquiring screen wakelock due to %s", + "-5444412205083968021": { + "message": "createAnimationAdapter(): container=%s", "level": "DEBUG", - "group": "WM_DEBUG_KEEP_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-381475323": { - "message": "DisplayContent: boot is waiting for window of type %d to be drawn", + "6986037643494242400": { + "message": "goodToGo()", "level": "DEBUG", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-379068494": { - "message": "unknownApps is not empty: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "-1902984034737899928": { + "message": "goodToGo(): Animation canceled already", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-376950429": { - "message": "DeferredDisplayUpdater: deferring DisplayInfo update", + "6727618365838540075": { + "message": "goodToGo(): No apps to animate, mPendingAnimations=%d", "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-374767836": { - "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-2525509826755873433": { + "message": "goodToGo(): onAnimationStart, transit=%s, apps=%d, wallpapers=%d, nonApps=%d", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-373110070": { - "message": "Skipping task: (mismatch activity\/task) %s", + "-1148281153370899511": { + "message": "startAnimation(): Notify animation start:", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-360208282": { - "message": "Animating wallpapers: old: %s hidden=%b new: %s hidden=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "7501495587927045391": { + "message": "cancelAnimation(): reason=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-354571697": { - "message": "Existence Changed in transition %d: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "-1424368765415574722": { + "message": "Starting remote animation", + "level": "INFO", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-353495930": { - "message": "TaskFragmentTransaction changes are not collected in transition because there is an ongoing sync for applySyncTransaction().", - "level": "WARN", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowOrganizerController.java" + "-2676700429940607853": { + "message": "%s", + "level": "INFO", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-347866078": { - "message": "Setting move animation on %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "7094394833775573933": { + "message": "createAppAnimations()", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-344488673": { - "message": "Finishing drawing window %s: mDrawState=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "-4411070227420990074": { + "message": "\tAdd container=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-322743468": { - "message": "setInputMethodInputTarget %s", - "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-4411631520586057580": { + "message": "\tRemove container=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-322035974": { - "message": "App freeze timeout expired.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-7002230949892506736": { + "message": "createWallpaperAnimations()", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-319689203": { - "message": "Reparenting to original parent: %s for %s", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + "8743612568733301175": { + "message": "createNonAppWindowAnimations()", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-317761482": { - "message": "Create sleep token: tag=%s, displayId=%d", + "-2716313493239418198": { + "message": "onAnimationFinished(): mPendingAnimations=%d", "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-317194205": { - "message": "clearLockedTasks: %s", - "level": "INFO", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "7221400292415257709": { + "message": "onAnimationFinished(): Notify animation finished:", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-315778658": { - "message": "transferTouchGesture failed because args transferFromToken or transferToToken is null", - "level": "ERROR", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7483194715776694698": { + "message": "\tcontainer=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-312353598": { - "message": "Executing finish of activity: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "6697982664439247822": { + "message": "\twallpaper=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-310337305": { - "message": "Activity config changed during resume: %s, new next: %s", + "6938838346517131964": { + "message": "\tnonApp=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + }, + "-3880290251819699866": { + "message": "Finishing remote animation", "level": "INFO", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-304728471": { - "message": "New wallpaper: target=%s prev=%s", + "-7169244688499657832": { + "message": "app-onAnimationFinished(): mOuter=%s", "level": "DEBUG", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-302468788": { - "message": "Expected target rootTask=%s to be top most but found rootTask=%s", - "level": "WARN", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "3923111589554171989": { + "message": "app-release(): mOuter=%s", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-292790591": { - "message": "Attempted to set IME policy to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "8918152561092803537": { + "message": "startAnimation", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-275077723": { - "message": "New animation: %s old animation: %s", + "1736084564226683342": { + "message": "Starting remote display change: from [rot = %d], to [%dx%d, rot = %d]", "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java" }, - "-266707683": { - "message": "Moving #%d from collecting to waiting.", + "-4617490621756721600": { + "message": "resetTaskIntendedTask: calling finishActivity on %s", + "level": "WARN", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + }, + "3361857745281957526": { + "message": "Removing activity %s from task=%s adding to task=%s Callers=%s", + "level": "INFO", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" + }, + "3958829063955690349": { + "message": "Pushing next activity %s out to target's task %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" }, - "-251259736": { - "message": "No longer freezing: %s", + "1730793580703791926": { + "message": "Start pushing activity %s out to bottom task %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java" }, - "-248761393": { - "message": "startPausing: taskFrag =%s mResumedActivity=%s", + "-8961882615747561040": { + "message": "Looking for task of %s in %s", "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-240296576": { - "message": "handleAppTransitionReady: displayId=%d appTransition={%s} openingApps=[%s] closingApps=[%s] transit=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "8899721161806265460": { + "message": "Skipping task: (mismatch activity\/task) %s", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-235225312": { - "message": "Skipping config check for initializing activity: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "6841550641928224256": { + "message": "Skipping %s: voice session", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-233530384": { - "message": "Content Recording: Incoming session on display %d can't be set since it is already null; the corresponding VirtualDisplay must have already been removed.", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" + "4468520936943270392": { + "message": "Skipping %s: different user", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-230587670": { - "message": "SyncGroup %d: Unfinished container: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "-4764624740388751268": { + "message": "Skipping %s: mismatch root %s", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-228813488": { - "message": "%s: Setting back callback %s", + "9031436623838917667": { + "message": "Skipping %s: mismatch activity type", "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-208825711": { - "message": "shouldWaitAnimatingExit: isWallpaperTarget: %s", + "6022828946761399284": { + "message": "Comparing existing cls=%s \/aff=%s to new cls=%s \/aff=%s", "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-208664771": { - "message": "Reparenting to leash for %s", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + "-3413620974545388702": { + "message": "Found matching class!", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-203358733": { - "message": "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "-2649361982747625232": { + "message": "For Intent %s bringing to top: %s", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-198463978": { - "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7046266138098744790": { + "message": "Found matching affinity candidate!", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-195654020": { - "message": "Attempt to transfer touch gesture with host window not associated with embedded window", - "level": "WARN", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + "6481733556290926693": { + "message": "Not a match: %s", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-193782861": { - "message": "Final remove of window: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_MOVEMENT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3331249072840061049": { + "message": "New topFocusedDisplayId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-186693085": { - "message": "Starting a Recents transition which can be parallel.", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "865845626039449679": { + "message": "SURFACE RECOVER DESTROY: %s", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-182877285": { - "message": "Wallpaper layer changed: assigning layers + relayout", + "-4150611780753674023": { + "message": "Wallpaper may change! Adjusting", "level": "VERBOSE", "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-180594244": { - "message": "Content Recording: Unable to tell MediaProjectionManagerService about visibility change on the active projection: %s", - "level": "ERROR", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "4177291132772627699": { + "message": "With display frozen, orientationChangeComplete=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-177040661": { - "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s", + "-5513616928833586179": { + "message": "Performing post-rotate rotation", "level": "DEBUG", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-172326720": { - "message": "Saving icicle of %s: %s", - "level": "INFO", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-7698723716637247994": { + "message": "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w.isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d", + "level": "DEBUG", + "group": "WM_DEBUG_KEEP_SCREEN_ON", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-168799453": { - "message": "Allowing features %d:0x%s", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "8621291657500572364": { + "message": "mUserActivityTimeout set to %d", + "level": "DEBUG", + "group": "WM_DEBUG_KEEP_SCREEN_ON", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-167822951": { - "message": "Attempted to add starting window to token with already existing starting window", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-1418592110950138870": { + "message": "Looking for task of type=%s, taskAffinity=%s, intent=%s, info=%s, preferredTDA=%s", + "level": "DEBUG", + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-163974242": { - "message": "setFinishTaskTransaction(%d): transaction=%s", + "2828976699481734755": { + "message": "No task found", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-143556958": { - "message": "resumeNextFocusableActivityWhenRootTaskIsEmpty: %s, go home", + "-4405347314716558580": { + "message": "Create sleep token: tag=%s, displayId=%d", "level": "DEBUG", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/Task.java" - }, - "-125383273": { - "message": "Content Recording: waiting to record, so do nothing", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" - }, - "-124316973": { - "message": "Translucent=%s Floating=%s ShowWallpaper=%s Disable=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-116086365": { - "message": "******************** ENABLING SCREEN!", - "level": "INFO", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "1329131651776855609": { + "message": "Remove sleep token: tag=%s, displayId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-108977760": { - "message": "Sandbox max bounds for uid %s to bounds %s. config to never sandbox = %s, config to always sandbox = %s, letterboxing from mismatch with parent bounds = %s, has mCompatDisplayInsets = %s, should create compatDisplayInsets = %s", + "1653728842643223887": { + "message": "allResumedActivitiesIdle: rootTask=%d %s not idle", "level": "DEBUG", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-106400104": { - "message": "Preload recents with %s", + "3785779399471740019": { + "message": "allPausedActivitiesComplete: r=%s state=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "-98422345": { - "message": "Focus window is closing.", + "4666728330189027178": { + "message": "Failed to register MediaProjectionWatcherCallback", + "level": "ERROR", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/ScreenRecordingCallbackController.java" + }, + "8010999385228654193": { + "message": " FREEZE %s: CREATE", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + }, + "-6586462455018013482": { + "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s", "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, - "-91393839": { - "message": "Set animatingExit: reason=remove\/applyAnimation win=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "-5825336546511998057": { + "message": " FREEZE %s: DESTROY", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, - "-87705714": { - "message": "findFocusedWindow: focusedApp=null using new focus @ %s", + "6883897856740637908": { + "message": "ScreenRotation still animating: type: %d\nmDisplayAnimator: %s\nmEnterBlackFrameAnimator: %s\nmRotateScreenAnimator: %s\nmScreenshotRotationAnimator: %s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + }, + "-3943622313307983155": { + "message": "ScreenRotationAnimation onAnimationEnd", + "level": "DEBUG", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + }, + "-1594708154257031561": { + "message": " NEW SURFACE SESSION %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/Session.java" }, - "-86763148": { + "2638961674625826260": { "message": " KILL SURFACE SESSION %s", "level": "INFO", "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/Session.java" }, - "-81260230": { - "message": "Display id=%d is notified that Camera %s is closed, scheduling rotation update.", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "5380455212389185829": { + "message": "Removing dim surface %s on transaction %s", + "level": "DEBUG", + "group": "WM_DEBUG_DIMMER", + "at": "com\/android\/server\/wm\/SmoothDimmer.java" }, - "-81121442": { - "message": "ImeContainer just became organized but it doesn't have a parent or the parent doesn't have a surface control. mSurfaceControl=%s imeParentSurfaceControl=%s", - "level": "ERROR", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-820649637734629482": { + "message": "Animation start delayed for %s", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/SurfaceAnimator.java" }, - "-80004683": { - "message": "Resume failed; resetting state to %s: %s", + "1371702561758591499": { + "message": "Animation start for %s, anim=%s", + "level": "DEBUG", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + }, + "-5370506662233296228": { + "message": "Cancelling animation restarting=%b for %s", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + }, + "-3045933321063743917": { + "message": "Reparenting to original parent: %s for %s", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + }, + "-855083149623806053": { + "message": "Reparenting to leash for %s", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + }, + "-2595923278763115975": { + "message": " THUMBNAIL %s: CREATE", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/SurfaceFreezer.java" + }, + "-8609432747982701423": { + "message": "Setting Intent of %s to %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/Task.java" }, - "-70719599": { - "message": "Unregister remote animations for organizer=%s uid=%d pid=%d", + "-9155008290180285590": { + "message": "Setting Intent of %s to target %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "group": "WM_DEBUG_TASKS", + "at": "com\/android\/server\/wm\/Task.java" }, - "-57750640": { - "message": "show IME snapshot, ime target=%s, callers=%s", + "6424220442758232673": { + "message": "Removing and adding activity %s to root task at top callers=%s", "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/Task.java" }, - "-57572004": { - "message": "applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b canCustomizeAppTransition=%b Callers=%s", + "-1028890010429408946": { + "message": "addChild: %s at top.", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/Task.java" }, - "-55185509": { - "message": "setFocusedTask: taskId=%d touchedActivity=%s", + "38991867929900764": { + "message": "setLockTaskAuth: task=%s mLockTaskAuth=%s", "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "group": "WM_DEBUG_LOCKTASK", + "at": "com\/android\/server\/wm\/Task.java" }, - "-50336993": { - "message": "moveFocusableActivityToTop: activity=%s", + "-3401780415681318335": { + "message": "applyAnimationUnchecked, control: %s, task: %s, transit: %s", "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/Task.java" }, - "-33096143": { - "message": "applyAnimation: transition animation is disabled or skipped. container=%s", + "4446998544419008924": { + "message": "Moving to RESUMED: %s (starting new instance) callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/Task.java" }, - "-32102932": { - "message": "Error sending initial configuration change to WindowContainer overlay", - "level": "ERROR", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "4037728373502324767": { + "message": "resumeNextFocusableActivityWhenRootTaskIsEmpty: %s, go home", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/Task.java" }, - "-21399771": { - "message": "activity %s already destroying, skipping request with reason:%s", + "-2261257617975724313": { + "message": "Adding activity %s to task %s callers: %s", + "level": "INFO", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/Task.java" + }, + "7378236902389922467": { + "message": "App is requesting an orientation, return %d for display id=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/TaskDisplayArea.java" + }, + "2005499548343677845": { + "message": "No app is requesting an orientation, return %d for display id=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/TaskDisplayArea.java" + }, + "646076184396185067": { + "message": "App died while pausing: %s", "level": "VERBOSE", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "-8483143": { - "message": "No root task above target root task=%s", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "-7596917112222697106": { + "message": "Waiting for screen on due to %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "-4263657": { - "message": "Got a buffer for request id=%d but latest request is id=%d. Since the buffer is out-of-date, drop it. win=%s", - "level": "DEBUG", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/WindowState.java" + "-8472961767591168851": { + "message": "Sleep needs to pause %s", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "1877956": { - "message": "Content Recording: Display %d should start recording, but don't yet since the task is in PIP", + "-1472885369931482317": { + "message": "Sleep still waiting to pause %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "3593205": { - "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b", + "-2693016397674039814": { + "message": "Sleep still need to stop %d activities", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WallpaperWindowToken.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "9803449": { - "message": "startFreezingDisplayLocked: exitAnim=%d enterAnim=%d called by %s", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "8892147402270850613": { + "message": "resumeTopActivity: Skip resume: some activity pausing.", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "10608884": { - "message": " FREEZE %s: CREATE", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + "958293038551087087": { + "message": "resumeTopActivity: Top activity resumed %s", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "11060725": { - "message": "Attempted to get system decors flag of a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "4340810061306869942": { + "message": "resumeTopActivity: Going to sleep and all paused", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "17696244": { - "message": "startAnimation(): mPendingStart=%b mCanceled=%b", + "-7681635901109618685": { + "message": "resumeTopActivity: Pausing %s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "33989965": { - "message": " Met condition %s for #%d (%d left)", + "-3463034909521330970": { + "message": "resumeTopActivity: Skip resume: need to start pausing", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "34106798": { - "message": "Content Recording: Display %d state was (%d), is now (%d), so update recording?", + "-2264725269594226780": { + "message": "resumeTopActivity: Top activity resumed (dontWaitForPause) %s", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" + }, + "-8359248677489986541": { + "message": "Moving to RESUMED: %s (in existing)", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "34682671": { - "message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: FLAG_STEAL_TOP_FOCUS_DISABLED", + "2088177629189452176": { + "message": "Activity config changed during resume: %s, new next: %s", "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "35398067": { - "message": "goodToGo(): onAnimationStart, transit=%s, apps=%d, wallpapers=%d, nonApps=%d", + "-8483536760290526299": { + "message": "resumeTopActivity: Resumed %s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "45285419": { - "message": "startingWindow was set but startingSurface==null, couldn't remove", + "-4911500660485375799": { + "message": "Resume failed; resetting state to %s: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "51200510": { - "message": " BLACK %s: DESTROY", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/BlackFrame.java" - }, - "51628177": { - "message": "Attempted to get windowing mode of a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "51927339": { - "message": "Skipping %s: voice session", + "3723891427717889172": { + "message": "resumeTopActivity: Restarting %s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "61363198": { - "message": "Auto-PIP allowed, requesting PIP mode via requestStartTransition(): %s, willAutoPip: %b", + "1529152423206006904": { + "message": "startPausing: taskFrag =%s mResumedActivity=%s", "level": "DEBUG", "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "74885950": { - "message": "Waiting for top state to be released by %s", + "136971836458873178": { + "message": "Moving to PAUSING: %s", "level": "VERBOSE", "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "83950285": { - "message": "removeAnimation(%d)", + "-208996201631695262": { + "message": "Auto-PIP allowed, requesting PIP mode via requestStartTransition(): %s, willAutoPip: %b", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "95216706": { - "message": "hideIme target: %s ", + "-4123447037565780632": { + "message": "Auto-PIP allowed, entering PIP mode directly: %s, didAutoPip: %b", "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "95902367": { - "message": "Relayout of %s: focusMayChange=%b", + "-3710776151994843320": { + "message": "Key dispatch not paused for screen off", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "100936473": { - "message": "Wallpaper animation!", + "8543865526552245064": { + "message": "Activity not running or entered PiP, resuming next.", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" - }, - "102618780": { - "message": "resumeTopActivity: Pausing %s", - "level": "DEBUG", "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "108170907": { - "message": "Add starting %s: startingData=%s", + "1917394294249960915": { + "message": "Enqueueing pending pause: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "112145970": { - "message": " SKIP: its sibling was rejected", + "-8936154984341817384": { + "message": "Complete pause: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "114070759": { - "message": "New wallpaper target: %s prevTarget: %s caller=%s", + "4971958459026584561": { + "message": "Executing finish of activity: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "115358443": { - "message": "Focus changing: %s -> %s", - "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-7113165071559345173": { + "message": "Enqueue pending stop if needed: %s wasStopping=%b visibleRequested=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "138097009": { - "message": "NOSENSOR override is absent: reverting", + "-3777748052684097788": { + "message": "App died during pause, not stopping: %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotationReversionController.java" + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" }, - "140319294": { - "message": "IME target changed within ActivityRecord", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "-2808577027789344626": { + "message": "TaskFragment appeared name=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "146871307": { - "message": "Tried to remove starting window but startingWindow was null: %s", + "-3582112419663037270": { + "message": "TaskFragment vanished name=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "150351993": { - "message": "addWindow: %s startingWindow=%s", + "3294593748816836746": { + "message": "TaskFragment info changed name=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "152914409": { - "message": " BLACK %s: CREATE layer=%d", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/BlackFrame.java" + "5007230330523630579": { + "message": "TaskFragment parent info changed name=%s parentTaskId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "155482615": { - "message": "Focus requested for window=%s", + "6475066005515810081": { + "message": "Sending TaskFragment error exception=%s", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/InputMonitor.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "174572959": { - "message": "DisplayArea info changed name=%s", + "-7893265697482064583": { + "message": "Activity=%s reparent to taskId=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "182319432": { - "message": " remove from targets %s", + "7048981249808281819": { + "message": "Defer transition id=%d for TaskFragmentTransaction=%s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "184362060": { - "message": "screenshotTask(%d): mCanceled=%b", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "-1315509853595025526": { + "message": "Deferred transition id=%d has been continued before the TaskFragmentTransaction=%s is finished", + "level": "WARN", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "184610856": { - "message": "Start calculating TransitionInfo based on participants: %s", + "7421521217481553621": { + "message": "Continue transition id=%d for TaskFragmentTransaction=%s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "186668272": { - "message": "Now changing app %s", + "3509684748201636981": { + "message": "Register task fragment organizer=%s uid=%d pid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "189628502": { - "message": "Moving to STOPPING: %s (stop requested)", + "-6777461169027010201": { + "message": "Unregister task fragment organizer=%s uid=%d pid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "191486492": { - "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s", - "level": "DEBUG", - "group": "WM_DEBUG_KEEP_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, - "200829729": { - "message": "ScreenRotationAnimation onAnimationEnd", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "202263690": { - "message": "rotationForOrientation(orient=%s (%d), last=%s (%d)); user=%s (%d) %s", + "1327792561585467865": { + "message": "Register remote animations for organizer=%s uid=%d pid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "210750281": { - "message": "applyAnimationUnchecked, control: %s, task: %s, transit: %s", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/Task.java" + "-2524361347368208519": { + "message": "Unregister remote animations for organizer=%s uid=%d pid=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" }, - "215077284": { - "message": "Animation start delayed for %s", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + "-6181189296332065162": { + "message": "Task appeared taskId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "221540118": { - "message": "mUserActivityTimeout set to %d", - "level": "DEBUG", - "group": "WM_DEBUG_KEEP_SCREEN_ON", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "6535296991997214354": { + "message": "Task vanished taskId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "232317536": { - "message": "Set intercept back pressed on root=%b", + "-6638141753476761854": { + "message": "Task info changed taskId=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "240271590": { - "message": "moveFocusableActivityToTop: unfocusable activity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-8100069665346602959": { + "message": "Task back pressed on root taskId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "241961619": { - "message": "Adding %s to %s", + "-610138383571469481": { + "message": "Register task organizer=%s uid=%d", "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowToken.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "246676969": { - "message": "Attempted to add window with non-application token .%s Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "1705860547080436016": { + "message": "Unregister task organizer=%s uid=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "248210157": { - "message": "Finishing remote animation", - "level": "INFO", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "-2286607251115721394": { + "message": "createRootTask unknown displayId=%d", + "level": "ERROR", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "251812577": { - "message": "Register display organizer=%s uid=%d", + "8466395828406204368": { + "message": "Create root task displayId=%d winMode=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" - }, - "254883724": { - "message": "addWindowToken: Attempted to add binder token: %s for already created window token: %s displayId=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "255339989": { - "message": "setFocusedRootTask: taskId=%d", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "6867170298997192615": { + "message": "Delete root task display=%d winMode=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "255692476": { - "message": "**** GOOD TO GO", + "-4296644831871159510": { + "message": "Set intercept back pressed on root=%b", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "259206414": { - "message": "Creating Transition: %s", + "-558727273888268534": { + "message": "Restart top activity process of Task taskId=%d", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "261227010": { - "message": "Content Recording: Unable to tell log windowing mode change: %s", - "level": "ERROR", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "-7064081458956324316": { + "message": "Update camera compat control state to %s for taskId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, - "269576220": { - "message": "Resuming rotation after drag", + "3007492640459931179": { + "message": "Pausing rotation during re-position", "level": "DEBUG", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DragState.java" + "at": "com\/android\/server\/wm\/TaskPositioner.java" }, - "269976641": { - "message": "goodToGo(): Animation canceled already", + "5478864901888225320": { + "message": "Resuming rotation after re-position", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/TaskPositioner.java" }, - "273212558": { - "message": " info=%s", + "-2700498872917476567": { + "message": "Starting a Recents transition which can be parallel.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "274773837": { - "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL transit=%s Callers=%s", + "-8676279589273455859": { + "message": "Transition %d: Set %s as transient-launch", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" - }, - "283489582": { - "message": "Clear animatingExit: reason=exitAnimationDone win=%s", - "level": "DEBUG", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "288485303": { - "message": "Attempted to set remove mode to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "289967521": { - "message": "Check opening app=%s: allDrawn=%b startingDisplayed=%b startingMoved=%b isRelaunching()=%b startingWindow=%s", + "2734227875286695843": { + "message": "Override sync-method for %s because seamless rotating", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "292904800": { - "message": "Deferring rotation, animation in progress.", + "2808217645990556209": { + "message": "Starting Transition %d", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "295861935": { - "message": "startLockTaskMode: %s", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "-4672522645315112127": { + "message": "Collecting in transition %d: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "302969511": { - "message": "Task info changed taskId=%d", + "65881049096729394": { + "message": " Creating Ready-group for Transition %d with root=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "302992539": { - "message": "addAnimation(%s)", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "1101215730201607371": { + "message": "Existence Changed in transition %d: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "306524472": { - "message": "Stop failed; moving to STOPPED: %s", + "-3942072270654590479": { + "message": "Set transition ready=%b %d", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "312030608": { - "message": "New topFocusedDisplayId=%d", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-4688704756793656554": { + "message": " Commit activity becoming invisible: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "315395835": { - "message": "Trying to add window with invalid user=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "1817207111271920503": { + "message": " Skipping post-transition snapshot for task %d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "323235828": { - "message": "Delaying app transition for recents animation to finish", + "-2960171012238790176": { + "message": " Commit wallpaper becoming invisible: %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "327461496": { - "message": "Complete pause: %s", + "1230784960534033968": { + "message": "Aborting Transition: %d", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "339482207": { - "message": "Content Recording: Display %d was already recording, so apply transformations if necessary", + "-892865733969888022": { + "message": "Force Playing Transition: %d", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "341055768": { - "message": "resumeTopActivity: Skip resume: need to start pausing", + "-1354622424895965634": { + "message": "#%d: Met condition: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "341360111": { - "message": "selectAnimation in %s: transit=%d", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/DisplayPolicy.java" + "-5350671621840749173": { + "message": "Calling onTransitionReady: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "342460966": { - "message": "DRAG %s: pos=(%d,%d)", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/DragState.java" + "1830385055586991567": { + "message": "Apply and finish immediately because player is disabled for transition #%d .", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "344795667": { - "message": "*** APP TRANSITION TIMEOUT. displayId=%d isTransitionSet()=%b mOpeningApps.size()=%d mClosingApps.size()=%d mChangingApps.size()=%d", + "-758501334967569539": { + "message": " SKIP: %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "350168164": { - "message": "Removing activity %s, reason= %s callers=%s", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-2714847784842612086": { + "message": " SKIP: is wallpaper", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "355720268": { - "message": "stopFreezingDisplayLocked: Unfreezing now", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "1855461834864671586": { + "message": " check sibling %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "360319850": { - "message": "fractionRendered scale=%f", + "-6292043690918793069": { + "message": " SKIP: sibling is visible but not part of transition", "level": "VERBOSE", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "364992694": { - "message": "freezeDisplayRotation: current rotation=%d, new rotation=%d, caller=%s", + "7897657428993391672": { + "message": " unrelated invisible sibling %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "371173718": { - "message": "finishSync cancel=%b for %s", + "3873493605120555608": { + "message": " sibling is a participant with mode %s", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "371641947": { - "message": "Window Manager Crash %s", - "level": "WTF", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "7665553560859456426": { + "message": " SKIP: common mode mismatch. was %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "372792199": { - "message": "Non-null activity for system window of rootType=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-8916099332247176657": { + "message": " checking %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "374506950": { - "message": "Reporting activity moved to display, activityRecord=%s, displayId=%d, config=%s", + "-6818387694968032301": { + "message": " SKIP: its sibling was rejected", "level": "VERBOSE", - "group": "WM_DEBUG_SWITCH", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "374972436": { - "message": "performEnableScreen: Waiting for anim complete", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-7326702978448933012": { + "message": " keep as target %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "378825104": { - "message": "Enqueueing pending pause: %s", + "943961036184959431": { + "message": " remove from targets %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "378890013": { - "message": "Apply and finish immediately because player is disabled for transition #%d .", + "841543868388687804": { + "message": " CAN PROMOTE: promoting to parent %s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/Transition.java" }, - "385237117": { - "message": "moveFocusableActivityToTop: already on top and focused, activity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "743586316159041023": { + "message": "Start calculating TransitionInfo based on participants: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "385595355": { - "message": "Starting animation on %s: type=%d, anim=%s", + "-7247430213293162757": { + "message": " Rejecting as detached: %s", "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "390947100": { - "message": "Screenshotting %s [%s]", + "-5811837191094192313": { + "message": " Rejecting as no-op: %s", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/Transition.java" }, - "397382873": { - "message": "Moving to PAUSED: %s %s", + "-1153926883525904120": { + "message": " Initial targets: %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "397862437": { - "message": "Cancelling animation restarting=%b for %s", - "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/SurfaceAnimator.java" + "-9191328656870721224": { + "message": " Final targets: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "399841913": { - "message": "SURFACE RECOVER DESTROY: %s", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-2971560715211489406": { + "message": " Add condition %s for #%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "405146734": { - "message": " Final targets: %s", + "7631061720069910622": { + "message": " Met condition %s for #%d (%d left)", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/Transition.java" }, - "416924848": { - "message": "InsetsSource Control %s for target %s", - "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + "-4770394322045550928": { + "message": " Setting Ready-group to %b. group=%s from %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "417311568": { - "message": "onResize: Resizing %s", - "level": "DEBUG", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" + "6039132370452820927": { + "message": " Setting allReady override", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "419378610": { - "message": "Content Recording: Apply transformations of shift %d x %d, scale %f x %f, crop (aka recorded content size) %d x %d for display %d; display has size %d x %d; surface has size %d x %d", + "-3263748870548668913": { + "message": " allReady query: used=%b override=%b defer=%d states=[%s]", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "422634333": { - "message": "First draw done in potential wallpaper target %s", + "2699903406935781477": { + "message": "Screenshotting %s [%s]", "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" }, - "424524729": { - "message": "Attempted to add wallpaper window with unknown token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-233096875591058130": { + "message": "Creating Transition: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "431715812": { - "message": "Launch on display check: allow launch any on display", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "2154694726162725342": { + "message": "Start collecting in Transition: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "435494046": { - "message": "Attempted to add window to a display for which the application does not have access: %d. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-4235778637051052061": { + "message": "Disabling player for transition #%d because display isn't enabled yet", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "463993897": { - "message": "Aborted waiting for drawn: %s", - "level": "WARN", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "4005704720444963797": { + "message": "Requesting StartTransition: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "485170982": { - "message": "Not finishing noHistory %s on stop because we're just sleeping", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-6030030735787868329": { + "message": "Finish Transition: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "487621047": { - "message": "DisplayArea vanished name=%s", + "-1611886029896664304": { + "message": "Moving #%d from collecting to waiting.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "508887531": { - "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", + "-7097461682459496366": { + "message": "Playing #%d in parallel on track #%d", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "528150092": { - "message": " keep as target %s", + "-7364464699035275052": { + "message": "Marking #%d animation as SYNC.", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "531242746": { - "message": " THUMBNAIL %s: CREATE", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowContainerThumbnail.java" + "-5509640937151643757": { + "message": "Queueing transition: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "531891870": { - "message": "Previous Destination is Activity:%s Task:%s removedContainer:%s, backType=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "-2741593375634604522": { + "message": "Queueing legacy sync-set: %s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "532771960": { - "message": "Adding untrusted state listener=%s with id=%d", - "level": "DEBUG", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "-5051723169912572741": { + "message": "%s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "535103992": { - "message": "Wallpaper may change! Adjusting", + "4281568181321808508": { + "message": " startWCT=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "539077569": { - "message": "Clear freezing of %s force=%b", + "5141999957143860655": { + "message": " info=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" }, - "544101314": { - "message": "performEnableScreen: Waited %dms for all windows to be drawn", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3445530300764535903": { + "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" }, - "556758086": { - "message": "Applying new update lock state '%s' for %s", + "-6140852484700685564": { + "message": "Registering listener=%s with id=%d for window=%s with %s", "level": "DEBUG", - "group": "WM_DEBUG_IMMERSIVE", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "557227556": { - "message": "onAnimationFinished(): Notify animation finished:", + "3691097873058247482": { + "message": "Unregistering listener=%s with id=%d", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "558823034": { - "message": "SURFACE isOpaque=%b: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + "6408851516381868623": { + "message": "Checking %d windows", + "level": "VERBOSE", + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "573582981": { - "message": "reparent: moving activity=%s to new task fragment in task=%d at %d", - "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "7718187745767272532": { + "message": "Skipping %s", + "level": "VERBOSE", + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "579298675": { - "message": "Moving to DESTROYED: %s (removed from history)", + "-1135667737459933313": { + "message": "coveredRegionsAbove updated with %s frame:%s region:%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "585096182": { - "message": "SURFACE isColorSpaceAgnostic=%b: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + "854487339271667012": { + "message": "checkIfInThreshold fractionRendered=%f alpha=%f currTimeMs=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "585839596": { - "message": "call showInsets(ime) on %s", - "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "-2248576188205088843": { + "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" }, - "594260577": { - "message": "createWallpaperAnimations()", + "6236170793308011579": { + "message": "Adding untrusted state listener=%s with id=%d", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, - "600140673": { - "message": "checkBootAnimationComplete: Waiting for anim complete", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "601283564": { - "message": "Dream packageName does not match active dream. Package %s does not match %s", - "level": "ERROR", - "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", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/Session.java" + "5405816744363636527": { + "message": "Adding trusted state listener=%s with id=%d", + "level": "DEBUG", + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "612856628": { - "message": "Content Recording: Stop MediaProjection on virtual display %d", + "-5162728346383863020": { + "message": "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s scale=%f,%f", "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "620519522": { - "message": "findFocusedWindow: No focusable windows, display=%d", + "898769258643799441": { + "message": "fractionRendered scale=%f", "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "628276090": { - "message": "Delaying app transition for screen rotation animation to finish", + "-455501334697331596": { + "message": "fractionRendered boundsOverSource=%f", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" - }, - "631792420": { - "message": "Attempted to add window with token that is not a window: %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_TPL", + "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" }, - "638429464": { - "message": "\tRemove container=%s", + "1964980935866463086": { + "message": "\tWallpaper of display=%s is not visible", "level": "DEBUG", "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" }, - "644675193": { - "message": "Real start recents", + "8131665298937888044": { + "message": "startAnimation", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" }, - "646155519": { - "message": "Started intent=%s", + "8030745595351281943": { + "message": "onAnimationCancelled", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" - }, - "646981048": { - "message": "Invalid displayId for requestScrollCapture: %d", - "level": "ERROR", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "662572728": { - "message": "Attempted to add a toast window with bad token %s. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" }, - "665256544": { - "message": "All windows drawn!", + "-5254364639040552989": { + "message": "Hiding wallpaper %s from %s target=%s prev=%s callers=%s", "level": "DEBUG", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "666937535": { - "message": "attachWindowContextToDisplayArea: trying to attach to a non-existing display:%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "669361121": { - "message": "Sleep still need to stop %d activities", + "-3477087868568520027": { + "message": "No longer animating wallpaper targets!", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "674932310": { - "message": "Setting Intent of %s to target %s", + "-3751289048117070874": { + "message": "New wallpaper target: %s prevTarget: %s caller=%s", "level": "VERBOSE", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/Task.java" - }, - "675705156": { - "message": "resumeTopActivity: Top activity resumed %s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "685047360": { - "message": "Resizing window %s", + "5625223922466895079": { + "message": "New animation: %s old animation: %s", "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "686185515": { - "message": "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", + "7634524672408826188": { + "message": "Animating wallpapers: old: %s hidden=%b new: %s hidden=%b", "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "691515534": { - "message": " Commit wallpaper becoming invisible: %s", + "-4345077332231178044": { + "message": "Old wallpaper still the target.", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" - }, - "693423992": { - "message": "setAnimationLocked: setting mFocusMayChange true", - "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "701366755": { - "message": "Attempt to transfer touch gesture with non-existent embedded window", - "level": "WARN", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + "-2504764636812266719": { + "message": "New wallpaper: target=%s prev=%s", + "level": "DEBUG", + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperController.java" }, - "704998117": { - "message": "Failed to create surface control for %s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-7936547457136708587": { + "message": "Wallpaper token %s visible=%b", + "level": "DEBUG", + "group": "WM_DEBUG_WALLPAPER", + "at": "com\/android\/server\/wm\/WallpaperWindowToken.java" }, - "708142634": { - "message": "Top resumed state released %s", + "7214407534407465113": { + "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WallpaperWindowToken.java" }, - "715749922": { - "message": "Allowlisting %d:%s", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "-5360147928134631656": { + "message": ">>> OPEN TRANSACTION animate", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowAnimator.java" }, - "723575093": { - "message": "Attempted to add window with a client %s that is dead. Aborting.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-3993586364046165922": { + "message": "<<< CLOSE TRANSACTION animate", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowAnimator.java" }, - "726205185": { - "message": "Moving to DESTROYED: %s (destroy skipped)", + "-5231580410559054259": { + "message": "%s is requesting orientation %d (%s)", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "733466617": { - "message": "Wallpaper token %s visible=%b", - "level": "DEBUG", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperWindowToken.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "736692676": { - "message": "Config is relaunching %s", + "6949303417875346627": { + "message": "Starting animation on %s: type=%d, anim=%s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "743418423": { - "message": "Sending TaskFragment error exception=%s", + "-8730310387200541562": { + "message": "applyAnimation: transition animation is disabled or skipped. container=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "744171317": { - "message": " SKIP: %s", + "2363818604357955690": { + "message": "applyAnimation: transit=%s, enter=%b, wc=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "745391677": { - "message": " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x \/ %s", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "2262119454684034794": { + "message": "applyAnimation: container=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "765395228": { - "message": "onAnimationFinished(): controller=%s reorderMode=%d", + "5857165752965610762": { + "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "769218938": { + "9017113545720281233": { "message": "Loaded animation %s for %s, duration: %d, stack=%s", "level": "INFO", "group": "WM_DEBUG_ANIM", "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "781471998": { - "message": "moveWindowTokenToDisplay: Cannot move to the original display for token: %s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, - "782864973": { - "message": "Releasing screen wakelock, obscured by %s", - "level": "DEBUG", - "group": "WM_DEBUG_KEEP_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, - "791468751": { - "message": "Pausing rotation during re-position", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/TaskPositioner.java" + "5272307326252759722": { + "message": "onSyncFinishedDrawing %s", + "level": "VERBOSE", + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "793568608": { - "message": " SKIP: sibling is visible but not part of transition", + "-8311909671193661340": { + "message": "setSyncGroup #%d on %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "794570322": { - "message": "Now closing app %s", + "-3871009616397322067": { + "message": "finishSync cancel=%b for %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "801521566": { - "message": "Content Recording: Attempting to mirror %d from %d but no DisplayContent associated. Changing to mirror default display.", - "level": "WARN", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-4267530270533009730": { + "message": "Error sending initial configuration change to WindowContainer overlay", + "level": "ERROR", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "806891543": { - "message": "Setting mOrientationChangeComplete=true because wtoken %s numInteresting=%d numDrawn=%d", - "level": "INFO", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "5179630990780610966": { + "message": "Error sending initial insets change to WindowContainer overlay", + "level": "ERROR", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" }, - "810599500": { - "message": "SURFACE isSecure=%b: %s", + "-131600102855790053": { + "message": " THUMBNAIL %s: CREATE", "level": "INFO", "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", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "at": "com\/android\/server\/wm\/WindowContainerThumbnail.java" }, - "835814848": { - "message": "%s", + "2163930285157267092": { + "message": "The listener does not exist.", "level": "INFO", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, - "851368695": { - "message": "Deferred transition id=%d has been continued before the TaskFragmentTransaction=%s is finished", - "level": "WARN", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" - }, - "872933199": { - "message": "Changing focus from %s to %s displayId=%d Callers=%s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, - "873160948": { - "message": "Activity=%s reparent to taskId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowContextListenerController.java" }, - "873914452": { - "message": "goodToGo()", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "6139364662459841509": { + "message": "Could not register window container listener token=%s, container=%s", + "level": "ERROR", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowContextListenerController.java" }, - "892244061": { - "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", - "level": "INFO", - "group": "WM_DEBUG_SCREEN_ON", + "3655576047584951173": { + "message": "Window Manager Crash %s", + "level": "WTF", + "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "895158150": { - "message": "allPausedActivitiesComplete: r=%s state=%s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" - }, - "898863925": { - "message": "Attempted to add QS dialog window with unknown token %s. Aborting.", + "-3029436704707366221": { + "message": "Attempted to add window with a client %s that is dead. Aborting.", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "906215061": { - "message": "Apply window transaction, syncId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/WindowOrganizerController.java" - }, - "913494177": { - "message": "removeAllWindowsIfPossible: removing win=%s", + "-1303710477998542095": { + "message": "Attempted to add window to a display that does not exist: %d. Aborting.", "level": "WARN", - "group": "WM_DEBUG_WINDOW_MOVEMENT", - "at": "com\/android\/server\/wm\/WindowToken.java" - }, - "916191774": { - "message": "Orientation change complete in %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" - }, - "935418348": { - "message": "resumeTopActivity: Skip resume: some activity pausing.", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" - }, - "937080808": { - "message": "Content Recording: Recorded task is removed, so stop recording on display %d", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "939638078": { - "message": "config_deviceTabletopRotations is not defined. Half-fold letterboxing will work inconsistently.", + "8039410207325630747": { + "message": "Attempted to add window to a display for which the application does not have access: %d. Aborting.", "level": "WARN", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" - }, - "948208142": { - "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "950074526": { - "message": "setLockTaskMode: Can't lock due to auth", + "-3451016577701561221": { + "message": "Window %s is already added", "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" - }, - "954470154": { - "message": "FORCED DISPLAY SCALING DISABLED", - "level": "INFO", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "956374481": { - "message": "removeLockedTask: task=%s last task, reverting locktask mode. Callers=%s", - "level": "DEBUG", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" - }, - "958338552": { - "message": "grantEmbeddedWindowFocus win=%s dropped focus so setting focus to null since no candidate was found", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", + "7245919222637411747": { + "message": "Attempted to add window with token that is not a window: %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "959486822": { - "message": "setSyncGroup #%d on %s", - "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/WindowContainer.java" - }, - "966569777": { - "message": "SyncGroup %d: onSurfacePlacement checking %s", - "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" - }, - "969323241": { - "message": "Sending new config to %s, config: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "972354148": { - "message": "\tcontainer=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" - }, - "975028389": { - "message": "unable to call receiver for empty keyboard shortcuts", - "level": "ERROR", + "-8579305050440451727": { + "message": "Attempted to add window with token that is a sub-window: %s. Aborting.", + "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "975275467": { - "message": "Set animatingExit: reason=remove\/isAnimating win=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" + "-1075040941127814341": { + "message": "Attempted to add private presentation window to a non-private display. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "979347997": { - "message": "Launch on display check: disallow activity embedding without permission.", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "7599690046549866326": { + "message": "Attempted to add presentation window to a non-suitable display. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "987903142": { - "message": "Sleep needs to pause %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "-2546047231197102533": { + "message": "Trying to add window with invalid user=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "996960396": { - "message": "Starting Transition %d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "3713874359318494804": { + "message": "Attempted to add window with non-application token .%s Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1001904964": { - "message": "***** BOOT TIMEOUT: forcing display enabled", + "-6507147599943157469": { + "message": "Attempted to add window with exiting application token .%s Aborting.", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1015746067": { - "message": "Display id=%d is ignoring orientation request for %d, return %d following a per-app override for %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-1409483453189443362": { + "message": "Attempted to add starting window to token with already existing starting window", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1022095595": { - "message": "TaskFragment info changed name=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "-1806907994917883598": { + "message": "Attempted to add starting window to token but already cleaned", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1023413388": { - "message": "Finish waiting for pause of: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-5450131464624918523": { + "message": "Attempted to add input method window with bad token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1030898920": { - "message": "notifyInsetsControlChanged for %s ", - "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/WindowState.java" + "-6484128707849211138": { + "message": "Attempted to add voice interaction window with bad token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1033274509": { - "message": "moveWindowTokenToDisplay: Attempted to move non-existing token: %s", + "7768591536609704658": { + "message": "Attempted to add wallpaper window with bad token %s. Aborting.", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1040675582": { - "message": "Can't report activity configuration update - client not running, activityRecord=%s", + "7497077135474110999": { + "message": "Attempted to add Accessibility overlay window with bad token %s. Aborting.", "level": "WARN", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1042363394": { - "message": "Attempt to transfer touch gesture using a host window with no input channel", + "8957851092580119204": { + "message": "Attempted to add a toast window with bad token %s. Aborting.", "level": "WARN", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1046228706": { - "message": "Defer transition id=%d for TaskFragmentTransaction=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "-1945746969404688952": { + "message": "Attempted to add QS dialog window with bad token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1046922686": { - "message": "requestScrollCapture: caught exception dispatching callback: %s", + "3419934373251134563": { + "message": "Non-null activity for system window of rootType=%d", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1047505501": { - "message": "notifyInsetsChanged for %s ", - "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/WindowState.java" + "-1161056447389155729": { + "message": "Adding more than one toast window for UID at a time.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1047769218": { - "message": "Finishing activity r=%s, result=%d, data=%s, reason=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-7518552252637236411": { + "message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1049367566": { - "message": "Sending to proc %s new config %s", + "-6055615852717459196": { + "message": "addWindow: %s startingWindow=%s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/WindowProcessController.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1051545910": { - "message": "Exit animation finished in %s: remove=%b", + "-2829980616540274784": { + "message": "addWindow: New client %s: window=%s Callers=%s", "level": "VERBOSE", "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "1068803972": { - "message": "Activity paused: token=%s, timeout=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1073230342": { - "message": "startAnimation", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" + "-7315179333005789167": { + "message": "Attempted to add application window with unknown token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1075460705": { - "message": "Continue transition id=%d for TaskFragmentTransaction=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "-7547709658889961930": { + "message": "Attempted to add input method window with unknown token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1087494661": { - "message": "Clear window stuck on animatingExit status: %s", + "3009864422591182484": { + "message": "Attempted to add voice interaction window with unknown token %s. Aborting.", "level": "WARN", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowState.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1088929964": { - "message": "onLockTaskPackagesUpdated: starting new locktask task=%s", - "level": "DEBUG", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "-2639914438438144071": { + "message": "Attempted to add wallpaper window with unknown token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1089714158": { - "message": " FREEZE %s: DESTROY", - "level": "INFO", - "group": "WM_SHOW_SURFACE_ALLOC", - "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + "-7529563697886120786": { + "message": "Attempted to add QS dialog window with unknown token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1090378847": { - "message": "Checking %d windows", - "level": "VERBOSE", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "4253401518117961686": { + "message": "Attempted to add Accessibility overlay window with unknown token %s. Aborting.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1100065297": { - "message": "Attempted to get IME policy of a display that does not exist: %d", + "5834230650841873680": { + "message": "Attempted to add a toast window with unknown token %s. Aborting.", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1105210816": { - "message": "Skipping config check in destroyed state %s", + "5265273548711408921": { + "message": "postWindowRemoveCleanupLocked: %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "1112047265": { - "message": "finishDrawingWindow: %s mDrawState=%s", - "level": "DEBUG", "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1115248873": { - "message": "Calling onTransitionReady: %s", + "-3847568084407666790": { + "message": "Final remove of window: %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" - }, - "1115417974": { - "message": "FORCED DISPLAY SIZE: %dx%d", - "level": "INFO", - "group": "WM_ERROR", + "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1126328412": { - "message": "Scheduling idle now: forceIdle=%b immediate=%b", + "1419572818243106725": { + "message": "Removing %s from %s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1140424002": { - "message": "Finished screen turning on...", + "8312693933819247897": { + "message": "Relayout %s: oldVis=%d newVis=%d. %s", "level": "INFO", "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayPolicy.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1145016093": { - "message": "Content Recording: Attempting to mirror self on %d", + "8319702790708803735": { + "message": "Exception thrown when creating surface for client %s (%s). %s", "level": "WARN", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1149424314": { - "message": "Unregister display organizer=%s uid=%d", + "212929172223901460": { + "message": "Relayout of %s: focusMayChange=%b", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1151072840": { - "message": "collectTaskRemoteAnimations, target: %s", + "-255991894956556845": { + "message": "Set animatingExit: reason=startExitingAnimation\/%s win=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" - }, - "1164325516": { - "message": "onExitAnimationDone in %s: exiting=%b remove=%b selfAnimating=%b anim=%s", - "level": "VERBOSE", "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "1166381079": { - "message": "Execute app transition: %s, displayId: %d Callers=%s", - "level": "WARN", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1175495463": { - "message": "ImeContainer just became organized. Reparenting under parent. imeParentSurfaceControl=%s", + "6555160513135851764": { + "message": "OUT SURFACE %s: copied", "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1178653181": { - "message": "Old wallpaper still the target.", - "level": "VERBOSE", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "-196459205494031145": { + "message": "Failed to create surface control for %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1191587912": { - "message": "Moved rootTask=%s behind rootTask=%s", + "-5512006943172316333": { + "message": "finishDrawingWindow: %s mDrawState=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1192413464": { - "message": "Comparing existing cls=%s \/aff=%s to new cls=%s \/aff=%s", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "-2577785761087081584": { + "message": "Permission Denial: %s from pid=%d, uid=%d requires %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1208313423": { + "4547566763172245740": { "message": "addWindowToken: Attempted to add token: %s for non-exiting displayId=%d", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1210037962": { - "message": "Register remote animations for organizer=%s uid=%d pid=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" - }, - "1219600119": { - "message": "addWindow: win=%s Callers=%s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/WindowToken.java" + "-972832559831959983": { + "message": "addWindowToken: Attempted to add binder token: %s for already created window token: %s displayId=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1224184681": { - "message": "No longer Stopped: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "8372202339190060748": { + "message": "attachWindowContextToDisplayArea: calling from non-existing process pid=%d uid=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1224307091": { - "message": "checkBootAnimationComplete: Animation complete!", - "level": "INFO", - "group": "WM_DEBUG_BOOT", + "1904306629015452865": { + "message": "attachWindowContextToDisplayArea: trying to attach to a non-existing display:%d", + "level": "WARN", + "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1239439010": { - "message": "moveFocusableActivityToTop: set focused, activity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-6845859096032432107": { + "message": "attachWindowContextToDisplayContent: calling from non-existing process pid=%d uid=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.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" + "1473791807245791604": { + "message": "attachWindowContextToWindowToken: calling from non-existing process pid=%d uid=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1252594551": { - "message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d", + "-2056866750160555704": { + "message": "Then token:%s is invalid. It might be removed", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1254403969": { - "message": "Surface returned was null: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-1045756671264607145": { + "message": "removeWindowToken: Attempted to remove token: %s for non-exiting displayId=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1264179654": { - "message": "No focused window, defaulting to top current task's window", + "874825105313641295": { + "message": "removeWindowToken: Attempted to remove non-existing token: %s", "level": "WARN", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1270792394": { - "message": "Resumed after relaunch %s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "5128669121055635771": { + "message": "moveWindowTokenToDisplay: Attempted to move token: %s to non-exiting displayId=%d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1282992082": { - "message": "Disabling player for transition #%d because display isn't enabled yet", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" + "6497954191906583839": { + "message": "moveWindowTokenToDisplay: Attempted to move non-existing token: %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1284122013": { - "message": "TaskFragment appeared name=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "2865882097969084039": { + "message": "moveWindowTokenToDisplay: Cannot move to the original display for token: %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1288731814": { - "message": "WindowState.hideLw: setting mFocusMayChange true", + "-886583195545553099": { + "message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: FLAG_STEAL_TOP_FOCUS_DISABLED", "level": "INFO", "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "1288920916": { - "message": "Error sending initial insets change to WindowContainer overlay", - "level": "ERROR", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" - }, - "1305412562": { - "message": "Report configuration: %s %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityClientController.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1309365288": { - "message": "Removing dim surface %s on transaction %s", - "level": "DEBUG", - "group": "WM_DEBUG_DIMMER", - "at": "com\/android\/server\/wm\/SmoothDimmer.java" + "-1557387535886241553": { + "message": "enableScreenAfterBoot: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1316533291": { - "message": "State movement: %s from:%s to:%s reason:%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-6467850045030187736": { + "message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1325649102": { - "message": "Bad requesting window %s", + "179762478329442868": { + "message": "***** BOOT TIMEOUT: forcing display enabled", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1329340614": { - "message": "Orientation not waiting for draw in %s, surfaceController %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowState.java" + "-3417569256875279779": { + "message": "performEnableScreen: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1330804250": { - "message": "addChild: %s at top.", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/Task.java" + "-7516915153725082358": { + "message": "performEnableScreen: Waited %dms for all windows to be drawn", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1331177619": { - "message": "Attempted to add a toast window with unknown token %s. Aborting.", + "-1541244520024033685": { + "message": "performEnableScreen: Waiting for anim complete", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, + "2670150656385758826": { + "message": "performEnableScreen: bootFinished() failed.", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1335791109": { - "message": "createSurface %s: mDrawState=DRAW_PENDING", + "530628508916855904": { + "message": "******************** ENABLING SCREEN!", "level": "INFO", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" - }, - "1337596507": { - "message": "Sending to proc %s new compat %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/CompatModePackages.java" + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1346895820": { - "message": "ScreenRotation still animating: type: %d\nmDisplayAnimator: %s\nmEnterBlackFrameAnimator: %s\nmRotateScreenAnimator: %s\nmScreenshotRotationAnimator: %s", + "5477889324043875194": { + "message": "Notified TransitionController that the display is ready.", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1360176455": { - "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteDisplayChange=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", + "-2061779801633179448": { + "message": "checkBootAnimationComplete: Waiting for anim complete", + "level": "INFO", + "group": "WM_DEBUG_BOOT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1364126018": { - "message": "Resumed activity; dropping state of: %s", + "-8177456840019985809": { + "message": "checkBootAnimationComplete: Animation complete!", "level": "INFO", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1364498663": { - "message": "notifyAppResumed: wasStopped=%b %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-333924817004774456": { + "message": "showBootMessage: msg=%s always=%b mAllowBootMessages=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1373000889": { - "message": "abortShowImePostLayout", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "2994810644159608200": { + "message": "hideBootMessagesLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1381227466": { - "message": "App is requesting an orientation, return %d for display id=%d", + "-6625203651195752178": { + "message": "freezeDisplayRotation: current rotation=%d, new rotation=%d, caller=%s", "level": "VERBOSE", "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" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1393721079": { - "message": "Starting remote display change: from [rot = %d], to [%dx%d, rot = %d]", + "8988910478484254861": { + "message": "thawRotation: mRotation=%d, caller=%s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java" - }, - "1396893178": { - "message": "createRootTask unknown displayId=%d", - "level": "ERROR", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" - }, - "1401295262": { - "message": "Mode default, asking user", - "level": "WARN", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" - }, - "1401700824": { - "message": "Window drawn win=%s", - "level": "DEBUG", - "group": "WM_DEBUG_SCREEN_ON", + "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1422781269": { - "message": "Resuming rotation after re-position", - "level": "DEBUG", + "7261084872394224738": { + "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b", + "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/TaskPositioner.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1423418408": { - "message": "unable to restore pointer icon", + "8664813170125714536": { + "message": "View server did not start", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1430336882": { - "message": "findFocusedWindow: focusedApp windows not focusable using new focus @ %s", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "-8019372496359375449": { + "message": "Could not send command %s with parameters %s. %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1434383382": { - "message": "Attempted to get flag of a display that does not exist: %d", + "1893303527772009363": { + "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.", "level": "WARN", "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" + "-3652974372240081071": { + "message": "SAFE MODE ENABLED (menu=%d s=%d dpad=%d trackball=%d)", + "level": "INFO", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1448683958": { - "message": "Override pending remote transitionSet=%b adapter=%s", + "4945624619344146947": { + "message": "SAFE MODE not enabled", "level": "INFO", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1457990604": { - "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE transit=%s Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "-3428027271337724889": { + "message": "Focus changing: %s -> %s", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1460759282": { - "message": "getAnimationTarget in=%s, out=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "1624328195833150047": { + "message": "App freeze timeout expired.", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1463355909": { - "message": "Queueing legacy sync-set: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" + "5830724144971462783": { + "message": "Timeout waiting for drawn: undrawn=%s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1469310004": { - "message": " SKIP: common mode mismatch. was %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "-2240705227895260140": { + "message": "CHECK_IF_BOOT_ANIMATION_FINISHED:", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1473051122": { - "message": "Pausing configuration dispatch for %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "8641557333789260779": { + "message": "FORCED DISPLAY SIZE: %dx%d", + "level": "INFO", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1494644409": { - "message": " Rejecting as detached: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "3781141652793604337": { + "message": "FORCED DISPLAY SCALING DISABLED", + "level": "INFO", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1495525537": { - "message": "createWallpaperAnimations()", - "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "4117606810523219596": { + "message": "Failed looking up window session=%s callers=%s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1497304204": { - "message": "Deferring rotation, rotation is paused.", + "1233670725456443473": { + "message": "Changing surface while display frozen: %s", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" - }, - "1504168072": { - "message": "removeIfPossible: %s callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowState.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1511273241": { - "message": "Refreshing activity for camera compatibility treatment, activityRecord=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java" + "-1716033239040181528": { + "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", + "level": "INFO", + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1518495446": { - "message": "removeWindowToken: Attempted to remove non-existing token: %s", + "-4609828204247499633": { + "message": "Aborted waiting for drawn: %s", "level": "WARN", - "group": "WM_ERROR", + "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1519757176": { - "message": "setHomeApp(%s)", + "-7561054602203220590": { + "message": "Window drawn win=%s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" - }, - "1520642640": { - "message": "Attempt to transfer touch gesture using embedded window with no associated host", - "level": "WARN", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" - }, - "1521476038": { - "message": "Attempted to set flag to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", + "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1524174282": { - "message": "Launch on display check: no caller info, skip check", + "2809030008663191766": { + "message": "All windows drawn!", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" + "group": "WM_DEBUG_SCREEN_ON", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1525976603": { - "message": "cancelAnimation(): reason=%s", + "-1615905649072328410": { + "message": "startFreezingDisplayLocked: exitAnim=%d enterAnim=%d called by %s", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1528528509": { - "message": "No thumbnail header bitmap for: %s", + "4565793239453546297": { + "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteDisplayChange=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "1546187372": { - "message": "Content Recording: Pause the recording session on display %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1557732761": { - "message": "For Intent %s bringing to top: %s", + "-6877112251967196129": { + "message": "stopFreezingDisplayLocked: Unfreezing now", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1563755163": { - "message": "Permission Denial: %s from pid=%d, uid=%d requires %s", - "level": "WARN", + "721393258715103117": { + "message": "%s", + "level": "INFO", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1577579529": { - "message": "win=%s destroySurfaces: appStopped=%b win.mWindowRemovalAllowed=%b win.mRemoveOnExit=%b", - "level": "ERROR", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "1584270979": { - "message": "applyAnimation: container=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/WindowContainer.java" - }, - "1589610525": { - "message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" - }, - "1610646518": { - "message": "Enqueueing pending finish: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "1621562070": { - "message": " startWCT=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" - }, - "1628345525": { - "message": "Now opening app %s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" - }, - "1634557978": { + "-5706083447992207254": { "message": "**** Dismissing screen rotation animation", "level": "INFO", "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1635062046": { - "message": "Skipping config check invisible: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "1635462459": { - "message": "onMovedByResize: Moving %s", + "2233371241933584073": { + "message": "Performing post-rotate rotation", "level": "DEBUG", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, - "1640436199": { - "message": "No app is requesting an orientation, return %d for display id=%d", - "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/TaskDisplayArea.java" - }, - "1653025361": { - "message": "Register task fragment organizer=%s uid=%d pid=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1653210583": { - "message": "Removing app %s delayed=%b animation=%s animating=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "1010635158502326025": { + "message": "unable to call receiver for empty keyboard shortcuts", + "level": "ERROR", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1658605381": { - "message": "onImeControlTargetChanged %s", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/InsetsStateController.java" + "1278715281433572858": { + "message": "Bad requesting window %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1661414284": { - "message": "Content Recording: Unable to tell MediaProjectionManagerService about resizing the active projection: %s", - "level": "ERROR", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "-707915937966769475": { + "message": "unable to update pointer icon", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1670933628": { - "message": " Setting allReady override", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "-8663841671650918687": { + "message": "unable to restore pointer icon", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1674747211": { - "message": "%s forcing orientation to %d for display id=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayArea.java" + "-6186782212018913664": { + "message": "Invalid displayId for requestScrollCapture: %d", + "level": "ERROR", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1677260366": { - "message": "Finish starting %s: first real window is shown, no animation", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "51378282333944649": { + "message": "requestScrollCapture: caught exception dispatching to window.token=%s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1679569477": { - "message": "Configuration doesn't matter not running %s", - "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-8972916676375201577": { + "message": "requestScrollCapture: caught exception dispatching callback: %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1687944543": { - "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s, since the surface is not available.", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "-1875125162673622728": { + "message": "Attempted to get windowing mode of a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1699269281": { - "message": "Don't organize or trigger events for untrusted displayId=%d", + "3938331948687900219": { + "message": "Attempted to set windowing mode to a display that does not exist: %d", "level": "WARN", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1712935427": { - "message": "Content Recording: Unable to start recording for display %d since the surface is not available.", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "4200292050699107329": { + "message": "Attempted to get remove mode of a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1720229827": { - "message": "Creating animation bounds layer", - "level": "INFO", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "-5574580669790275797": { + "message": "Attempted to set remove mode to a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1721036256": { - "message": "Attempt to transfer touch gesture using embedded window that has no input channel", + "525945815055875796": { + "message": "Attempted to get flag of a display that does not exist: %d", "level": "WARN", - "group": "WM_DEBUG_EMBEDDED_WINDOWS", - "at": "com\/android\/server\/wm\/EmbeddedWindowController.java" + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1730300180": { - "message": "PendingStartTransaction found", - "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "8186524992939307511": { + "message": "Attempted to set flag to a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1735199721": { - "message": "Queueing transition: %s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" + "-600035824255550632": { + "message": "Attempted to get system decors flag of a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1739298851": { - "message": "removeWindowToken: Attempted to remove token: %s for non-exiting displayId=%d", + "3056518663346732662": { + "message": "Attempted to set system decors flag to a display that does not exist: %d", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1746778201": { - "message": "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "5177195624625618567": { + "message": "Attempted to get IME policy of a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1750878635": { - "message": "Content Recording: Provided surface for recording on display %d is not present, so do not update the surface", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecorder.java" + "3932627933834459400": { + "message": "Attempted to set IME policy to a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1756082882": { - "message": "Orientation change skips hidden %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "5770211341769258866": { + "message": "setWallpaperShowWhenLocked: non-existent wallpaper token: %s", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1774661765": { - "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.", + "698926505694016512": { + "message": "setWallpaperCropHints: non-existent wallpaper token: %s", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1781673113": { - "message": "onAnimationFinished(): targetRootTask=%s targetActivity=%s mRestoreTargetBehindRootTask=%s", + "-7428028317216329062": { + "message": "hideIme target: %s ", "level": "DEBUG", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1786463281": { - "message": "Adding trusted state listener=%s with id=%d", + "1006302987953651112": { + "message": "hideIme Control target: %s ", "level": "DEBUG", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1789321832": { - "message": "Then token:%s is invalid. It might be removed", + "5213970642134448962": { + "message": "Attempted to get home support flag of a display that does not exist: %d", "level": "WARN", "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1789603530": { - "message": "Removing activity %s hasSavedState=%b stateNotNeeded=%s finishing=%b state=%s callers=%s", + "-2065144681579661392": { + "message": "onPointerDownOutsideFocusLocked called on %s", "level": "INFO", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1794249572": { - "message": "Requesting StartTransition: %s", + "-7394143854567081754": { + "message": "grantEmbeddedWindowFocus win=%s dropped focus so setting focus to null since no candidate was found", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/TransitionController.java" - }, - "1804245629": { - "message": "Attempted to add starting window to token but already cleaned", - "level": "WARN", - "group": "WM_ERROR", + "group": "WM_DEBUG_FOCUS", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1805116444": { - "message": "We don't support remote animation for Task with multiple TaskFragmentOrganizers.", - "level": "ERROR", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" - }, - "1810019902": { - "message": "TRANSIT_FLAG_OPEN_BEHIND, adding %s to mOpeningApps", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "1810209625": { - "message": "Animation done in %s: exiting=%b, reportedVisible=%b", + "-6056928081282320632": { + "message": "grantEmbeddedWindowFocus win=%s grantFocus=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "1810872941": { - "message": "setWallpaperCropHints: non-existent wallpaper token: %s", + "6110791601270766802": { + "message": "TaskFragmentTransaction changes are not collected in transition because there is an ongoing sync for applySyncTransaction().", "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowOrganizerController.java" }, - "1820873642": { - "message": "SyncGroup %d: Unfinished dependencies: %s", + "9200403125156001641": { + "message": "Apply window transaction, syncId=%d", "level": "VERBOSE", - "group": "WM_DEBUG_SYNC_ENGINE", - "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/WindowOrganizerController.java" }, - "1822314934": { - "message": "Expected target rootTask=%s to restored behind rootTask=%s but it is behind rootTask=%s", - "level": "WARN", - "group": "WM_DEBUG_RECENTS_ANIMATIONS", - "at": "com\/android\/server\/wm\/RecentsAnimation.java" + "433446585990132440": { + "message": "Set sync ready, syncId=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/WindowOrganizerController.java" }, - "1822843721": { - "message": "Aborted starting %s: startingData=%s", + "6552038620140878489": { + "message": "Transaction ready, syncId=%d", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/WindowOrganizerController.java" }, - "1824105730": { - "message": "setLockTaskAuth: task=%s mLockTaskAuth=%s", - "level": "DEBUG", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/Task.java" + "-4629255026637000251": { + "message": "Sending to proc %s new config %s", + "level": "VERBOSE", + "group": "WM_DEBUG_CONFIGURATION", + "at": "com\/android\/server\/wm\/WindowProcessController.java" }, - "1829094918": { - "message": "onLockTaskPackagesUpdated: removing %s mLockTaskAuth()=%s", + "-7237767461056267619": { + "message": "%s: Setting back callback %s", "level": "DEBUG", - "group": "WM_DEBUG_LOCKTASK", - "at": "com\/android\/server\/wm\/LockTaskController.java" + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1831008694": { - "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/WindowContainer.java" + "8135615413833185273": { + "message": "Adding %s to %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1836214582": { - "message": "startingData was nulled out before handling mAddStartingWindow: %s", + "8842744325264128950": { + "message": "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1836306327": { - "message": "Skipping set freeze of %s", + "-8636590597069784069": { + "message": "Resizing window %s", + "level": "VERBOSE", + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" + }, + "-2710188685736986208": { + "message": "Orientation not waiting for draw in %s, surfaceController %s", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1856783490": { - "message": "resumeTopActivity: Restarting %s", + "5236278969232209904": { + "message": "onMovedByResize: Moving %s", "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1865125884": { - "message": "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, mScreenOnFully=%b, mKeyguardDrawComplete=%b, mWindowManagerDrawComplete=%b", + "7646042751617940718": { + "message": "Set animatingExit: reason=onAppVisibilityChanged win=%s", "level": "DEBUG", - "group": "WM_DEBUG_SCREEN_ON", - "at": "com\/android\/server\/wm\/DisplayPolicy.java" - }, - "1866772666": { - "message": "SAFE MODE not enabled", - "level": "INFO", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1874559932": { - "message": "The TaskDisplayArea with %s does not exist.", - "level": "WARN", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/DisplayAreaPolicyBuilder.java" + "1783521309242112490": { + "message": "onResize: Resizing %s", + "level": "DEBUG", + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1877863087": { - "message": "Display id=%d is ignoring orientation request for %d, return %d", + "1351053513466395411": { + "message": "WS.removeImmediately: %s Already removed...", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1879463933": { - "message": "attachWindowContextToWindowToken: calling from non-existing process pid=%d uid=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "3927343382258792268": { + "message": "removeIfPossible: %s callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1891501279": { - "message": "cancelAnimation(): reason=%s", + "-4831815184899821371": { + "message": "Starting window removed %s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1912291550": { - "message": "Sleep still waiting to pause %s", + "-5803097884846965819": { + "message": "Remove client=%x, surfaceController=%s Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1918448345": { - "message": "Task appeared taskId=%d", + "-2547748024041128829": { + "message": "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b mDisplayFrozen=%b callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_ORGANIZER", - "at": "com\/android\/server\/wm\/TaskOrganizerController.java" - }, - "1928325128": { - "message": "Run showImeRunner", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1931178855": { - "message": "\tnonApp=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "7789778354950913237": { + "message": "Set animatingExit: reason=remove\/applyAnimation win=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1945495497": { - "message": "Focused window didn't have a valid surface drawn.", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" + "-4143841388126586338": { + "message": "Not removing %s due to exit animation", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1946983717": { - "message": "Waiting for screen on due to %s", + "4419190702135590390": { + "message": "Set animatingExit: reason=remove\/isAnimating win=%s", "level": "VERBOSE", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1947239194": { - "message": "Deferring rotation, still finishing previous rotation", + "-6167820560758523840": { + "message": "setAnimationLocked: setting mFocusMayChange true", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowState.java" + }, + "-208079497999140637": { + "message": "WindowState.hideLw: setting mFocusMayChange true", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowState.java" + }, + "8812513438749898553": { + "message": "set mOrientationChanging of %s", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1947936538": { - "message": "Found matching class!", + "-2964267636425934067": { + "message": "win=%s destroySurfaces: appStopped=%b win.mWindowRemovalAllowed=%b win.mRemoveOnExit=%b", + "level": "ERROR", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowState.java" + }, + "7336961102428192483": { + "message": "Clear animatingExit: reason=destroySurface win=%s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1955470028": { - "message": "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s scale=%f,%f", + "-6920306331987525705": { + "message": "Reporting new frame to %s: %s", "level": "VERBOSE", - "group": "WM_DEBUG_TPL", - "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java" + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1964565370": { - "message": "Starting remote animation", + "2714651498627020992": { + "message": "Resizing %s WITH DRAW PENDING", "level": "INFO", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1967975839": { - "message": "Changing app %s visible=%b performLayout=%b", + "-5755338358883139945": { + "message": "Requested redraw for orientation change: %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1984782949": { - "message": ">>> OPEN TRANSACTION animate", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowAnimator.java" + "-5211036212243647844": { + "message": "notifyInsetsChanged for %s ", + "level": "DEBUG", + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1984843251": { - "message": "Hiding wallpaper %s from %s target=%s prev=%s callers=%s", + "-3186229270467822891": { + "message": "notifyInsetsControlChanged for %s ", "level": "DEBUG", - "group": "WM_DEBUG_WALLPAPER", - "at": "com\/android\/server\/wm\/WallpaperController.java" + "group": "WM_DEBUG_WINDOW_INSETS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1995093920": { - "message": "Checking to restart %s: changed=0x%s, handles=0x%s, mLastReportedConfiguration=%s", + "-7413136364930452718": { + "message": "performShowLocked: mDrawState=HAS_DRAWN in %s", "level": "VERBOSE", - "group": "WM_DEBUG_CONFIGURATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "1999594750": { - "message": "startAnimation", + "7624470121297688739": { + "message": "shouldWaitAnimatingExit: isTransition: %s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2001473656": { - "message": "App %s is focused, but the window is not ready. Start a transaction to remove focus from the window of non-focused apps.", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/InputMonitor.java" + "810267895099109466": { + "message": "shouldWaitAnimatingExit: isAnimating: %s", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2004282287": { - "message": "Override sync-method for %s because seamless rotating", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "-1760879391350377377": { + "message": "shouldWaitAnimatingExit: isWallpaperTarget: %s", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2010476671": { - "message": "Animation done in %s: reportedVisible=%b okToDisplay=%b okToAnimate=%b startingDisplayed=%b", + "272960397873328729": { + "message": "Clear window stuck on animatingExit status: %s", + "level": "WARN", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" + }, + "-1007526574020149845": { + "message": "onExitAnimationDone in %s: exiting=%b remove=%b selfAnimating=%b anim=%s", "level": "VERBOSE", "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/ActivityRecord.java" + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2018454757": { - "message": "WS.removeImmediately: %s Already removed...", + "1738645946553610841": { + "message": "Exit animation finished in %s: remove=%b", "level": "VERBOSE", "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/WindowState.java" }, - "2018852077": { - "message": "Creating SplashScreenStartingData", - "level": "VERBOSE", - "group": "WM_DEBUG_STARTING_WINDOW", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, - "2019765997": { - "message": "selectRotationAnimation topFullscreen=%s rotationAnimation=%d forceJumpcut=%b", - "level": "INFO", + "-7737516306844862315": { + "message": "Clear animatingExit: reason=exitAnimationDone win=%s", + "level": "DEBUG", "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/DisplayRotation.java" - }, - "2021079047": { - "message": "%s", - "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", - "at": "com\/android\/server\/wm\/TransitionController.java" + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2022422429": { - "message": "createAnimationAdapter(): container=%s", + "-3153130647145726082": { + "message": "Clear animatingExit: reason=clearAnimatingFlags win=%s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/RemoteAnimationController.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2024493888": { - "message": "\tWallpaper of display=%s is not visible", + "-5202247309108694583": { + "message": "Clear animatingExit: reason=relayoutVisibleWindow win=%s", "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2028163120": { - "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s", + "6291563604478341956": { + "message": "Setting move animation on %s", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2034780299": { - "message": "CHECK_IF_BOOT_ANIMATION_FINISHED:", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-5774445199273871848": { + "message": "Preparing to sync a window that was already in the sync, so try dropping buffer. win=%s", + "level": "DEBUG", + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2039056415": { - "message": "Found matching affinity candidate!", + "8097934579596343476": { + "message": "Got a buffer for request id=%d but latest request is id=%d. Since the buffer is out-of-date, drop it. win=%s", "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" + "group": "WM_DEBUG_SYNC_ENGINE", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2043434284": { - "message": "setWallpaperShowWhenLocked: non-existent wallpaper token: %s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "8269653477215188641": { + "message": "SURFACE isSecure=%b: %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowState.java" }, - "2045641491": { - "message": "Checking %d opening apps (frozen=%b timeout=%b)...", + "-1495677286613044867": { + "message": "Animation done in %s: exiting=%b, reportedVisible=%b", "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2053743391": { - "message": " Add condition %s for #%d", + "3436877176443058520": { + "message": "Finishing drawing window %s: mDrawState=%s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2060978050": { - "message": "moveWindowTokenToDisplay: Attempted to move token: %s to non-exiting displayId=%d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "345647873457403698": { + "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", + "level": "VERBOSE", + "group": "WM_DEBUG_DRAW", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2066210760": { - "message": "foldStateChanged: displayId %d, halfFoldStateChanged %s, saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, mLastOrientation: %d, mRotation: %d", + "-2385558637577093121": { + "message": "Draw state now committed in %s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2070726247": { - "message": "InsetsSource updateVisibility for %s, serverVisible: %s clientVisible: %s", - "level": "DEBUG", - "group": "WM_DEBUG_WINDOW_INSETS", - "at": "com\/android\/server\/wm\/InsetsSourceProvider.java" + "-3490933626936411542": { + "message": "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s", + "level": "INFO", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2075693141": { - "message": "Set animatingExit: reason=startExitingAnimation\/%s win=%s", - "level": "DEBUG", + "-6088246515441976339": { + "message": "createSurface %s: mDrawState=DRAW_PENDING", + "level": "INFO", "group": "WM_DEBUG_ANIM", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2079410261": { - "message": "applyAnimation: override requested, but it is prohibited by policy.", - "level": "ERROR", - "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", - "at": "com\/android\/server\/wm\/AppTransition.java" + "2353125758087345363": { + "message": " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x \/ %s", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2083556954": { - "message": "Set mOrientationChanging of %s", + "-4491856282178275074": { + "message": "SURFACE DESTROY: %s. %s", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + }, + "8602950884833508970": { + "message": "Orientation change skips hidden %s", "level": "VERBOSE", "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2086878461": { - "message": "Could not send command %s with parameters %s. %s", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" + "-5079712802591263622": { + "message": "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2100457473": { - "message": "Task=%d contains embedded TaskFragment. Disabled all input during TaskFragment remote animation.", - "level": "DEBUG", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/AppTransitionController.java" + "-2824875917893878016": { + "message": "Orientation continue waiting for draw in %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2117696413": { - "message": "moveTaskToFront: moving taskId=%d", - "level": "DEBUG", - "group": "WM_DEBUG_TASKS", - "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" + "7457181879495900576": { + "message": "Orientation change complete in %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, - "2119122320": { - "message": "setInputMethodTarget %s", + "-5668794009329913533": { + "message": "applyAnimation: win=%s anim=%d attr=0x%x a=%s transit=%d type=%d isEntrance=%b Callers %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowStateAnimator.java" + }, + "-2055407587764455051": { + "message": "SURFACE HIDE ( %s ): %s", "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowSurfaceController.java" }, - "2124732293": { - "message": "#%d: Met condition: %s", + "-5854683348829455340": { + "message": "Destroying surface %s called by %s", + "level": "INFO", + "group": "WM_SHOW_SURFACE_ALLOC", + "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + }, + "7813672046338784579": { + "message": "SURFACE isOpaque=%b: %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + }, + "-8864150640874799238": { + "message": "SURFACE isColorSpaceAgnostic=%b: %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + }, + "-8398940245851553814": { + "message": "SURFACE SHOW (performLayout): %s", + "level": "INFO", + "group": "WM_SHOW_TRANSACTIONS", + "at": "com\/android\/server\/wm\/WindowSurfaceController.java" + }, + "8174298531248485625": { + "message": "removeAllWindowsIfPossible: removing win=%s", + "level": "WARN", + "group": "WM_DEBUG_WINDOW_MOVEMENT", + "at": "com\/android\/server\/wm\/WindowToken.java" + }, + "2740931087734487464": { + "message": "addWindow: win=%s Callers=%s", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/WindowToken.java" + }, + "2382798629637143561": { + "message": "Adding %s to %s", "level": "VERBOSE", - "group": "WM_DEBUG_WINDOW_TRANSITIONS", - "at": "com\/android\/server\/wm\/Transition.java" + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/WindowToken.java" }, - "2128917433": { - "message": "onProposedRotationChanged, rotation=%d", + "-7314975896738778749": { + "message": "setClientVisible: %s clientVisible=%b Callers=%s", "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayRotation.java" + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowToken.java" } }, "groups": { diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index f3bb21719890..b6ce9b64323b 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -153,6 +153,18 @@ public class Canvas extends BaseCanvas { } /** + * Indicates whether this Canvas is drawing high contrast text. + * + * @see android.view.accessibility.AccessibilityManager#isHighTextContrastEnabled() + * @return True if high contrast text is enabled, false otherwise. + * + * @hide + */ + public boolean isHighContrastTextEnabled() { + return nIsHighContrastText(mNativeCanvasWrapper); + } + + /** * Specify a bitmap for the canvas to draw into. All canvas state such as * layers, filters, and the save/restore stack are reset. Additionally, * the canvas' target density is updated to match that of the bitmap. @@ -1452,6 +1464,8 @@ public class Canvas extends BaseCanvas { @CriticalNative private static native boolean nIsOpaque(long canvasHandle); @CriticalNative + private static native boolean nIsHighContrastText(long canvasHandle); + @CriticalNative private static native int nGetWidth(long canvasHandle); @CriticalNative private static native int nGetHeight(long canvasHandle); diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 69e19824da26..3cd709ea10e5 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -25,9 +25,7 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; - import dalvik.system.CloseGuard; - import libcore.io.IoUtils; import java.io.IOException; @@ -39,12 +37,6 @@ import java.io.IOException; */ public final class PdfEditor { - /** - * Any call the native pdfium code has to be single threaded as the library does not support - * parallel use. - */ - private static final Object sPdfiumLock = new Object(); - private final CloseGuard mCloseGuard = CloseGuard.get(); private long mNativeDocument; @@ -87,7 +79,7 @@ public final class PdfEditor { } mInput = input; - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { mNativeDocument = nativeOpen(mInput.getFd(), size); try { mPageCount = nativeGetPageCount(mNativeDocument); @@ -120,7 +112,7 @@ public final class PdfEditor { throwIfClosed(); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { mPageCount = nativeRemovePage(mNativeDocument, pageIndex); } } @@ -146,12 +138,12 @@ public final class PdfEditor { Point size = new Point(); getPageSize(pageIndex, size); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), 0, 0, size.x, size.y); } } else { - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), clip.left, clip.top, clip.right, clip.bottom); } @@ -169,7 +161,7 @@ public final class PdfEditor { throwIfOutSizeNull(outSize); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeGetPageSize(mNativeDocument, pageIndex, outSize); } } @@ -185,7 +177,7 @@ public final class PdfEditor { throwIfOutMediaBoxNull(outMediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); } } @@ -201,7 +193,7 @@ public final class PdfEditor { throwIfMediaBoxNull(mediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); } } @@ -217,7 +209,7 @@ public final class PdfEditor { throwIfOutCropBoxNull(outCropBox); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); } } @@ -233,7 +225,7 @@ public final class PdfEditor { throwIfCropBoxNull(cropBox); throwIfPageNotInDocument(pageIndex); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); } } @@ -246,7 +238,7 @@ public final class PdfEditor { public boolean shouldScaleForPrinting() { throwIfClosed(); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { return nativeScaleForPrinting(mNativeDocument); } } @@ -263,7 +255,7 @@ public final class PdfEditor { try { throwIfClosed(); - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeWrite(mNativeDocument, output.getFd()); } } finally { @@ -295,7 +287,7 @@ public final class PdfEditor { private void doClose() { if (mNativeDocument != 0) { - synchronized (sPdfiumLock) { + synchronized (PdfRenderer.sPdfiumLock) { nativeClose(mNativeDocument); } mNativeDocument = 0; diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java new file mode 100644 index 000000000000..4666963b5dd4 --- /dev/null +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -0,0 +1,502 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.pdf; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Matrix; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Build; +import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; + +import com.android.internal.util.Preconditions; + +import dalvik.system.CloseGuard; + +import libcore.io.IoUtils; + +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * <p> + * This class enables rendering a PDF document. This class is not thread safe. + * </p> + * <p> + * If you want to render a PDF, you create a renderer and for every page you want + * to render, you open the page, render it, and close the page. After you are done + * with rendering, you close the renderer. After the renderer is closed it should not + * be used anymore. Note that the pages are rendered one by one, i.e. you can have + * only a single page opened at any given time. + * </p> + * <p> + * A typical use of the APIs to render a PDF looks like this: + * </p> + * <pre> + * // create a new renderer + * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); + * + * // let us just render all pages + * final int pageCount = renderer.getPageCount(); + * for (int i = 0; i < pageCount; i++) { + * Page page = renderer.openPage(i); + * + * // say we render for showing on the screen + * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); + * + * // do stuff with the bitmap + * + * // close the page + * page.close(); + * } + * + * // close the renderer + * renderer.close(); + * </pre> + * + * <h3>Print preview and print output</h3> + * <p> + * If you are using this class to rasterize a PDF for printing or show a print + * preview, it is recommended that you respect the following contract in order + * to provide a consistent user experience when seeing a preview and printing, + * i.e. the user sees a preview that is the same as the printout. + * </p> + * <ul> + * <li> + * Respect the property whether the document would like to be scaled for printing + * as per {@link #shouldScaleForPrinting()}. + * </li> + * <li> + * When scaling a document for printing the aspect ratio should be preserved. + * </li> + * <li> + * Do not inset the content with any margins from the {@link android.print.PrintAttributes} + * as the application is responsible to render it such that the margins are respected. + * </li> + * <li> + * If document page size is greater than the printed media size the content should + * be anchored to the upper left corner of the page for left-to-right locales and + * top right corner for right-to-left locales. + * </li> + * </ul> + * + * @see #close() + */ +public final class PdfRenderer implements AutoCloseable { + /** + * Any call the native pdfium code has to be single threaded as the library does not support + * parallel use. + */ + final static Object sPdfiumLock = new Object(); + + private final CloseGuard mCloseGuard = CloseGuard.get(); + + private final Point mTempPoint = new Point(); + + private long mNativeDocument; + + private final int mPageCount; + + private ParcelFileDescriptor mInput; + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private Page mCurrentPage; + + /** @hide */ + @IntDef({ + Page.RENDER_MODE_FOR_DISPLAY, + Page.RENDER_MODE_FOR_PRINT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RenderMode {} + + /** + * Creates a new instance. + * <p> + * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, + * i.e. its data being randomly accessed, e.g. pointing to a file. + * </p> + * <p> + * <strong>Note:</strong> This class takes ownership of the passed in file descriptor + * and is responsible for closing it when the renderer is closed. + * </p> + * <p> + * If the file is from an untrusted source it is recommended to run the renderer in a separate, + * isolated process with minimal permissions to limit the impact of security exploits. + * </p> + * + * @param input Seekable file descriptor to read from. + * + * @throws java.io.IOException If an error occurs while reading the file. + * @throws java.lang.SecurityException If the file requires a password or + * the security scheme is not supported. + */ + public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { + if (input == null) { + throw new NullPointerException("input cannot be null"); + } + + final long size; + try { + Os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); + size = Os.fstat(input.getFileDescriptor()).st_size; + } catch (ErrnoException ee) { + throw new IllegalArgumentException("file descriptor not seekable"); + } + mInput = input; + + synchronized (sPdfiumLock) { + mNativeDocument = nativeCreate(mInput.getFd(), size); + try { + mPageCount = nativeGetPageCount(mNativeDocument); + } catch (Throwable t) { + nativeClose(mNativeDocument); + mNativeDocument = 0; + throw t; + } + } + + mCloseGuard.open("close"); + } + + /** + * Closes this renderer. You should not use this instance + * after this method is called. + */ + public void close() { + throwIfClosed(); + throwIfPageOpened(); + doClose(); + } + + /** + * Gets the number of pages in the document. + * + * @return The page count. + */ + public int getPageCount() { + throwIfClosed(); + return mPageCount; + } + + /** + * Gets whether the document prefers to be scaled for printing. + * You should take this info account if the document is rendered + * for printing and the target media size differs from the page + * size. + * + * @return If to scale the document. + */ + public boolean shouldScaleForPrinting() { + throwIfClosed(); + + synchronized (sPdfiumLock) { + return nativeScaleForPrinting(mNativeDocument); + } + } + + /** + * Opens a page for rendering. + * + * @param index The page index. + * @return A page that can be rendered. + * + * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() + */ + public Page openPage(int index) { + throwIfClosed(); + throwIfPageOpened(); + throwIfPageNotInDocument(index); + mCurrentPage = new Page(index); + return mCurrentPage; + } + + @Override + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + + doClose(); + } finally { + super.finalize(); + } + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private void doClose() { + if (mCurrentPage != null) { + mCurrentPage.close(); + mCurrentPage = null; + } + + if (mNativeDocument != 0) { + synchronized (sPdfiumLock) { + nativeClose(mNativeDocument); + } + mNativeDocument = 0; + } + + if (mInput != null) { + IoUtils.closeQuietly(mInput); + mInput = null; + } + mCloseGuard.close(); + } + + private void throwIfClosed() { + if (mInput == null) { + throw new IllegalStateException("Already closed"); + } + } + + private void throwIfPageOpened() { + if (mCurrentPage != null) { + throw new IllegalStateException("Current page not closed"); + } + } + + private void throwIfPageNotInDocument(int pageIndex) { + if (pageIndex < 0 || pageIndex >= mPageCount) { + throw new IllegalArgumentException("Invalid page index"); + } + } + + /** + * This class represents a PDF document page for rendering. + */ + public final class Page implements AutoCloseable { + + private final CloseGuard mCloseGuard = CloseGuard.get(); + + /** + * Mode to render the content for display on a screen. + */ + public static final int RENDER_MODE_FOR_DISPLAY = 1; + + /** + * Mode to render the content for printing. + */ + public static final int RENDER_MODE_FOR_PRINT = 2; + + private final int mIndex; + private final int mWidth; + private final int mHeight; + + private long mNativePage; + + private Page(int index) { + Point size = mTempPoint; + synchronized (sPdfiumLock) { + mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); + } + mIndex = index; + mWidth = size.x; + mHeight = size.y; + mCloseGuard.open("close"); + } + + /** + * Gets the page index. + * + * @return The index. + */ + public int getIndex() { + return mIndex; + } + + /** + * Gets the page width in points (1/72"). + * + * @return The width in points. + */ + public int getWidth() { + return mWidth; + } + + /** + * Gets the page height in points (1/72"). + * + * @return The height in points. + */ + public int getHeight() { + return mHeight; + } + + /** + * Renders a page to a bitmap. + * <p> + * You may optionally specify a rectangular clip in the bitmap bounds. No rendering + * outside the clip will be performed, hence it is your responsibility to initialize + * the bitmap outside the clip. + * </p> + * <p> + * You may optionally specify a matrix to transform the content from page coordinates + * which are in points (1/72") to bitmap coordinates which are in pixels. If this + * matrix is not provided this method will apply a transformation that will fit the + * whole page to the destination clip if provided or the destination bitmap if no + * clip is provided. + * </p> + * <p> + * The clip and transformation are useful for implementing tile rendering where the + * destination bitmap contains a portion of the image, for example when zooming. + * Another useful application is for printing where the size of the bitmap holding + * the page is too large and a client can render the page in stripes. + * </p> + * <p> + * <strong>Note: </strong> The destination bitmap format must be + * {@link Config#ARGB_8888 ARGB}. + * </p> + * <p> + * <strong>Note: </strong> The optional transformation matrix must be affine as per + * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify + * rotation, scaling, translation but not a perspective transformation. + * </p> + * + * @param destination Destination bitmap to which to render. + * @param destClip Optional clip in the bitmap bounds. + * @param transform Optional transformation to apply when rendering. + * @param renderMode The render mode. + * + * @see #RENDER_MODE_FOR_DISPLAY + * @see #RENDER_MODE_FOR_PRINT + */ + public void render(@NonNull Bitmap destination, @Nullable Rect destClip, + @Nullable Matrix transform, @RenderMode int renderMode) { + if (mNativePage == 0) { + throw new NullPointerException(); + } + + destination = Preconditions.checkNotNull(destination, "bitmap null"); + + if (destination.getConfig() != Config.ARGB_8888) { + throw new IllegalArgumentException("Unsupported pixel format"); + } + + if (destClip != null) { + if (destClip.left < 0 || destClip.top < 0 + || destClip.right > destination.getWidth() + || destClip.bottom > destination.getHeight()) { + throw new IllegalArgumentException("destBounds not in destination"); + } + } + + if (transform != null && !transform.isAffine()) { + throw new IllegalArgumentException("transform not affine"); + } + + if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { + throw new IllegalArgumentException("Unsupported render mode"); + } + + if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { + throw new IllegalArgumentException("Only single render mode supported"); + } + + final int contentLeft = (destClip != null) ? destClip.left : 0; + final int contentTop = (destClip != null) ? destClip.top : 0; + final int contentRight = (destClip != null) ? destClip.right + : destination.getWidth(); + final int contentBottom = (destClip != null) ? destClip.bottom + : destination.getHeight(); + + // If transform is not set, stretch page to whole clipped area + if (transform == null) { + int clipWidth = contentRight - contentLeft; + int clipHeight = contentBottom - contentTop; + + transform = new Matrix(); + transform.postScale((float)clipWidth / getWidth(), + (float)clipHeight / getHeight()); + transform.postTranslate(contentLeft, contentTop); + } + + // FIXME: This code is planned to be outside the UI rendering module, so it should not + // be able to access native instances from Bitmap, Matrix, etc. + final long transformPtr = transform.ni(); + + synchronized (sPdfiumLock) { + nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), + contentLeft, contentTop, contentRight, contentBottom, transformPtr, + renderMode); + } + } + + /** + * Closes this page. + * + * @see android.graphics.pdf.PdfRenderer#openPage(int) + */ + @Override + public void close() { + throwIfClosed(); + doClose(); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + + doClose(); + } finally { + super.finalize(); + } + } + + private void doClose() { + if (mNativePage != 0) { + synchronized (sPdfiumLock) { + nativeClosePage(mNativePage); + } + mNativePage = 0; + } + + mCloseGuard.close(); + mCurrentPage = null; + } + + private void throwIfClosed() { + if (mNativePage == 0) { + throw new IllegalStateException("Already closed"); + } + } + } + + private static native long nativeCreate(int fd, long size); + private static native void nativeClose(long documentPtr); + private static native int nativeGetPageCount(long documentPtr); + private static native boolean nativeScaleForPrinting(long documentPtr); + private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, + int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, + int renderMode); + private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, + Point outSize); + private static native void nativeClosePage(long pagePtr); +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java index 65955b1d9bcc..e37dea4dfd69 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java @@ -126,7 +126,7 @@ public final class CommonFoldingFeature { * @see #FEATURE_PATTERN * @return {@link List} of {@link CommonFoldingFeature}. */ - static List<CommonFoldingFeature> parseListFromString(@NonNull String value, + public static List<CommonFoldingFeature> parseListFromString(@NonNull String value, @State int hingeState) { List<CommonFoldingFeature> features = new ArrayList<>(); String[] featureStrings = value.split(";"); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index a184dff5005b..88fd461debbe 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -36,6 +36,7 @@ import androidx.window.util.BaseDataProducer; import com.android.internal.R; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -78,7 +79,9 @@ public final class DeviceStateManagerFoldingFeatureProducer private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE; @NonNull - private final BaseDataProducer<String> mRawFoldSupplier; + private final RawFoldingFeatureProducer mRawFoldSupplier; + + private final boolean mIsHalfOpenedSupported; private final DeviceStateCallback mDeviceStateCallback = new DeviceStateCallback() { @Override @@ -101,10 +104,12 @@ public final class DeviceStateManagerFoldingFeatureProducer }; public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context, - @NonNull BaseDataProducer<String> rawFoldSupplier) { + @NonNull RawFoldingFeatureProducer rawFoldSupplier, + @NonNull DeviceStateManager deviceStateManager) { mRawFoldSupplier = rawFoldSupplier; String[] deviceStatePosturePairs = context.getResources() .getStringArray(R.array.config_device_state_postures); + boolean isHalfOpenedSupported = false; for (String deviceStatePosturePair : deviceStatePosturePairs) { String[] deviceStatePostureMapping = deviceStatePosturePair.split(":"); if (deviceStatePostureMapping.length != 2) { @@ -128,12 +133,13 @@ public final class DeviceStateManagerFoldingFeatureProducer } continue; } - + isHalfOpenedSupported = isHalfOpenedSupported + || posture == CommonFoldingFeature.COMMON_STATE_HALF_OPENED; mDeviceStateToPostureMap.put(deviceState, posture); } - + mIsHalfOpenedSupported = isHalfOpenedSupported; if (mDeviceStateToPostureMap.size() > 0) { - Objects.requireNonNull(context.getSystemService(DeviceStateManager.class)) + Objects.requireNonNull(deviceStateManager) .registerCallback(context.getMainExecutor(), mDeviceStateCallback); } } @@ -188,6 +194,31 @@ public final class DeviceStateManagerFoldingFeatureProducer } /** + * Returns a {@link List} of all the {@link CommonFoldingFeature} with the state set to + * {@link CommonFoldingFeature#COMMON_STATE_UNKNOWN}. This method parses a {@link String} so a + * caller should consider caching the value or the derived value. + */ + @NonNull + public List<CommonFoldingFeature> getFoldsWithUnknownState() { + Optional<String> optionalFoldingFeatureString = mRawFoldSupplier.getCurrentData(); + + if (optionalFoldingFeatureString.isPresent()) { + return CommonFoldingFeature.parseListFromString( + optionalFoldingFeatureString.get(), CommonFoldingFeature.COMMON_STATE_UNKNOWN + ); + } + return Collections.emptyList(); + } + + + /** + * Returns {@code true} if the device supports half-opened mode, {@code false} otherwise. + */ + public boolean isHalfOpenedSupported() { + return mIsHalfOpenedSupported; + } + + /** * Adds the data to the storeFeaturesConsumer when the data is ready. * @param storeFeaturesConsumer a consumer to collect the data when it is first available. */ diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java index 29cf05407a61..6714263ad952 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java @@ -20,6 +20,7 @@ import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.Application; import android.content.Context; +import android.hardware.devicestate.DeviceStateManager; import android.util.Log; import androidx.annotation.NonNull; @@ -64,6 +65,11 @@ public class WindowExtensionsImpl implements WindowExtensions { } @NonNull + private DeviceStateManager getDeviceStateManager() { + return Objects.requireNonNull(getApplication().getSystemService(DeviceStateManager.class)); + } + + @NonNull private DeviceStateManagerFoldingFeatureProducer getFoldingFeatureProducer() { if (mFoldingFeatureProducer == null) { synchronized (mLock) { @@ -73,7 +79,7 @@ public class WindowExtensionsImpl implements WindowExtensions { new RawFoldingFeatureProducer(context); mFoldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context, - foldingFeatureProducer); + foldingFeatureProducer, getDeviceStateManager()); } } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index b2e5b75cf0b5..ae3a854baf9f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -72,6 +72,7 @@ import android.util.Pair; import android.util.Size; import android.util.SparseArray; import android.view.WindowMetrics; +import android.window.ActivityWindowInfo; import android.window.TaskFragmentAnimationParams; import android.window.TaskFragmentInfo; import android.window.TaskFragmentOperation; @@ -2864,11 +2865,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen */ @Override public boolean isActivityEmbedded(@NonNull Activity activity) { + Objects.requireNonNull(activity); synchronized (mLock) { + if (Flags.activityWindowInfoFlag()) { + final ActivityWindowInfo activityWindowInfo = getActivityWindowInfo(activity); + return activityWindowInfo != null && activityWindowInfo.isEmbedded(); + } return mPresenter.isActivityEmbedded(activity.getActivityToken()); } } + @Nullable + private static ActivityWindowInfo getActivityWindowInfo(@NonNull Activity activity) { + if (activity.isFinishing()) { + return null; + } + final ActivityThread.ActivityClientRecord record = + ActivityThread.currentActivityThread() + .getActivityClient(activity.getActivityToken()); + return record != null ? record.getActivityWindowInfo() : null; + } + /** * If the two rules have the same presentation, and the calculated {@link SplitAttributes} * matches the {@link SplitAttributes} of {@link SplitContainer}, we can reuse the same diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java new file mode 100644 index 000000000000..a0f481a911ad --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/DisplayFoldFeatureUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.window.extensions.layout; + +import androidx.window.common.CommonFoldingFeature; +import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; + +import java.util.ArrayList; +import java.util.List; + +/** + * Util functions for working with {@link androidx.window.extensions.layout.DisplayFoldFeature}. + */ +public class DisplayFoldFeatureUtil { + + private DisplayFoldFeatureUtil() {} + + private static DisplayFoldFeature create(CommonFoldingFeature foldingFeature, + boolean isHalfOpenedSupported) { + final int foldType; + if (foldingFeature.getType() == CommonFoldingFeature.COMMON_TYPE_HINGE) { + foldType = DisplayFoldFeature.TYPE_HINGE; + } else { + foldType = DisplayFoldFeature.TYPE_SCREEN_FOLD_IN; + } + DisplayFoldFeature.Builder featureBuilder = new DisplayFoldFeature.Builder(foldType); + + if (isHalfOpenedSupported) { + featureBuilder.addProperty(DisplayFoldFeature.FOLD_PROPERTY_SUPPORTS_HALF_OPENED); + } + return featureBuilder.build(); + } + + /** + * Returns the list of supported {@link DisplayFeature} calculated from the + * {@link DeviceStateManagerFoldingFeatureProducer}. + */ + public static List<DisplayFoldFeature> extractDisplayFoldFeatures( + DeviceStateManagerFoldingFeatureProducer producer) { + List<DisplayFoldFeature> foldFeatures = new ArrayList<>(); + List<CommonFoldingFeature> folds = producer.getFoldsWithUnknownState(); + + final boolean isHalfOpenedSupported = producer.isHalfOpenedSupported(); + for (CommonFoldingFeature fold : folds) { + foldFeatures.add(DisplayFoldFeatureUtil.create(fold, isHalfOpenedSupported)); + } + return foldFeatures; + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index 6e704f35fb22..4fd11c495529 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -45,7 +45,6 @@ import androidx.window.common.CommonFoldingFeature; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.extensions.core.util.function.Consumer; -import androidx.window.util.DataProducer; import java.util.ArrayList; import java.util.Collections; @@ -56,10 +55,6 @@ import java.util.Set; /** * Reference implementation of androidx.window.extensions.layout OEM interface for use with * WindowManager Jetpack. - * - * NOTE: This version is a work in progress and under active development. It MUST NOT be used in - * production builds since the interface can still change before reaching stable version. - * Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead. */ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private static final String TAG = WindowLayoutComponentImpl.class.getSimpleName(); @@ -71,7 +66,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { new ArrayMap<>(); @GuardedBy("mLock") - private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; + private final DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer; @GuardedBy("mLock") private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>(); @@ -87,12 +82,17 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private final RawConfigurationChangedListener mRawConfigurationChangedListener = new RawConfigurationChangedListener(); + private final SupportedWindowFeatures mSupportedWindowFeatures; + public WindowLayoutComponentImpl(@NonNull Context context, @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) { ((Application) context.getApplicationContext()) .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); mFoldingFeatureProducer = foldingFeatureProducer; mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + final List<DisplayFoldFeature> displayFoldFeatures = + DisplayFoldFeatureUtil.extractDisplayFoldFeatures(mFoldingFeatureProducer); + mSupportedWindowFeatures = new SupportedWindowFeatures.Builder(displayFoldFeatures).build(); } /** @@ -283,6 +283,15 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { } } + /** + * Returns the {@link SupportedWindowFeatures} for the device. This list does not change over + * time. + */ + @NonNull + public SupportedWindowFeatures getSupportedWindowFeatures() { + return mSupportedWindowFeatures; + } + /** @see #getWindowLayoutInfo(Context, List) */ private WindowLayoutInfo getWindowLayoutInfo(int displayId, @NonNull WindowConfiguration windowConfiguration, diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index a836e05b2d66..56c3bce87d6e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -17,6 +17,7 @@ package androidx.window.sidecar; import static android.view.Display.DEFAULT_DISPLAY; + import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; @@ -25,6 +26,7 @@ import android.app.ActivityThread; import android.app.Application; import android.content.Context; import android.graphics.Rect; +import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.IBinder; @@ -49,10 +51,11 @@ class SampleSidecarImpl extends StubSidecar { SampleSidecarImpl(Context context) { ((Application) context.getApplicationContext()) .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); - BaseDataProducer<String> settingsFeatureProducer = new RawFoldingFeatureProducer(context); + RawFoldingFeatureProducer settingsFeatureProducer = new RawFoldingFeatureProducer(context); BaseDataProducer<List<CommonFoldingFeature>> foldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context, - settingsFeatureProducer); + settingsFeatureProducer, + context.getSystemService(DeviceStateManager.class)); foldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index d66c925de376..0ecf1f8f1feb 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -82,16 +82,18 @@ filegroup { genrule { name: "wm_shell_protolog_src", srcs: [ + ":protolog-impl", ":wm_shell_protolog-groups", ":wm_shell-sources", ], tools: ["protologtool"], cmd: "$(location protologtool) transform-protolog-calls " + "--protolog-class com.android.internal.protolog.common.ProtoLog " + - "--protolog-impl-class com.android.wm.shell.protolog.ShellProtoLogImpl " + - "--protolog-cache-class com.android.wm.shell.protolog.ShellProtoLogCache " + "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " + "--loggroups-jar $(location :wm_shell_protolog-groups) " + + "--viewer-config-file-path /system_ext/etc/wmshell.protolog.pb " + + "--legacy-viewer-config-file-path /system_ext/etc/wmshell.protolog.json.gz " + + "--legacy-output-file-path /data/misc/wmtrace/shell_log.winscope " + "--output-srcjar $(out) " + "$(locations :wm_shell-sources)", out: ["wm_shell_protolog.srcjar"], @@ -108,12 +110,30 @@ genrule { "--protolog-class com.android.internal.protolog.common.ProtoLog " + "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " + "--loggroups-jar $(location :wm_shell_protolog-groups) " + - "--viewer-conf $(out) " + + "--viewer-config-type json " + + "--viewer-config $(out) " + "$(locations :wm_shell-sources)", out: ["wm_shell_protolog.json"], } genrule { + name: "gen-wmshell.protolog.pb", + srcs: [ + ":wm_shell_protolog-groups", + ":wm_shell-sources", + ], + tools: ["protologtool"], + cmd: "$(location protologtool) generate-viewer-config " + + "--protolog-class com.android.internal.protolog.common.ProtoLog " + + "--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " + + "--loggroups-jar $(location :wm_shell_protolog-groups) " + + "--viewer-config-type proto " + + "--viewer-config $(out) " + + "$(locations :wm_shell-sources)", + out: ["wmshell.protolog.pb"], +} + +genrule { name: "protolog.json.gz", srcs: [":generate-wm_shell_protolog.json"], out: ["wmshell.protolog.json.gz"], @@ -127,6 +147,13 @@ prebuilt_etc { filename_from_src: true, } +prebuilt_etc { + name: "wmshell.protolog.pb", + system_ext_specific: true, + src: ":gen-wmshell.protolog.pb", + filename_from_src: true, +} + // End ProtoLog java_library { diff --git a/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_dark.xml b/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_dark.xml new file mode 100644 index 000000000000..52a59671baa1 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_dark.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_hovered="true" + android:color="@color/desktop_mode_caption_button_on_hover_dark"/> + <item android:color="@color/desktop_mode_caption_button"/> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_light.xml b/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_light.xml new file mode 100644 index 000000000000..6d8a51cd6f8f --- /dev/null +++ b/libs/WindowManager/Shell/res/color/desktop_mode_caption_button_color_selector_light.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_hovered="true" + android:color="@color/desktop_mode_caption_button_on_hover_light"/> + <item android:color="@color/desktop_mode_caption_button"/> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/circular_progress.xml b/libs/WindowManager/Shell/res/drawable/circular_progress.xml new file mode 100644 index 000000000000..948264579e1d --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/circular_progress.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/progress"> + <rotate + android:pivotX="50%" + android:pivotY="50%" + android:fromDegrees="275" + android:toDegrees="275"> + <shape + android:shape="ring" + android:thickness="3dp" + android:innerRadius="17dp" + android:useLevel="true"> + </shape> + </rotate> + </item> +</layer-list>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/rounded_button.xml b/libs/WindowManager/Shell/res/drawable/rounded_button.xml new file mode 100644 index 000000000000..17a0bab56a74 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/rounded_button.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <corners android:radius="20dp" /> +</shape>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml index e4f793c2665b..d1b1af3e77ab 100644 --- a/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml +++ b/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml @@ -74,17 +74,11 @@ android:layout_height="40dp" android:layout_weight="1"/> - <ImageButton - android:id="@+id/maximize_window" - android:layout_width="40dp" - android:layout_height="40dp" - android:padding="9dp" - android:layout_marginEnd="8dp" - android:contentDescription="@string/maximize_button_text" - android:src="@drawable/decor_desktop_mode_maximize_button_dark" - android:scaleType="fitCenter" - android:gravity="end" - android:background="@null"/> + <com.android.wm.shell.windowdecor.MaximizeButtonView + android:id="@+id/maximize_button_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end"/> <ImageButton android:id="@+id/close_window" diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml index 0db72f7be8e6..dbfd6e5d8d94 100644 --- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml +++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml @@ -15,6 +15,7 @@ ~ limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/maximize_menu" style="?android:attr/buttonBarStyle" android:layout_width="@dimen/desktop_mode_maximize_menu_width" android:layout_height="@dimen/desktop_mode_maximize_menu_height" diff --git a/libs/WindowManager/Shell/res/layout/maximize_menu_button.xml b/libs/WindowManager/Shell/res/layout/maximize_menu_button.xml new file mode 100644 index 000000000000..bb6efcec1a70 --- /dev/null +++ b/libs/WindowManager/Shell/res/layout/maximize_menu_button.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <ProgressBar + android:id="@+id/progress_bar" + style="?android:attr/progressBarStyleHorizontal" + android:progressDrawable="@drawable/circular_progress" + android:layout_width="40dp" + android:layout_height="40dp" + android:indeterminate="false" + android:visibility="invisible"/> + + <ImageButton + android:id="@+id/maximize_window" + android:layout_width="40dp" + android:layout_height="40dp" + android:padding="9dp" + android:contentDescription="@string/maximize_button_text" + android:src="@drawable/decor_desktop_mode_maximize_button_dark" + android:scaleType="fitCenter" + android:background="@drawable/rounded_button"/> +</merge>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml index fae71efe3b39..758dbfd5f3c5 100644 --- a/libs/WindowManager/Shell/res/values/colors.xml +++ b/libs/WindowManager/Shell/res/values/colors.xml @@ -66,4 +66,9 @@ <color name="desktop_mode_maximize_menu_button_outline">#797869</color> <color name="desktop_mode_maximize_menu_button_outline_on_hover">#606219</color> <color name="desktop_mode_maximize_menu_button_on_hover">#E7E790</color> + <color name="desktop_mode_maximize_menu_progress_light">#33000000</color> + <color name="desktop_mode_maximize_menu_progress_dark">#33FFFFFF</color> + <color name="desktop_mode_caption_button_on_hover_light">#11000000</color> + <color name="desktop_mode_caption_button_on_hover_dark">#11FFFFFF</color> + <color name="desktop_mode_caption_button">#00000000</color> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java index 88525aabe53b..93893e33d2d5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java @@ -16,7 +16,10 @@ package com.android.wm.shell; -import com.android.wm.shell.protolog.ShellProtoLogImpl; +import com.android.internal.protolog.LegacyProtoLogImpl; +import com.android.internal.protolog.common.ILogger; +import com.android.internal.protolog.common.IProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellInit; @@ -24,19 +27,19 @@ import java.io.PrintWriter; import java.util.Arrays; /** - * Controls the {@link ShellProtoLogImpl} in WMShell via adb shell commands. + * Controls the {@link ProtoLog} in WMShell via adb shell commands. * * Use with {@code adb shell dumpsys activity service SystemUIService WMShell protolog ...}. */ public class ProtoLogController implements ShellCommandHandler.ShellCommandActionHandler { private final ShellCommandHandler mShellCommandHandler; - private final ShellProtoLogImpl mShellProtoLog; + private final IProtoLog mShellProtoLog; public ProtoLogController(ShellInit shellInit, ShellCommandHandler shellCommandHandler) { shellInit.addInitCallback(this::onInit, this); mShellCommandHandler = shellCommandHandler; - mShellProtoLog = ShellProtoLogImpl.getSingleInstance(); + mShellProtoLog = ProtoLog.getSingleInstance(); } void onInit() { @@ -45,22 +48,35 @@ public class ProtoLogController implements ShellCommandHandler.ShellCommandActio @Override public boolean onShellCommand(String[] args, PrintWriter pw) { + final ILogger logger = pw::println; switch (args[0]) { case "status": { - pw.println(mShellProtoLog.getStatus()); + if (android.tracing.Flags.perfettoProtolog()) { + pw.println("(Deprecated) legacy command. Use Perfetto commands instead."); + return false; + } + ((LegacyProtoLogImpl) mShellProtoLog).getStatus(); return true; } case "start": { - mShellProtoLog.startProtoLog(pw); + if (android.tracing.Flags.perfettoProtolog()) { + pw.println("(Deprecated) legacy command. Use Perfetto commands instead."); + return false; + } + ((LegacyProtoLogImpl) mShellProtoLog).startProtoLog(pw); return true; } case "stop": { - mShellProtoLog.stopProtoLog(pw, true /* writeToFile */); + if (android.tracing.Flags.perfettoProtolog()) { + pw.println("(Deprecated) legacy command. Use Perfetto commands instead."); + return false; + } + ((LegacyProtoLogImpl) mShellProtoLog).stopProtoLog(pw, true); return true; } case "enable-text": { String[] groups = Arrays.copyOfRange(args, 1, args.length); - int result = mShellProtoLog.startTextLogging(groups, pw); + int result = mShellProtoLog.startLoggingToLogcat(groups, logger); if (result == 0) { pw.println("Starting logging on groups: " + Arrays.toString(groups)); return true; @@ -69,7 +85,7 @@ public class ProtoLogController implements ShellCommandHandler.ShellCommandActio } case "disable-text": { String[] groups = Arrays.copyOfRange(args, 1, args.length); - int result = mShellProtoLog.stopTextLogging(groups, pw); + int result = mShellProtoLog.stopLoggingToLogcat(groups, logger); if (result == 0) { pw.println("Stopping logging on groups: " + Arrays.toString(groups)); return true; @@ -78,19 +94,23 @@ public class ProtoLogController implements ShellCommandHandler.ShellCommandActio } case "enable": { String[] groups = Arrays.copyOfRange(args, 1, args.length); - return mShellProtoLog.startTextLogging(groups, pw) == 0; + return mShellProtoLog.startLoggingToLogcat(groups, logger) == 0; } case "disable": { String[] groups = Arrays.copyOfRange(args, 1, args.length); - return mShellProtoLog.stopTextLogging(groups, pw) == 0; + return mShellProtoLog.stopLoggingToLogcat(groups, logger) == 0; } case "save-for-bugreport": { + if (android.tracing.Flags.perfettoProtolog()) { + pw.println("(Deprecated) legacy command"); + return false; + } if (!mShellProtoLog.isProtoEnabled()) { pw.println("Logging to proto is not enabled for WMShell."); return false; } - mShellProtoLog.stopProtoLog(pw, true /* writeToFile */); - mShellProtoLog.startProtoLog(pw); + ((LegacyProtoLogImpl) mShellProtoLog).stopProtoLog(pw, true /* writeToFile */); + ((LegacyProtoLogImpl) mShellProtoLog).startProtoLog(pw); return true; } default: { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 34be9b097e81..2606fb661e80 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -114,6 +114,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont /** Tracks if we should start the back gesture on the next motion move event */ private boolean mShouldStartOnNextMoveEvent = false; private boolean mOnBackStartDispatched = false; + private boolean mPointerPilfered = false; private final FlingAnimationUtils mFlingAnimationUtils; @@ -404,11 +405,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @VisibleForTesting void onPilferPointers() { + mPointerPilfered = true; // Dispatch onBackStarted, only to app callbacks. // System callbacks will receive onBackStarted when the remote animation starts. if (!shouldDispatchToAnimator() && mActiveCallback != null) { mCurrentTracker.updateStartLocation(); - tryDispatchAppOnBackStarted(mActiveCallback, mCurrentTracker.createStartEvent(null)); + tryDispatchOnBackStarted(mActiveCallback, mCurrentTracker.createStartEvent(null)); } } @@ -511,7 +513,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback(); // App is handling back animation. Cancel system animation latency tracking. cancelLatencyTracking(); - tryDispatchAppOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null)); + tryDispatchOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null)); } } @@ -555,14 +557,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont && mBackNavigationInfo.isPrepareRemoteAnimation(); } - private void tryDispatchAppOnBackStarted( + private void tryDispatchOnBackStarted( IOnBackInvokedCallback callback, BackMotionEvent backEvent) { - if (mOnBackStartDispatched && callback != null) { + if (mOnBackStartDispatched || callback == null || !mPointerPilfered) { return; } dispatchOnBackStarted(callback, backEvent); - mOnBackStartDispatched = true; } private void dispatchOnBackStarted( @@ -573,6 +574,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } try { callback.onBackStarted(backEvent); + mOnBackStartDispatched = true; } catch (RemoteException e) { Log.e(TAG, "dispatchOnBackStarted error: ", e); } @@ -872,6 +874,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mActiveCallback = null; mShouldStartOnNextMoveEvent = false; mOnBackStartDispatched = false; + mPointerPilfered = false; mShellBackAnimationRegistry.resetDefaultCrossActivity(); cancelLatencyTracking(); if (mBackNavigationInfo != null) { @@ -957,15 +960,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mCurrentTracker.updateStartLocation(); BackMotionEvent startEvent = mCurrentTracker.createStartEvent(apps[0]); - // {@code mActiveCallback} is the callback from - // the BackAnimationRunners and not a real app-side - // callback. We also dispatch to the app-side callback - // (which should be a system callback with PRIORITY_SYSTEM) - // to keep consistent with app registered callbacks. dispatchOnBackStarted(mActiveCallback, startEvent); - tryDispatchAppOnBackStarted( - mBackNavigationInfo.getOnBackInvokedCallback(), - startEvent); } // Dispatch the first progress after animation start for diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index e0f0556d03f0..15350fb19209 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -122,6 +122,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -247,6 +248,9 @@ public class BubbleController implements ConfigurationChangeListener, /** Saved font scale, used to detect font size changes in {@link #onConfigurationChanged}. */ private float mFontScale = 0; + /** Saved locale, used to detect local changes in {@link #onConfigurationChanged}. */ + private Locale mLocale = null; + /** Saved direction, used to detect layout direction changes @link #onConfigChanged}. */ private int mLayoutDirection = View.LAYOUT_DIRECTION_UNDEFINED; @@ -683,6 +687,17 @@ public class BubbleController implements ConfigurationChangeListener, mDataRepository.removeBubblesForUser(removedUserId, parentUserId); } + /** Called when sensitive notification state has changed */ + public void onSensitiveNotificationProtectionStateChanged( + boolean sensitiveNotificationProtectionActive) { + if (mStackView != null) { + mStackView.onSensitiveNotificationProtectionStateChanged( + sensitiveNotificationProtectionActive); + ProtoLog.d(WM_SHELL_BUBBLES, "onSensitiveNotificationProtectionStateChanged=%b", + sensitiveNotificationProtectionActive); + } + } + /** Whether bubbles are showing in the bubble bar. */ public boolean isShowingAsBubbleBar() { return canShowAsBubbleBar() && mBubbleStateListener != null; @@ -1057,6 +1072,11 @@ public class BubbleController implements ConfigurationChangeListener, mLayoutDirection = newConfig.getLayoutDirection(); mStackView.onLayoutDirectionChanged(mLayoutDirection); } + Locale newLocale = newConfig.locale; + if (newLocale != null && !newLocale.equals(mLocale)) { + mLocale = newLocale; + mStackView.updateLocale(); + } } } @@ -2583,6 +2603,14 @@ public class BubbleController implements ConfigurationChangeListener, mMainExecutor.execute( () -> BubbleController.this.onNotificationPanelExpandedChanged(expanded)); } + + @Override + public void onSensitiveNotificationProtectionStateChanged( + boolean sensitiveNotificationProtectionActive) { + mMainExecutor.execute( + () -> BubbleController.this.onSensitiveNotificationProtectionStateChanged( + sensitiveNotificationProtectionActive)); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 123693db3622..74f087b6d8f8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -517,6 +517,15 @@ public class BubbleExpandedView extends LinearLayout { } } + void updateLocale() { + if (mManageButton != null) { + mManageButton.setText(mContext.getString(R.string.manage_bubbles_text)); + } + if (mOverflowView != null) { + mOverflowView.updateLocale(); + } + } + void applyThemeAttrs() { final TypedArray ta = mContext.obtainStyledAttributes(new int[]{ android.R.attr.dialogCornerRadius, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java index b06de4f4002c..633b01bde4ca 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java @@ -242,6 +242,11 @@ public class BubbleOverflowContainerView extends LinearLayout { mEmptyStateSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); } + public void updateLocale() { + mEmptyStateTitle.setText(mContext.getString(R.string.bubble_overflow_empty_title)); + mEmptyStateSubtitle.setText(mContext.getString(R.string.bubble_overflow_empty_subtitle)); + } + private final BubbleData.Listener mDataListener = new BubbleData.Listener() { @Override 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 b23fd5269eae..8fd6ffe15cfe 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 @@ -291,6 +291,11 @@ public class BubbleStackView extends FrameLayout */ private boolean mRemovingLastBubbleWhileExpanded = false; + /** + * Whether sensitive notification protection should disable flyout + */ + private boolean mSensitiveNotificationProtectionActive = false; + /** Animator for animating the expanded view's alpha (including the TaskView inside it). */ private final ValueAnimator mExpandedViewAlphaAnimator = ValueAnimator.ofFloat(0f, 1f); @@ -1447,6 +1452,12 @@ public class BubbleStackView extends FrameLayout } } + void updateLocale() { + if (mBubbleOverflow != null && mBubbleOverflow.getExpandedView() != null) { + mBubbleOverflow.getExpandedView().updateLocale(); + } + } + private void updateOverflow() { mBubbleOverflow.update(); mBubbleContainer.reorderView(mBubbleOverflow.getIconView(), @@ -2199,6 +2210,11 @@ public class BubbleStackView extends FrameLayout } } + void onSensitiveNotificationProtectionStateChanged( + boolean sensitiveNotificationProtectionActive) { + mSensitiveNotificationProtectionActive = sensitiveNotificationProtectionActive; + } + /** * Asks the BubbleController to hide the IME from anywhere, whether it's focused on Bubbles or * not. @@ -2842,6 +2858,7 @@ public class BubbleStackView extends FrameLayout || isExpanded() || mIsExpansionAnimating || mIsGestureInProgress + || mSensitiveNotificationProtectionActive || mBubbleToExpandAfterFlyoutCollapse != null || bubbleView == null) { if (bubbleView != null && mFlyout.getVisibility() != VISIBLE) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 28af0ca6ac6c..26077cf7057b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -286,6 +286,16 @@ public interface Bubbles { void onUserRemoved(int removedUserId); /** + * Called when the Sensitive notification protection state has changed, such as when media + * projection starts and stops. + * + * @param sensitiveNotificationProtectionActive {@code true} if notifications should be + * protected + */ + void onSensitiveNotificationProtectionStateChanged( + boolean sensitiveNotificationProtectionActive); + + /** * A listener to be notified of bubble state changes, used by launcher to render bubbles in * its process. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS index 8271014d290e..08c70314973e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS @@ -1,2 +1,6 @@ # WM shell sub-module bubble owner madym@google.com +atsjenk@google.com +liranb@google.com +sukeshram@google.com +mpodolian@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java index 1959eb03a6b3..86cec02ab138 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java @@ -22,12 +22,7 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.os.Process.SYSTEM_UID; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; -import static android.util.RotationUtils.rotateBounds; -import static android.util.RotationUtils.rotateInsets; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; -import static android.view.Surface.ROTATION_0; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; import android.annotation.IntDef; import android.annotation.NonNull; @@ -40,11 +35,9 @@ import android.graphics.Rect; import android.os.SystemProperties; import android.provider.Settings; import android.util.DisplayMetrics; -import android.util.Size; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayInfo; -import android.view.Gravity; import android.view.InsetsState; import android.view.Surface; import android.view.WindowInsets; @@ -226,25 +219,22 @@ public class DisplayLayout { /** * Apply a rotation to this layout and its parameters. - * @param res - * @param targetRotation */ - public void rotateTo(Resources res, @Surface.Rotation int targetRotation) { - final int rotationDelta = (targetRotation - mRotation + 4) % 4; - final boolean changeOrient = (rotationDelta % 2) != 0; - + public void rotateTo(Resources res, @Surface.Rotation int toRotation) { final int origWidth = mWidth; final int origHeight = mHeight; + final int fromRotation = mRotation; + final int rotationDelta = (toRotation - fromRotation + 4) % 4; + final boolean changeOrient = (rotationDelta % 2) != 0; - mRotation = targetRotation; + mRotation = toRotation; if (changeOrient) { mWidth = origHeight; mHeight = origWidth; } - if (mCutout != null && !mCutout.isEmpty()) { - mCutout = calculateDisplayCutoutForRotation(mCutout, rotationDelta, origWidth, - origHeight); + if (mCutout != null) { + mCutout = mCutout.getRotated(origWidth, origHeight, fromRotation, toRotation); } recalcInsets(res); @@ -398,96 +388,6 @@ public class DisplayLayout { } } - /** Calculate the DisplayCutout for a particular display size/rotation. */ - public static DisplayCutout calculateDisplayCutoutForRotation( - DisplayCutout cutout, int rotation, int displayWidth, int displayHeight) { - if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) { - return null; - } - if (rotation == ROTATION_0) { - return computeSafeInsets(cutout, displayWidth, displayHeight); - } - final Insets waterfallInsets = rotateInsets(cutout.getWaterfallInsets(), rotation); - final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); - Rect[] cutoutRects = cutout.getBoundingRectsAll(); - final Rect[] newBounds = new Rect[cutoutRects.length]; - final Rect displayBounds = new Rect(0, 0, displayWidth, displayHeight); - for (int i = 0; i < cutoutRects.length; ++i) { - final Rect rect = new Rect(cutoutRects[i]); - if (!rect.isEmpty()) { - rotateBounds(rect, displayBounds, rotation); - } - newBounds[getBoundIndexFromRotation(i, rotation)] = rect; - } - final DisplayCutout.CutoutPathParserInfo info = cutout.getCutoutPathParserInfo(); - final DisplayCutout.CutoutPathParserInfo newInfo = new DisplayCutout.CutoutPathParserInfo( - info.getDisplayWidth(), info.getDisplayHeight(), info.getPhysicalDisplayWidth(), - info.getPhysicalDisplayHeight(), info.getDensity(), info.getCutoutSpec(), rotation, - info.getScale(), info.getPhysicalPixelDisplaySizeRatio()); - return computeSafeInsets( - DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo), - rotated ? displayHeight : displayWidth, - rotated ? displayWidth : displayHeight); - } - - private static int getBoundIndexFromRotation(int index, int rotation) { - return (index - rotation) < 0 - ? index - rotation + DisplayCutout.BOUNDS_POSITION_LENGTH - : index - rotation; - } - - /** Calculate safe insets. */ - public static DisplayCutout computeSafeInsets(DisplayCutout inner, - int displayWidth, int displayHeight) { - if (inner == DisplayCutout.NO_CUTOUT) { - return null; - } - - final Size displaySize = new Size(displayWidth, displayHeight); - final Rect safeInsets = computeSafeInsets(displaySize, inner); - return inner.replaceSafeInsets(safeInsets); - } - - private static Rect computeSafeInsets( - Size displaySize, DisplayCutout cutout) { - if (displaySize.getWidth() == displaySize.getHeight()) { - throw new UnsupportedOperationException("not implemented: display=" + displaySize - + " cutout=" + cutout); - } - - int leftInset = Math.max(cutout.getWaterfallInsets().left, - findCutoutInsetForSide(displaySize, cutout.getBoundingRectLeft(), Gravity.LEFT)); - int topInset = Math.max(cutout.getWaterfallInsets().top, - findCutoutInsetForSide(displaySize, cutout.getBoundingRectTop(), Gravity.TOP)); - int rightInset = Math.max(cutout.getWaterfallInsets().right, - findCutoutInsetForSide(displaySize, cutout.getBoundingRectRight(), Gravity.RIGHT)); - int bottomInset = Math.max(cutout.getWaterfallInsets().bottom, - findCutoutInsetForSide(displaySize, cutout.getBoundingRectBottom(), - Gravity.BOTTOM)); - - return new Rect(leftInset, topInset, rightInset, bottomInset); - } - - private static int findCutoutInsetForSide(Size display, Rect boundingRect, int gravity) { - if (boundingRect.isEmpty()) { - return 0; - } - - int inset = 0; - switch (gravity) { - case Gravity.TOP: - return Math.max(inset, boundingRect.bottom); - case Gravity.BOTTOM: - return Math.max(inset, display.getHeight() - boundingRect.top); - case Gravity.LEFT: - return Math.max(inset, boundingRect.right); - case Gravity.RIGHT: - return Math.max(inset, display.getWidth() - boundingRect.left); - default: - throw new IllegalArgumentException("unknown gravity: " + gravity); - } - } - static boolean hasNavigationBar(DisplayInfo info, Context context, int displayId) { if (displayId == Display.DEFAULT_DISPLAY) { // Allow a system property to override this. Used by the emulator. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java index b57e2d2c6ac2..b87c2f6ebad5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java @@ -228,6 +228,14 @@ public class PipBoundsState { mExpandedMovementBounds.set(bounds); } + /** Updates the min and max sizes based on the size spec and aspect ratio. */ + public void updateMinMaxSize(float aspectRatio) { + final Size minSize = mSizeSpecSource.getMinSize(aspectRatio); + mMinSize.set(minSize.getWidth(), minSize.getHeight()); + final Size maxSize = mSizeSpecSource.getMaxSize(aspectRatio); + mMaxSize.set(maxSize.getWidth(), maxSize.getHeight()); + } + /** Sets the max possible size for resize. */ public void setMaxSize(int width, int height) { mMaxSize.set(width, height); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt new file mode 100644 index 000000000000..95d47146e834 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.desktopmode + +import com.android.internal.util.FrameworkStatsLog +import com.android.wm.shell.protolog.ShellProtoLogGroup +import com.android.wm.shell.util.KtProtoLog + +/** + * Event logger for logging desktop mode session events + */ +class DesktopModeEventLogger { + /** + * Logs the enter of desktop mode having session id [sessionId] and the reason [enterReason] for + * entering desktop mode + */ + fun logSessionEnter(sessionId: Int, enterReason: EnterReason) { + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging session enter, session: %s reason: %s", + sessionId, enterReason.name + ) + FrameworkStatsLog.write(DESKTOP_MODE_ATOM_ID, + /* event */ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__ENTER, + /* enterReason */ enterReason.reason, + /* exitReason */ 0, + /* session_id */ sessionId) + } + + /** + * Logs the exit of desktop mode having session id [sessionId] and the reason [exitReason] for + * exiting desktop mode + */ + fun logSessionExit(sessionId: Int, exitReason: ExitReason) { + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging session exit, session: %s reason: %s", + sessionId, exitReason.name + ) + FrameworkStatsLog.write(DESKTOP_MODE_ATOM_ID, + /* event */ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__EXIT, + /* enterReason */ 0, + /* exitReason */ exitReason.reason, + /* session_id */ sessionId) + } + + /** + * Logs that the task with update [taskUpdate] was added in the desktop mode session having + * session id [sessionId] + */ + fun logTaskAdded(sessionId: Int, taskUpdate: TaskUpdate) { + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging task added, session: %s taskId: %s", + sessionId, taskUpdate.instanceId + ) + FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID, + /* task_event */ + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED, + /* instance_id */ + taskUpdate.instanceId, + /* uid */ + taskUpdate.uid, + /* task_height */ + taskUpdate.taskHeight, + /* task_width */ + taskUpdate.taskWidth, + /* task_x */ + taskUpdate.taskX, + /* task_y */ + taskUpdate.taskY, + /* session_id */ + sessionId) + } + + /** + * Logs that the task with update [taskUpdate] was removed in the desktop mode session having + * session id [sessionId] + */ + fun logTaskRemoved(sessionId: Int, taskUpdate: TaskUpdate) { + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging task remove, session: %s taskId: %s", + sessionId, taskUpdate.instanceId + ) + FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID, + /* task_event */ + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED, + /* instance_id */ + taskUpdate.instanceId, + /* uid */ + taskUpdate.uid, + /* task_height */ + taskUpdate.taskHeight, + /* task_width */ + taskUpdate.taskWidth, + /* task_x */ + taskUpdate.taskX, + /* task_y */ + taskUpdate.taskY, + /* session_id */ + sessionId) + } + + /** + * Logs that the task with update [taskUpdate] had it's info changed in the desktop mode session + * having session id [sessionId] + */ + fun logTaskInfoChanged(sessionId: Int, taskUpdate: TaskUpdate) { + KtProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging task info changed, session: %s taskId: %s", + sessionId, taskUpdate.instanceId + ) + FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID, + /* task_event */ + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED, + /* instance_id */ + taskUpdate.instanceId, + /* uid */ + taskUpdate.uid, + /* task_height */ + taskUpdate.taskHeight, + /* task_width */ + taskUpdate.taskWidth, + /* task_x */ + taskUpdate.taskX, + /* task_y */ + taskUpdate.taskY, + /* session_id */ + sessionId) + } + + companion object { + data class TaskUpdate( + val instanceId: Int, + val uid: Int, + val taskHeight: Int = Int.MIN_VALUE, + val taskWidth: Int = Int.MIN_VALUE, + val taskX: Int = Int.MIN_VALUE, + val taskY: Int = Int.MIN_VALUE, + ) + + /** + * Enum EnterReason mapped to the EnterReason definition in + * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto + */ + enum class EnterReason(val reason: Int) { + UNKNOWN_ENTER( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__UNKNOWN_ENTER + ), + OVERVIEW( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__OVERVIEW + ), + APP_HANDLE_DRAG( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_HANDLE_DRAG + ), + APP_HANDLE_MENU_BUTTON( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_HANDLE_MENU_BUTTON + ), + APP_FREEFORM_INTENT( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_FREEFORM_INTENT + ), + KEYBOARD_SHORTCUT_ENTER( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__KEYBOARD_SHORTCUT_ENTER + ), + SCREEN_ON( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__SCREEN_ON + ); + } + + /** + * Enum ExitReason mapped to the ExitReason definition in + * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto + */ + enum class ExitReason(val reason: Int) { + UNKNOWN_EXIT( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__UNKNOWN_EXIT + ), + DRAG_TO_EXIT( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__DRAG_TO_EXIT + ), + APP_HANDLE_MENU_BUTTON_EXIT( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__APP_HANDLE_MENU_BUTTON_EXIT + ), + KEYBOARD_SHORTCUT_EXIT( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__KEYBOARD_SHORTCUT_EXIT + ), + RETURN_HOME_OR_OVERVIEW( + FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME + ), + TASK_FINISHED( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__TASK_FINISHED + ), + SCREEN_OFF( + FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF + ) + } + + private const val DESKTOP_MODE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED + private const val DESKTOP_MODE_TASK_UPDATE_ATOM_ID = + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java index 405341803a46..7091c4b7210a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java @@ -22,8 +22,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; -import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FINAL_FREEFORM_SCALE; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.RectEvaluator; @@ -389,7 +387,8 @@ public class DesktopModeVisualIndicator { layout.width() - padding, layout.height() - padding); case TO_DESKTOP_INDICATOR: - final float adjustmentPercentage = 1f - FINAL_FREEFORM_SCALE; + final float adjustmentPercentage = 1f + - DesktopTasksController.DESKTOP_MODE_INITIAL_BOUNDS_SCALE; return new Rect((int) (adjustmentPercentage * layout.width() / 2), (int) (adjustmentPercentage * layout.height() / 2), (int) (layout.width() - (adjustmentPercentage * layout.width() / 2)), diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 98f9988eaabb..dcffb2d3e8fa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.desktopmode -import android.app.ActivityManager import android.app.ActivityManager.RunningTaskInfo import android.app.ActivityOptions import android.app.PendingIntent @@ -35,7 +34,6 @@ import android.graphics.Rect import android.graphics.Region import android.os.IBinder import android.os.SystemProperties -import android.util.DisplayMetrics.DENSITY_DEFAULT import android.view.Display.DEFAULT_DISPLAY import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE @@ -51,6 +49,7 @@ import com.android.internal.policy.ScreenDecorationsUtils import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.ExecutorUtils import com.android.wm.shell.common.ExternalInterfaceBinder import com.android.wm.shell.common.LaunchAdjacentController @@ -68,7 +67,6 @@ import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksLi import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE -import com.android.wm.shell.recents.RecentTasksController import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.splitscreen.SplitScreenController @@ -85,7 +83,6 @@ import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import java.io.PrintWriter import java.util.concurrent.Executor import java.util.function.Consumer -import java.util.function.Function /** Handles moving tasks in and out of desktop */ class DesktopTasksController( @@ -551,11 +548,7 @@ class DesktopTasksController( if (taskInfo.configuration.windowConfiguration.bounds == stableBounds) { // The desktop task is currently occupying the whole stable bounds, toggle to the // default bounds. - getDefaultDesktopTaskBounds( - density = taskInfo.configuration.densityDpi.toFloat() / DENSITY_DEFAULT, - stableBounds = stableBounds, - outBounds = destinationBounds - ) + getDefaultDesktopTaskBounds(displayLayout, destinationBounds) } else { // Toggle to the stable bounds. destinationBounds.set(stableBounds) @@ -610,15 +603,17 @@ class DesktopTasksController( } } - private fun getDefaultDesktopTaskBounds(density: Float, stableBounds: Rect, outBounds: Rect) { - val width = (DESKTOP_MODE_DEFAULT_WIDTH_DP * density + 0.5f).toInt() - val height = (DESKTOP_MODE_DEFAULT_HEIGHT_DP * density + 0.5f).toInt() - outBounds.set(0, 0, width, height) - // Center the task in stable bounds + private fun getDefaultDesktopTaskBounds(displayLayout: DisplayLayout, outBounds: Rect) { + // TODO(b/319819547): Account for app constraints so apps do not become letterboxed + val screenBounds = Rect(0, 0, displayLayout.width(), displayLayout.height()) + // Update width and height with default desktop mode values + val desiredWidth = screenBounds.width().times(DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt() + val desiredHeight = screenBounds.height().times(DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt() + outBounds.set(0, 0, desiredWidth, desiredHeight) + // Center the task in screen bounds outBounds.offset( - stableBounds.centerX() - outBounds.centerX(), - stableBounds.centerY() - outBounds.centerY() - ) + screenBounds.centerX() - outBounds.centerX(), + screenBounds.centerY() - outBounds.centerY()) } /** @@ -1233,13 +1228,9 @@ class DesktopTasksController( SystemProperties.getInt("persist.wm.debug.desktop_mode_density", 284) private val DESKTOP_DENSITY_ALLOWED_RANGE = (100..1000) - // Override default freeform task width when desktop mode is enabled. In dips. - private val DESKTOP_MODE_DEFAULT_WIDTH_DP = - SystemProperties.getInt("persist.wm.debug.desktop_mode.default_width", 840) - - // Override default freeform task height when desktop mode is enabled. In dips. - private val DESKTOP_MODE_DEFAULT_HEIGHT_DP = - SystemProperties.getInt("persist.wm.debug.desktop_mode.default_height", 630) + @JvmField + val DESKTOP_MODE_INITIAL_BOUNDS_SCALE = SystemProperties + .getInt("persist.wm.debug.freeform_initial_bounds_scale", 75) / 100f /** * Check if desktop density override is enabled diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java index 07cf202ddfac..79bb5408df82 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java @@ -54,8 +54,6 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition private final Transitions mTransitions; private final Supplier<SurfaceControl.Transaction> mTransactionSupplier; - // The size of the screen after drag relative to the fullscreen size - public static final float FINAL_FREEFORM_SCALE = 0.6f; public static final int FREEFORM_ANIMATION_DURATION = 336; private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); 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 ef32f6f5dbe1..c7daf561f682 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 @@ -1996,6 +1996,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, pw.println(innerPrefix + "mToken=" + mToken + " binder=" + (mToken != null ? mToken.asBinder() : null)); pw.println(innerPrefix + "mLeash=" + mLeash); + pw.println(innerPrefix + "mPipOverlay=" + mPipOverlay); pw.println(innerPrefix + "mState=" + mPipTransitionState.getTransitionState()); pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams); mPipTransitionController.dump(pw, innerPrefix); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index e018ecc0f7e3..6a1a62ea30a1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -1037,6 +1037,7 @@ public class PipTransition extends PipTransitionController { private void computeEnterPipRotatedBounds(int rotationDelta, int startRotation, int endRotation, TaskInfo taskInfo, Rect outDestinationBounds, @Nullable Rect outSourceHintRect) { mPipDisplayLayoutState.rotateTo(endRotation); + mPipBoundsState.updateMinMaxSize(mPipBoundsState.getAspectRatio()); final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds(); outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds()); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 46840773cfc6..2cdec81d77ac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -976,8 +976,16 @@ public class PipController implements PipTransitionController.PipTransitionCallb mPipBoundsState.addNamedUnrestrictedKeepClearArea(LAUNCHER_KEEP_CLEAR_AREA_TAG, hotseatKeepClearArea); onDisplayRotationChangedNotInPip(mContext, launcherRotation); + // cache current min/max size + Point minSize = mPipBoundsState.getMinSize(); + Point maxSize = mPipBoundsState.getMaxSize(); + mPipBoundsState.updateMinMaxSize(pictureInPictureParams.getAspectRatioFloat()); final Rect entryBounds = mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo, pictureInPictureParams); + // restore min/max size, as this is referenced later in OnDisplayChangingListener and needs + // to reflect the pre-rotation state for it to work + mPipBoundsState.setMinSize(minSize.x, minSize.y); + mPipBoundsState.setMaxSize(maxSize.x, maxSize.y); // sync mPipBoundsState with the newly calculated bounds. mPipBoundsState.setNormalBounds(entryBounds); return entryBounds; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index e7dd31cc1fa9..c1adfffce074 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -467,17 +467,11 @@ public class PipTouchHandler { } private void updatePinchResizeSizeConstraints(float aspectRatio) { - final int minWidth, minHeight, maxWidth, maxHeight; - - minWidth = mSizeSpecSource.getMinSize(aspectRatio).getWidth(); - minHeight = mSizeSpecSource.getMinSize(aspectRatio).getHeight(); - maxWidth = mSizeSpecSource.getMaxSize(aspectRatio).getWidth(); - maxHeight = mSizeSpecSource.getMaxSize(aspectRatio).getHeight(); - - mPipResizeGestureHandler.updateMinSize(minWidth, minHeight); - mPipResizeGestureHandler.updateMaxSize(maxWidth, maxHeight); - mPipBoundsState.setMaxSize(maxWidth, maxHeight); - mPipBoundsState.setMinSize(minWidth, minHeight); + mPipBoundsState.updateMinMaxSize(aspectRatio); + mPipResizeGestureHandler.updateMinSize(mPipBoundsState.getMinSize().x, + mPipBoundsState.getMinSize().y); + mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getMaxSize().x, + mPipBoundsState.getMaxSize().y); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java deleted file mode 100644 index 93ffb3dc8115..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.protolog; - -import android.annotation.Nullable; - -import com.android.internal.protolog.BaseProtoLogImpl; -import com.android.internal.protolog.ProtoLogViewerConfigReader; -import com.android.internal.protolog.common.IProtoLogGroup; - -import java.io.File; -import java.io.PrintWriter; - - -/** - * A service for the ProtoLog logging system. - */ -public class ShellProtoLogImpl extends BaseProtoLogImpl { - private static final String TAG = "ProtoLogImpl"; - private static final int BUFFER_CAPACITY = 1024 * 1024; - // TODO: find a proper location to save the protolog message file - private static final String LOG_FILENAME = "/data/misc/wmtrace/shell_log.winscope"; - private static final String VIEWER_CONFIG_FILENAME = "/system_ext/etc/wmshell.protolog.json.gz"; - - private static ShellProtoLogImpl sServiceInstance = null; - - static { - addLogGroupEnum(ShellProtoLogGroup.values()); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void d(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance() - .log(LogLevel.DEBUG, group, messageHash, paramsMask, messageString, args); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void v(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance().log(LogLevel.VERBOSE, group, messageHash, paramsMask, messageString, - args); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void i(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance().log(LogLevel.INFO, group, messageHash, paramsMask, messageString, args); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void w(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance().log(LogLevel.WARN, group, messageHash, paramsMask, messageString, args); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void e(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance() - .log(LogLevel.ERROR, group, messageHash, paramsMask, messageString, args); - } - - /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */ - public static void wtf(IProtoLogGroup group, int messageHash, int paramsMask, - @Nullable String messageString, - Object... args) { - getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args); - } - - /** Returns true iff logging is enabled for the given {@code IProtoLogGroup}. */ - public static boolean isEnabled(IProtoLogGroup group) { - return group.isLogToLogcat() - || (group.isLogToProto() && getSingleInstance().isProtoEnabled()); - } - - /** - * Returns the single instance of the ProtoLogImpl singleton class. - */ - public static synchronized ShellProtoLogImpl getSingleInstance() { - if (sServiceInstance == null) { - sServiceInstance = new ShellProtoLogImpl(); - } - return sServiceInstance; - } - - public int startTextLogging(String[] groups, PrintWriter pw) { - mViewerConfig.loadViewerConfig(pw, VIEWER_CONFIG_FILENAME); - return setLogging(true /* setTextLogging */, true, pw, groups); - } - - public int stopTextLogging(String[] groups, PrintWriter pw) { - return setLogging(true /* setTextLogging */, false, pw, groups); - } - - private ShellProtoLogImpl() { - super(new File(LOG_FILENAME), VIEWER_CONFIG_FILENAME, BUFFER_CAPACITY, - new ProtoLogViewerConfigReader()); - } -} - 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 fa14b4c64fe0..2933cf48614a 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 @@ -3396,6 +3396,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final int stageType = isMainStage ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(stageType, wct); + clearSplitPairedInRecents(EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW); mSplitTransitions.startDismissTransition(wct, StageCoordinator.this, stageType, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW); Log.w(TAG, splitFailureMessage("onNoLongerSupportMultiWindow", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt index 9b48a542720c..7a50814f0275 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.util import android.util.Log import com.android.internal.protolog.common.IProtoLogGroup -import com.android.wm.shell.protolog.ShellProtoLogImpl +import com.android.internal.protolog.common.ProtoLog /** * Log messages using an API similar to [com.android.internal.protolog.common.ProtoLog]. Useful for @@ -31,42 +31,42 @@ class KtProtoLog { companion object { /** @see [com.android.internal.protolog.common.ProtoLog.d] */ fun d(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.d(group.tag, String.format(messageString, *args)) } } /** @see [com.android.internal.protolog.common.ProtoLog.v] */ fun v(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.v(group.tag, String.format(messageString, *args)) } } /** @see [com.android.internal.protolog.common.ProtoLog.i] */ fun i(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.i(group.tag, String.format(messageString, *args)) } } /** @see [com.android.internal.protolog.common.ProtoLog.w] */ fun w(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.w(group.tag, String.format(messageString, *args)) } } /** @see [com.android.internal.protolog.common.ProtoLog.e] */ fun e(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.e(group.tag, String.format(messageString, *args)) } } /** @see [com.android.internal.protolog.common.ProtoLog.wtf] */ fun wtf(group: IProtoLogGroup, messageString: String, vararg args: Any) { - if (ShellProtoLogImpl.isEnabled(group)) { + if (ProtoLog.isEnabled(group)) { Log.wtf(group.tag, String.format(messageString, *args)) } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index a2d962d065c8..c1406d052195 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -21,11 +21,13 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.view.InputDevice.SOURCE_TOUCHSCREEN; +import static android.view.MotionEvent.ACTION_HOVER_ENTER; +import static android.view.MotionEvent.ACTION_HOVER_EXIT; import static android.view.WindowInsets.Type.statusBars; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FINAL_FREEFORM_SCALE; import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION; import static com.android.wm.shell.windowdecor.MoveToDesktopAnimator.DRAG_FREEFORM_SCALE; @@ -310,8 +312,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener, - DragDetector.MotionEventHandler { - + View.OnGenericMotionListener , DragDetector.MotionEventHandler { + private static final int CLOSE_MAXIMIZE_MENU_DELAY_MS = 150; private final int mTaskId; private final WindowContainerToken mTaskToken; private final DragPositioningCallback mDragPositioningCallback; @@ -322,6 +324,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private boolean mHasLongClicked; private boolean mShouldClick; private int mDragPointerId = -1; + private final Runnable mCloseMaximizeWindowRunnable; private DesktopModeTouchEventListener( RunningTaskInfo taskInfo, @@ -331,6 +334,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDragPositioningCallback = dragPositioningCallback; mDragDetector = new DragDetector(this); mGestureDetector = new GestureDetector(mContext, this); + mCloseMaximizeWindowRunnable = () -> { + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); + if (decoration == null) return; + decoration.closeMaximizeMenu(); + }; } @Override @@ -386,13 +394,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDesktopTasksController.ifPresent(c -> c.moveToNextDisplay(mTaskId)); } } else if (id == R.id.maximize_window) { - if (decoration.isMaximizeMenuActive()) { - decoration.closeMaximizeMenu(); - return; - } final RunningTaskInfo taskInfo = decoration.mTaskInfo; - mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(taskInfo)); decoration.closeHandleMenu(); + decoration.closeMaximizeMenu(); + mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(taskInfo)); } else if (id == R.id.maximize_menu_maximize_button) { final RunningTaskInfo taskInfo = decoration.mTaskInfo; mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(taskInfo)); @@ -429,8 +434,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } final long eventDuration = e.getEventTime() - e.getDownTime(); - final boolean shouldLongClick = id == R.id.maximize_window && !mIsDragging - && !mHasLongClicked && eventDuration >= ViewConfiguration.getLongPressTimeout(); + final boolean isTouchScreen = + (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; + final boolean shouldLongClick = isTouchScreen && id == R.id.maximize_window + && !mIsDragging && !mHasLongClicked + && eventDuration >= ViewConfiguration.getLongPressTimeout(); if (shouldLongClick) { v.performLongClick(); mHasLongClicked = true; @@ -456,6 +464,36 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return false; } + @Override + public boolean onGenericMotion(View v, MotionEvent ev) { + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); + final int id = v.getId(); + if (ev.getAction() == ACTION_HOVER_ENTER) { + if (!decoration.isMaximizeMenuActive() && id == R.id.maximize_window) { + decoration.onMaximizeWindowHoverEnter(); + } else if (id == R.id.maximize_window + || MaximizeMenu.Companion.isMaximizeMenuView(id)) { + // Re-hovering over any of the maximize menu views should keep the menu open by + // cancelling any attempts to close the menu. + mMainHandler.removeCallbacks(mCloseMaximizeWindowRunnable); + } + return true; + } else if (ev.getAction() == ACTION_HOVER_EXIT) { + if (!decoration.isMaximizeMenuActive() && id == R.id.maximize_window) { + decoration.onMaximizeWindowHoverExit(); + } else if (id == R.id.maximize_window + || MaximizeMenu.Companion.isMaximizeMenuView(id)) { + // Close menu if not hovering over maximize menu or maximize button after a + // delay to give user a chance to re-enter view or to move from one maximize + // menu view to another. + mMainHandler.postDelayed(mCloseMaximizeWindowRunnable, + CLOSE_MAXIMIZE_MENU_DELAY_MS); + } + return true; + } + return false; + } + private void moveTaskToFront(RunningTaskInfo taskInfo) { if (!taskInfo.isFocused) { mDesktopTasksController.ifPresent(c -> c.moveTaskToFront(taskInfo)); @@ -785,16 +823,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { * @param scale the amount to scale to relative to the Screen Bounds */ private Rect calculateFreeformBounds(int displayId, float scale) { + // TODO(b/319819547): Account for app constraints so apps do not become letterboxed final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId); final int screenWidth = displayLayout.width(); final int screenHeight = displayLayout.height(); final float adjustmentPercentage = (1f - scale) / 2; - final Rect endBounds = new Rect((int) (screenWidth * adjustmentPercentage), + return new Rect((int) (screenWidth * adjustmentPercentage), (int) (screenHeight * adjustmentPercentage), (int) (screenWidth * (adjustmentPercentage + scale)), (int) (screenHeight * (adjustmentPercentage + scale))); - return endBounds; } /** @@ -836,7 +874,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { c -> { c.onDragPositioningEndThroughStatusBar(relevantDecor.mTaskInfo, calculateFreeformBounds(ev.getDisplayId(), - FINAL_FREEFORM_SCALE)); + DesktopTasksController + .DESKTOP_MODE_INITIAL_BOUNDS_SCALE)); }); } }); @@ -986,7 +1025,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { new DesktopModeTouchEventListener(taskInfo, dragPositioningCallback); windowDecoration.setCaptionListeners( - touchEventListener, touchEventListener, touchEventListener); + touchEventListener, touchEventListener, touchEventListener, touchEventListener); windowDecoration.setExclusionRegionListener(mExclusionRegionListener); windowDecoration.setDragPositioningCallback(dragPositioningCallback); windowDecoration.setDragDetector(touchEventListener.mDragDetector); @@ -1032,6 +1071,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } decoration.showResizeVeil(t, bounds); + decoration.setAnimatingTaskResize(true); } @Override @@ -1046,6 +1086,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); if (decoration == null) return; decoration.hideResizeVeil(); + decoration.setAnimatingTaskResize(false); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 185365b2a501..74f460bf1226 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -60,6 +60,8 @@ import com.android.wm.shell.windowdecor.viewholder.DesktopModeAppControlsWindowD import com.android.wm.shell.windowdecor.viewholder.DesktopModeFocusedWindowDecorationViewHolder; import com.android.wm.shell.windowdecor.viewholder.DesktopModeWindowDecorationViewHolder; +import kotlin.Unit; + import java.util.function.Supplier; /** @@ -79,6 +81,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private View.OnClickListener mOnCaptionButtonClickListener; private View.OnTouchListener mOnCaptionTouchListener; private View.OnLongClickListener mOnCaptionLongClickListener; + private View.OnGenericMotionListener mOnCaptionGenericMotionListener; private DragPositioningCallback mDragPositioningCallback; private DragResizeInputListener mDragResizeListener; private DragDetector mDragDetector; @@ -152,10 +155,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void setCaptionListeners( View.OnClickListener onCaptionButtonClickListener, View.OnTouchListener onCaptionTouchListener, - View.OnLongClickListener onLongClickListener) { + View.OnLongClickListener onLongClickListener, + View.OnGenericMotionListener onGenericMotionListener) { mOnCaptionButtonClickListener = onCaptionButtonClickListener; mOnCaptionTouchListener = onCaptionTouchListener; mOnCaptionLongClickListener = onLongClickListener; + mOnCaptionGenericMotionListener = onGenericMotionListener; } void setExclusionRegionListener(ExclusionRegionListener exclusionRegionListener) { @@ -225,9 +230,15 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mOnCaptionTouchListener, mOnCaptionButtonClickListener, mOnCaptionLongClickListener, + mOnCaptionGenericMotionListener, mAppName, - mAppIconBitmap - ); + mAppIconBitmap, + () -> { + if (!isMaximizeMenuActive()) { + createMaximizeMenu(); + } + return Unit.INSTANCE; + }); } else { throw new IllegalArgumentException("Unexpected layout resource id"); } @@ -548,7 +559,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin */ void createMaximizeMenu() { mMaximizeMenu = new MaximizeMenu(mSyncQueue, mRootTaskDisplayAreaOrganizer, - mDisplayController, mTaskInfo, mOnCaptionButtonClickListener, mContext, + mDisplayController, mTaskInfo, mOnCaptionButtonClickListener, + mOnCaptionGenericMotionListener, mOnCaptionTouchListener, mContext, calculateMaximizeMenuPosition(), mSurfaceControlTransactionSupplier); mMaximizeMenu.show(); } @@ -776,6 +788,22 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin return R.id.desktop_mode_caption; } + void setAnimatingTaskResize(boolean animatingTaskResize) { + if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_focused_window_decor) return; + ((DesktopModeAppControlsWindowDecorationViewHolder) mWindowDecorViewHolder) + .setAnimatingTaskResize(animatingTaskResize); + } + + void onMaximizeWindowHoverExit() { + ((DesktopModeAppControlsWindowDecorationViewHolder) mWindowDecorViewHolder) + .onMaximizeWindowHoverExit(); + } + + void onMaximizeWindowHoverEnter() { + ((DesktopModeAppControlsWindowDecorationViewHolder) mWindowDecorViewHolder) + .onMaximizeWindowHoverEnter(); + } + @Override public String toString() { return "{" diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt new file mode 100644 index 000000000000..b2f8cfdbfb7a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.wm.shell.windowdecor + +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.content.Context +import android.content.res.ColorStateList +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.FrameLayout +import android.widget.ImageButton +import android.widget.ProgressBar +import androidx.core.animation.doOnEnd +import androidx.core.animation.doOnStart +import androidx.core.content.ContextCompat +import com.android.wm.shell.R + +private const val OPEN_MAXIMIZE_MENU_DELAY_ON_HOVER_MS = 350 +private const val MAX_DRAWABLE_ALPHA = 255 + +class MaximizeButtonView( + context: Context, + attrs: AttributeSet +) : FrameLayout(context, attrs) { + lateinit var onHoverAnimationFinishedListener: () -> Unit + private val hoverProgressAnimatorSet = AnimatorSet() + var hoverDisabled = false + + private val progressBar: ProgressBar + private val maximizeWindow: ImageButton + + init { + LayoutInflater.from(context).inflate(R.layout.maximize_menu_button, this, true) + + progressBar = requireViewById(R.id.progress_bar) + maximizeWindow = requireViewById(R.id.maximize_window) + } + + fun startHoverAnimation() { + if (hoverDisabled) return + if (hoverProgressAnimatorSet.isRunning) { + cancelHoverAnimation() + } + + maximizeWindow.background.alpha = 0 + + hoverProgressAnimatorSet.playSequentially( + ValueAnimator.ofInt(0, MAX_DRAWABLE_ALPHA) + .setDuration(50) + .apply { + addUpdateListener { + maximizeWindow.background.alpha = animatedValue as Int + } + }, + ObjectAnimator.ofInt(progressBar, "progress", 100) + .setDuration(OPEN_MAXIMIZE_MENU_DELAY_ON_HOVER_MS.toLong()) + .apply { + doOnStart { + progressBar.setProgress(0, false) + progressBar.visibility = View.VISIBLE + } + doOnEnd { + progressBar.visibility = View.INVISIBLE + onHoverAnimationFinishedListener() + } + } + ) + hoverProgressAnimatorSet.start() + } + + fun cancelHoverAnimation() { + hoverProgressAnimatorSet.removeAllListeners() + hoverProgressAnimatorSet.cancel() + progressBar.visibility = View.INVISIBLE + } + + fun setAnimationTints(darkMode: Boolean) { + if (darkMode) { + progressBar.progressTintList = ColorStateList.valueOf( + resources.getColor(R.color.desktop_mode_maximize_menu_progress_dark)) + maximizeWindow.background?.setTintList(ContextCompat.getColorStateList(context, + R.color.desktop_mode_caption_button_color_selector_dark)) + } else { + progressBar.progressTintList = ColorStateList.valueOf( + resources.getColor(R.color.desktop_mode_maximize_menu_progress_light)) + maximizeWindow.background?.setTintList(ContextCompat.getColorStateList(context, + R.color.desktop_mode_caption_button_color_selector_light)) + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt index 794b357c9f16..b82f7ca47ef3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.windowdecor +import android.annotation.IdRes import android.app.ActivityManager.RunningTaskInfo import android.content.Context import android.content.res.Resources @@ -27,6 +28,8 @@ import android.view.SurfaceControl import android.view.SurfaceControl.Transaction import android.view.SurfaceControlViewHost import android.view.View.OnClickListener +import android.view.View.OnGenericMotionListener +import android.view.View.OnTouchListener import android.view.WindowManager import android.view.WindowlessWindowManager import android.widget.Button @@ -49,6 +52,8 @@ class MaximizeMenu( private val displayController: DisplayController, private val taskInfo: RunningTaskInfo, private val onClickListener: OnClickListener, + private val onGenericMotionListener: OnGenericMotionListener, + private val onTouchListener: OnTouchListener, private val decorWindowContext: Context, private val menuPosition: PointF, private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() } @@ -142,15 +147,26 @@ class MaximizeMenu( private fun setupMaximizeMenu() { val maximizeMenuView = maximizeMenu?.mWindowViewHost?.view ?: return - maximizeMenuView.requireViewById<Button>( + maximizeMenuView.setOnGenericMotionListener(onGenericMotionListener) + maximizeMenuView.setOnTouchListener(onTouchListener) + + val maximizeButton = maximizeMenuView.requireViewById<Button>( R.id.maximize_menu_maximize_button - ).setOnClickListener(onClickListener) - maximizeMenuView.requireViewById<Button>( + ) + maximizeButton.setOnClickListener(onClickListener) + maximizeButton.setOnGenericMotionListener(onGenericMotionListener) + + val snapRightButton = maximizeMenuView.requireViewById<Button>( R.id.maximize_menu_snap_right_button - ).setOnClickListener(onClickListener) - maximizeMenuView.requireViewById<Button>( + ) + snapRightButton.setOnClickListener(onClickListener) + snapRightButton.setOnGenericMotionListener(onGenericMotionListener) + + val snapLeftButton = maximizeMenuView.requireViewById<Button>( R.id.maximize_menu_snap_left_button - ).setOnClickListener(onClickListener) + ) + snapLeftButton.setOnClickListener(onClickListener) + snapLeftButton.setOnGenericMotionListener(onGenericMotionListener) } /** @@ -173,4 +189,12 @@ class MaximizeMenu( private fun viewsLaidOut(): Boolean { return maximizeMenu?.mWindowViewHost?.view?.isLaidOut ?: false } + + companion object { + fun isMaximizeMenuView(@IdRes viewId: Int): Boolean { + return viewId == R.id.maximize_menu || viewId == R.id.maximize_menu_maximize_button || + viewId == R.id.maximize_menu_snap_left_button || + viewId == R.id.maximize_menu_snap_right_button + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt index 2309c54b6591..7e5b9bd649f2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt @@ -21,6 +21,7 @@ import com.android.internal.R.attr.materialColorSurfaceContainerHigh import com.android.internal.R.attr.materialColorSurfaceContainerLow import com.android.internal.R.attr.materialColorSurfaceDim import com.android.wm.shell.R +import com.android.wm.shell.windowdecor.MaximizeButtonView /** * A desktop mode window decoration used when the window is floating (i.e. freeform). It hosts @@ -32,8 +33,10 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder( onCaptionTouchListener: View.OnTouchListener, onCaptionButtonClickListener: View.OnClickListener, onLongClickListener: OnLongClickListener, + onCaptionGenericMotionListener: View.OnGenericMotionListener, appName: CharSequence, - appIconBitmap: Bitmap + appIconBitmap: Bitmap, + onMaximizeHoverAnimationFinishedListener: () -> Unit ) : DesktopModeWindowDecorationViewHolder(rootView) { private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption) @@ -41,6 +44,8 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder( private val openMenuButton: View = rootView.requireViewById(R.id.open_menu_button) private val closeWindowButton: ImageButton = rootView.requireViewById(R.id.close_window) private val expandMenuButton: ImageButton = rootView.requireViewById(R.id.expand_menu_button) + private val maximizeButtonView: MaximizeButtonView = + rootView.requireViewById(R.id.maximize_button_view) private val maximizeWindowButton: ImageButton = rootView.requireViewById(R.id.maximize_window) private val appNameTextView: TextView = rootView.requireViewById(R.id.application_name) private val appIconImageView: ImageView = rootView.requireViewById(R.id.application_icon) @@ -55,10 +60,13 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder( closeWindowButton.setOnClickListener(onCaptionButtonClickListener) maximizeWindowButton.setOnClickListener(onCaptionButtonClickListener) maximizeWindowButton.setOnTouchListener(onCaptionTouchListener) + maximizeWindowButton.setOnGenericMotionListener(onCaptionGenericMotionListener) maximizeWindowButton.onLongClickListener = onLongClickListener closeWindowButton.setOnTouchListener(onCaptionTouchListener) appNameTextView.text = appName appIconImageView.setImageBitmap(appIconBitmap) + maximizeButtonView.onHoverAnimationFinishedListener = + onMaximizeHoverAnimationFinishedListener } override fun bindData(taskInfo: RunningTaskInfo) { @@ -73,12 +81,30 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder( maximizeWindowButton.imageAlpha = alpha closeWindowButton.imageAlpha = alpha expandMenuButton.imageAlpha = alpha + + maximizeButtonView.setAnimationTints(isDarkMode()) } override fun onHandleMenuOpened() {} override fun onHandleMenuClosed() {} + fun setAnimatingTaskResize(animatingTaskResize: Boolean) { + // If animating a task resize, cancel any running hover animations + if (animatingTaskResize) { + maximizeButtonView.cancelHoverAnimation() + } + maximizeButtonView.hoverDisabled = animatingTaskResize + } + + fun onMaximizeWindowHoverExit() { + maximizeButtonView.cancelHoverAnimation() + } + + fun onMaximizeWindowHoverEnter() { + maximizeButtonView.startHoverAnimation() + } + @ColorInt private fun getCaptionBackgroundColor(taskInfo: RunningTaskInfo): Int { if (isTransparentBackgroundRequested(taskInfo)) { diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt index adf92d8854ff..3380adac0b3f 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.appcompat import android.content.Context -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.FlickerTestData -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.FlickerTestData +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.server.wm.flicker.helpers.LetterboxAppHelper import com.android.server.wm.flicker.helpers.setRotation import com.android.wm.shell.flicker.BaseTest diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt index 1e5e42fb077e..f08eba5a73a3 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.appcompat import android.platform.test.annotations.Postsubmit -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt index 2fa1ec386781..826fc541687e 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt @@ -17,13 +17,13 @@ package com.android.wm.shell.flicker.appcompat import android.platform.test.annotations.Postsubmit -import android.tools.common.Rotation -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt index b74aa1d7bf73..26e78bf625ba 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt @@ -18,15 +18,15 @@ package com.android.wm.shell.flicker.appcompat import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.RequiresDevice -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.datatypes.Rect -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.Rotation +import android.tools.datatypes.Rect +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt index 68fa8d2fc2e8..2aa84b4e55b8 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt @@ -17,13 +17,13 @@ package com.android.wm.shell.flicker.appcompat import android.platform.test.annotations.Postsubmit -import android.tools.common.Rotation -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.flicker.assertions.FlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import androidx.test.filters.RequiresDevice import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt index fcb6931af9a2..443fac19c7e7 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.appcompat import android.platform.test.annotations.Postsubmit -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.flicker.assertions.FlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import androidx.test.filters.RequiresDevice import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt index 446aad8a8936..7ffa23345589 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt @@ -19,17 +19,17 @@ package com.android.wm.shell.flicker.appcompat import android.os.Build import android.platform.test.annotations.Postsubmit import android.system.helpers.CommandsHelper -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.datatypes.Rect -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.NavBar +import android.tools.Rotation +import android.tools.datatypes.Rect +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/TransparentBaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/TransparentBaseAppCompat.kt index 9792c859cced..2c0f837248f7 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/TransparentBaseAppCompat.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/TransparentBaseAppCompat.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.appcompat import android.content.Context -import android.tools.device.flicker.legacy.FlickerTestData -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.flicker.legacy.FlickerTestData +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.Until diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt index 0c36e29a8315..8eca45694d48 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt @@ -21,12 +21,12 @@ import android.app.NotificationManager import android.content.Context import android.content.pm.PackageManager import android.os.ServiceManager -import android.tools.common.Rotation -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.FlickerTestData -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.SYSTEMUI_PACKAGE +import android.tools.Rotation +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.FlickerTestData +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.SYSTEMUI_PACKAGE import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.Until diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt index 55039f59190b..bc486c277aa5 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt @@ -18,9 +18,9 @@ package com.android.wm.shell.flicker.bubble import android.os.SystemClock import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.FlakyTest import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObject2 diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt index 9ca7bf113589..521c0d0aaeb7 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt @@ -19,11 +19,11 @@ package com.android.wm.shell.flicker.bubble import android.content.Context import android.graphics.Point import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import android.util.DisplayMetrics import android.view.WindowManager import androidx.test.uiautomator.By diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt index b007e6b3535c..e059ac78dc6b 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.bubble import android.platform.test.annotations.Postsubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import android.view.WindowInsets import android.view.WindowManager import androidx.test.filters.FlakyTest diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt index 4959672d865b..ef7fbfb79beb 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.bubble import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt index 0d95574aca06..87224b151b78 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.bubble import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt index af2db12faf3a..d64bfed382b9 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.pip.common.EnterPipTransition @@ -46,7 +46,7 @@ import org.junit.runners.Parameterized * ``` * 1. All assertions are inherited from [EnterPipTest] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt index 8c0a524cda1e..a0edcfb17971 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -44,7 +44,7 @@ import org.junit.runners.Parameterized * ``` * 1. All assertions are inherited from [AutoEnterPipOnGoToHomeTest] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt index 9256725c6180..031acf4919eb 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.ClosePipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -44,7 +44,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt index 002c019eff93..860307f2bb76 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.ClosePipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -44,7 +44,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt index 4cc9547ba2e3..c5541613fece 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.Assume import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt index 07cd68261083..ac7380f83233 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt @@ -19,14 +19,14 @@ package com.android.wm.shell.flicker.pip import android.app.Activity import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.entireScreenCovered import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper @@ -60,7 +60,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt index cc943678d492..f97d8d1842b0 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt @@ -16,9 +16,9 @@ package com.android.wm.shell.flicker.pip -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt index 7da442901e40..47bf41814d17 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt @@ -16,9 +16,9 @@ package com.android.wm.shell.flicker.pip -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.ExitPipToAppTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -43,7 +43,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt index 0ad9e4c61d83..a356e68d14dd 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt @@ -16,9 +16,9 @@ package com.android.wm.shell.flicker.pip -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.wm.shell.flicker.pip.common.ExitPipToAppTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -42,7 +42,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt index 89a6c93e478c..25614ef63ccc 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -46,7 +46,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt index 8978af0088b8..1964e3cebc89 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt index 27922988038c..b94989d98e97 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt @@ -17,13 +17,13 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils +import android.tools.traces.parsers.toFlickerComponent import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions @@ -52,7 +52,7 @@ import org.junit.runners.Parameterized * ``` * 1. All assertions are inherited from [EnterPipTest] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt index 4c2315324eca..1ccc7d8084a6 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt @@ -17,13 +17,13 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils +import android.tools.traces.parsers.toFlickerComponent import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions @@ -53,7 +53,7 @@ import org.junit.runners.Parameterized * ``` * 1. All assertions are inherited from [EnterPipTest] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt index 4776206724cc..9b746224a1a0 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.pip.common.MovePipShelfHeightTransition import com.android.wm.shell.flicker.utils.Direction @@ -47,7 +47,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt index 425cbfaffedd..e184cf04e4ae 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt @@ -17,14 +17,14 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.flicker.assertions.FlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import com.android.server.wm.flicker.helpers.ImeAppHelper import com.android.server.wm.flicker.helpers.setRotation import com.android.wm.shell.flicker.pip.common.PipTransition diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt index 18f30d96938b..490ebd190ee8 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.pip.common.MovePipShelfHeightTransition import com.android.wm.shell.flicker.utils.Direction @@ -47,7 +47,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt index 36047cca55ea..70be58f06548 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt index c7f2786debd0..a4df69fc6539 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt @@ -18,10 +18,10 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit import android.platform.test.annotations.RequiresDevice -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.testapp.ActivityOptions import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt index cabc1cc0b023..90b9798c6329 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.pip import android.graphics.Rect -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.rules.RemoveAllTasksButHomeRule import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.setRotation diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt index 381f947cbc84..68417066ac0a 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.subject.exceptions.IncorrectRegionException -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.subject.exceptions.IncorrectRegionException +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt index 1f69847e5481..9a6dacb187ef 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt @@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.pip import android.app.Activity import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.flicker.assertions.FlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt index 308ece40402f..d2f803ec9352 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.assertions.FlickerTest -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.flicker.assertions.FlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.helpers.setRotation import com.android.wm.shell.flicker.pip.common.PipTransition @@ -50,7 +50,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt index be771712834f..c9f4a6ca75b1 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt @@ -17,13 +17,13 @@ package com.android.wm.shell.flicker.pip.apps import android.platform.test.annotations.Postsubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.junit.FlickerBuilderProvider -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerBuilderProvider +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.Test import org.junit.runners.Parameterized @@ -101,8 +101,9 @@ abstract class AppsEnterPipTransition(flicker: LegacyFlickerTest) : EnterPipTran override fun pipLayerReduces() { flicker.assertLayers { val pipLayerList = - this.layers { standardAppHelper.packageNameMatcher.layerMatchesAnyOf(it) - && it.isVisible } + this.layers { + standardAppHelper.packageNameMatcher.layerMatchesAnyOf(it) && it.isVisible + } pipLayerList.zipWithNext { previous, current -> current.visibleRegion.notBiggerThan(previous.visibleRegion.region) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt index 4c2eff3b6ce4..88650107e63a 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt @@ -26,9 +26,9 @@ import android.os.Looper import android.os.SystemClock import android.platform.test.annotations.Postsubmit import android.tools.device.apphelpers.MapsAppHelper -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.RequiresDevice import org.junit.Assume import org.junit.FixMethodOrder @@ -53,7 +53,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt index 143f7a726ed3..9b5153875987 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt @@ -18,14 +18,14 @@ package com.android.wm.shell.flicker.pip.apps import android.Manifest import android.platform.test.annotations.Postsubmit -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.NetflixAppHelper -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.statusBarLayerPositionAtEnd import org.junit.Assume @@ -51,7 +51,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt index 509b32c11afe..3ae5937df4d0 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.pip.apps import android.Manifest import android.platform.test.annotations.Postsubmit -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.YouTubeAppHelper -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.filters.RequiresDevice import org.junit.Assume import org.junit.FixMethodOrder @@ -47,7 +47,7 @@ import org.junit.runners.Parameterized * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via - * [android.tools.device.flicker.legacy.runner.TransitionRunner], + * [android.tools.flicker.legacy.runner.TransitionRunner], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt index 751f2bc0807f..dc122590388f 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.pip.common import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.helpers.setRotation import org.junit.Test import org.junit.runners.Parameterized diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt index 9c129e47efba..3d9eae62b499 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.pip.common import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import org.junit.Test import org.junit.runners.Parameterized diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt index 9450bdd2d894..7b6839dc123f 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.pip.common import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.helpers.SimpleAppHelper import org.junit.Test import org.junit.runners.Parameterized diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt index 7e42bc11a9c1..f4baf5f75928 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.pip.common import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.subject.region.RegionSubject +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper import com.android.wm.shell.flicker.utils.Direction import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt index 7b7f1d7b5a82..fd467e32e0dc 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt @@ -19,12 +19,12 @@ package com.android.wm.shell.flicker.pip.common import android.app.Instrumentation import android.content.Intent import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome +import android.tools.helpers.WindowUtils import com.android.server.wm.flicker.helpers.PipAppHelper import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt index c6cbcd052fe0..4e1a8ff313cc 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt @@ -17,7 +17,7 @@ package com.android.wm.shell.flicker.pip.tv import android.app.Instrumentation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.uiautomator.By import androidx.test.uiautomator.BySelector import androidx.test.uiautomator.UiObject2 diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt index 0d1853534927..285422236c64 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt @@ -20,8 +20,8 @@ import android.app.ActivityManager import android.app.IActivityManager import android.app.IProcessObserver import android.os.SystemClock -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import android.view.Surface.ROTATION_0 import android.view.Surface.rotationToString import com.android.wm.shell.flicker.utils.SYSTEM_UI_PACKAGE_NAME diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/common/Utils.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/common/Utils.kt index 4bd79546b96d..4c6c6cce0105 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/common/Utils.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/common/Utils.kt @@ -20,13 +20,13 @@ import android.app.Instrumentation import android.platform.test.rule.NavigationModeRule import android.platform.test.rule.PressHomeRule import android.platform.test.rule.UnlockScreenRule -import android.tools.common.NavBar -import android.tools.common.Rotation +import android.tools.NavBar +import android.tools.Rotation import android.tools.device.apphelpers.MessagingAppHelper -import android.tools.device.flicker.rules.ArtifactSaverRule -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.flicker.rules.LaunchAppRule -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.flicker.rules.ArtifactSaverRule +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.flicker.rules.LaunchAppRule +import android.tools.flicker.rules.RemoveAllTasksButHomeRule import androidx.test.platform.app.InstrumentationRegistry import org.junit.rules.RuleChain diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavLandscape.kt index a5c512267508..1684a26ac3d2 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.CopyContentInSplit import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavPortrait.kt index 092fb6720e57..3b5fad60d8ee 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/CopyContentInSplitGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.CopyContentInSplit import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavLandscape.kt index 69499b9b488b..2b8a90305d90 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByDivider import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavPortrait.kt index bd627f4babaa..b284fe1caad5 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByDividerGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByDivider import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavLandscape.kt index a8f4d0a24c7e..a400ee44caa5 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByGoHome import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavPortrait.kt index cee9bbfb4aa4..7f5ee4c2cdda 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DismissSplitScreenByGoHomeGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByGoHome import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavLandscape.kt index c1b3aade11cd..1b075c498bc0 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DragDividerToResize import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavPortrait.kt index c6e2e854ab89..6ca373714f8a 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/DragDividerToResizeGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.DragDividerToResize import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt index 169b5cfa3462..f7d231f02935 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromAllApps import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt index 412c011a3f17..ab819fad292a 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromAllApps import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt index 6e4cf9f55cfd..a6b732c47ea2 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromNotification import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt index cc2870213e8d..07e5f4b0b472 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromNotification import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt index 736604f02377..272569456d7b 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromShortcut import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt index 8df8dfaab071..58cc4d70fde4 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromShortcut import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt index 378f055ef830..85897a136e33 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromTaskbar import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt index b33d26288d33..891b6df89b45 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromTaskbar import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavLandscape.kt index b1d3858b9dbb..798365218b04 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenFromOverview import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavPortrait.kt index 6d824c74c1fe..1bdea66fc596 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/EnterSplitScreenFromOverviewGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenFromOverview import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt index f1d3d0cf2716..bab0c0aa1e6a 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchAppByDoubleTapDivider import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt index a867bac8c0eb..17a59ab8a173 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchAppByDoubleTapDivider import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt index 76247ba10037..2c36d647b719 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromAnotherApp import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt index e179da81e4db..6e91d047e64b 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromAnotherApp import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavLandscape.kt index 20f554f7d154..a921b4663d09 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromHome import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavPortrait.kt index f7776ee3244a..05f8912f6f47 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromHomeGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromHome import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavLandscape.kt index 4ff0b4362e60..1ae1f53b9bc1 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromRecent import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavPortrait.kt index 930f31d1f348..e14ca550c84d 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBackToSplitFromRecentGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromRecent import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavLandscape.kt index 3da61e5e310c..ce0c4c456587 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBetweenSplitPairs import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavPortrait.kt index 627ae1843314..5a8d2d51bec4 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/SwitchBetweenSplitPairsGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBetweenSplitPairs import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavLandscape.kt index c744103d49ba..d44261549544 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavLandscape.kt @@ -16,12 +16,12 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.UnlockKeyguardToSplitScreen import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavPortrait.kt index 11a4e02c5e37..ddc8a0697beb 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/flicker/UnlockKeyguardToSplitScreenGesturalNavPortrait.kt @@ -16,12 +16,12 @@ package com.android.wm.shell.flicker.service.splitscreen.flicker -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.wm.shell.flicker.service.splitscreen.scenarios.UnlockKeyguardToSplitScreen import org.junit.Test import org.junit.runner.RunWith diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavLandscape.kt index e37d806c7a14..64293b288a2e 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.CopyContentInSplit import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavPortrait.kt index 2a50912e0a5c..517ba2dfc164 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/CopyContentInSplitGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.CopyContentInSplit import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavLandscape.kt index d5da1a8b558c..1bafe3b0898c 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByDivider import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavPortrait.kt index 7fdcb9be62ee..fd0100fd6c21 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByDividerGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByDivider import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavLandscape.kt index 308e954b86c1..850b3d8f9867 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByGoHome import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavPortrait.kt index 39e75bd25a71..0b752bf7f58e 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DismissSplitScreenByGoHomeGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DismissSplitScreenByGoHome import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavLandscape.kt index e18da17175c0..3c52aa71eb9d 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DragDividerToResize import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavPortrait.kt index 00d60e756ffa..c2e21b89a480 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/DragDividerToResizeGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.DragDividerToResize import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt index d7efbc8c0fd4..bf85ab44df5e 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromAllApps import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt index 4eece3f62d10..0ac4ca20e303 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromAllAppsGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromAllApps import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt index d96b056d8753..80bd088a192f 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromNotification import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt index 809b690e0861..0dffb4af8d41 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromNotificationGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromNotification import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt index bbdf2d728494..b721f2fe294a 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromShortcut import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt index 5c29fd8fe57e..22cbc77d024b 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromShortcutGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromShortcut import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt index a7398ebf56e8..ac0f9e25285d 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromTaskbar import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt index eae88ad4ad09..f7a229d5ff16 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenByDragFromTaskbarGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenByDragFromTaskbar import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavLandscape.kt index 7e8ee04a28fa..6dbbcb0fcfb5 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenFromOverview import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavPortrait.kt index 9295c330b879..bd69ea98a67b 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/EnterSplitScreenFromOverviewGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.EnterSplitScreenFromOverview import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt index 4b59e9fbd866..404b96fafd24 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchAppByDoubleTapDivider import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt index 5ff36d4aabbb..a79687ddf68f 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchAppByDoubleTapDividerGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchAppByDoubleTapDivider import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt index c0cb7219437b..b52eb4cd6533 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromAnotherApp import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt index 8c140884aa50..d79620c73132 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromAnotherAppGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromAnotherApp import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavLandscape.kt index 7b6614b81c11..d27bfa1a22c9 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromHome import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavPortrait.kt index 5df5be9daa8b..3c7d4d4806cf 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromHomeGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromHome import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavLandscape.kt index 9d63003bf2a1..26a2034f16d9 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromRecent import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavPortrait.kt index 9fa04b208ad1..5154b35ed0e6 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBackToSplitFromRecentGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBackToSplitFromRecent import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavLandscape.kt index 9386aa2b2cf0..86451c524ee6 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavLandscape.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavLandscape.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBetweenSplitPairs import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavPortrait.kt index 5ef21672bfe0..baf72b40d6d4 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavPortrait.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/platinum/SwitchBetweenSplitPairsGesturalNavPortrait.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.service.splitscreen.platinum import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation +import android.tools.Rotation import com.android.wm.shell.flicker.service.splitscreen.scenarios.SwitchBetweenSplitPairs import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt index 824e45403d2a..89ef91e12758 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByDivider.kt index 4c391047e853..c1a8ee714abd 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByDivider.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByGoHome.kt index f6d1afc05a5a..600855a8ab38 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByGoHome.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DismissSplitScreenByGoHome.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DragDividerToResize.kt index db5a32a382fb..c671fbe39ac5 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DragDividerToResize.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/DragDividerToResize.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromAllApps.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromAllApps.kt index 03170a326890..a189325d52ea 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromAllApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromAllApps.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt index c52ada3b312f..433669205834 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt index 479d01ddaeb9..8c7e63f7471f 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt index 625c56bc4a4c..2072831d7d1b 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt index f1a011c0d191..09e77ccffba7 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt index c9b1c916ff4b..babdae164835 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation import android.graphics.Point -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.helpers.WindowUtils -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.helpers.WindowUtils +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt index 72f2db3380dd..3e8547961ea0 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt index 511de4fd8b90..655ae4e29af3 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt index 558d2bf1f349..22082586bb62 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt index ecd68295df9a..2ac63c2afefc 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt index f50d5c7df8d7..35b122d7bc9e 100644 --- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.service.splitscreen.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.AndroidLoggerSetupRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.AndroidLoggerSetupRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt index 6b971699d212..d74c59ef0879 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.EdgeExtensionComponentMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.EdgeExtensionComponentMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.CopyContentInSplitBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt index 51588569a8aa..dd45f654d3bc 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt @@ -18,10 +18,10 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.helpers.WindowUtils +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.helpers.WindowUtils import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.DismissSplitScreenByDividerBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt index fc6c2b3d7ce7..6d396ea6e9d4 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.DismissSplitScreenByGoHomeBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt index 8b1689a9d816..2ed916e56c67 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.DragDividerToResizeBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt index 99613f39060d..1a455311b3b6 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.EnterSplitScreenByDragFromAllAppsBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt index 756a7fa4ba98..0cb1e4006c0d 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.EnterSplitScreenByDragFromNotificationBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt index 121b46acdb66..ff406b75b235 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.EnterSplitScreenByDragFromShortcutBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt index 99deb9279271..2b817988a589 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.EnterSplitScreenByDragFromTaskbarBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt index 212a4e3649dc..186af54fb57b 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.EnterSplitScreenFromOverviewBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt index fac97c8cc8c4..9dde49011ed0 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt @@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.SwitchAppByDoubleTapDividerBenchmark import com.android.wm.shell.flicker.utils.ICommonAssertions diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt index 284c32ea110d..5222b08240c6 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.SwitchBackToSplitFromAnotherAppBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt index 9e6448f0bec9..a8a8ae88a9e7 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.SwitchBackToSplitFromHomeBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt index 8e28712cd993..836f664ca544 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt @@ -17,11 +17,11 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.SwitchBackToSplitFromRecentBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt index fb0193b1830d..3c4a1caecb8d 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt @@ -17,10 +17,10 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.SwitchBetweenSplitPairsBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt index 715a533a7bab..8724346427f4 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt @@ -17,12 +17,12 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.PipAppHelper import com.android.wm.shell.flicker.splitscreen.benchmark.SplitScreenBase diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt index e6a2022166ea..16d73318bd3a 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt @@ -18,14 +18,14 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.common.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.region.RegionSubject +import android.tools.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.splitscreen.benchmark.UnlockKeyguardToSplitScreenBenchmark diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt index df1c9a2ec089..9c5a3fe35bfe 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt index d01eab060263..c99fcc4129d5 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt index e36bd33bd1fd..ef3a87955bd6 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt index 050d389e978c..18550d7f0467 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.Assume diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt index 5c43cbdb3832..d16c5d77410c 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.After diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt index cd3fbab1497b..f8be6be08782 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.Assume diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt index 15ad0c12c49a..a99ef64e7bf5 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.After diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt index ca8adb1fcb38..f58400966531 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.After diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt index 5e5e7d7fc3c9..7084f6aec1fb 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SplitScreenBase.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SplitScreenBase.kt index a0e437c25aa7..4b106034b2b5 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SplitScreenBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SplitScreenBase.kt @@ -17,8 +17,8 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.content.Context -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.server.wm.flicker.helpers.setRotation import com.android.wm.shell.flicker.BaseBenchmarkTest import com.android.wm.shell.flicker.utils.SplitScreenUtils diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt index e39c3c93d79a..38206c396efb 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt @@ -16,14 +16,14 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.WindowUtils +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt index 32284ba41aee..3a2316f7a10c 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt index a926ec903f58..ded0b0729998 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt index d2e1d5294aa1..7b1397baa7a3 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt index 9d6b25174c13..457288f445df 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/UnlockKeyguardToSplitScreenBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/UnlockKeyguardToSplitScreenBenchmark.kt index e71834de7123..7493538fa2ba 100644 --- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/UnlockKeyguardToSplitScreenBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/UnlockKeyguardToSplitScreenBenchmark.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.tools.common.NavBar -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt index e9363f725fd8..d03c2f1077bd 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt @@ -17,9 +17,9 @@ package com.android.wm.shell.flicker import android.app.Instrumentation -import android.tools.device.flicker.junit.FlickerBuilderProvider -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerBuilderProvider +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt index 568650d71872..a19d232c9a2f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt @@ -17,8 +17,8 @@ package com.android.wm.shell.flicker import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.LegacyFlickerTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.wm.shell.flicker.utils.ICommonAssertions diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt index f1cb37ee1293..3df0954da2e9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt @@ -18,13 +18,13 @@ package com.android.wm.shell.flicker.utils -import android.tools.common.Rotation -import android.tools.common.datatypes.Region -import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.traces.component.IComponentMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.helpers.WindowUtils +import android.tools.Rotation +import android.tools.datatypes.Region +import android.tools.flicker.subject.layers.LayerTraceEntrySubject +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.traces.component.IComponentMatcher +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.helpers.WindowUtils fun LegacyFlickerTest.appPairsDividerIsVisibleAtEnd() { assertLayersEnd { this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonConstants.kt index 3b66d6addacd..fb21fcceea6e 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonConstants.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonConstants.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.utils -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui" const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher" diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt index 7f58cedce63d..50c04354528f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt @@ -17,8 +17,8 @@ package com.android.wm.shell.flicker.utils import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import android.tools.flicker.legacy.LegacyFlickerTest import com.android.server.wm.flicker.entireScreenCovered import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt index 3244ebc9ef32..4e9a9d65dbf9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt @@ -19,14 +19,14 @@ package com.android.wm.shell.flicker.utils import android.app.Instrumentation import android.graphics.Point import android.os.SystemClock -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.IComponentMatcher -import android.tools.common.traces.component.IComponentNameMatcher +import android.tools.Rotation +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.IComponentMatcher +import android.tools.traces.component.IComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import android.view.InputDevice import android.view.MotionEvent import android.view.ViewConfiguration diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp index 8c4711603904..32c070305e05 100644 --- a/libs/WindowManager/Shell/tests/unittest/Android.bp +++ b/libs/WindowManager/Shell/tests/unittest/Android.bp @@ -24,7 +24,10 @@ package { android_test { name: "WMShellUnitTests", - + defaults: [ + // For ExtendedMockito dependencies. + "modules-utils-testable-device-config-defaults", + ], srcs: [ "**/*.java", "**/*.kt", diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt new file mode 100644 index 000000000000..4548fcb06c55 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.desktopmode + +import com.android.dx.mockito.inline.extended.ExtendedMockito +import com.android.internal.util.FrameworkStatsLog +import com.android.modules.utils.testing.ExtendedMockitoRule +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.mockito.kotlin.eq + +/** + * Tests for [DesktopModeEventLogger]. + */ +class DesktopModeEventLoggerTest { + + private val desktopModeEventLogger = DesktopModeEventLogger() + + @JvmField + @Rule + val extendedMockitoRule = ExtendedMockitoRule.Builder(this) + .mockStatic(FrameworkStatsLog::class.java).build()!! + + @Test + fun logSessionEnter_enterReason() = runBlocking { + desktopModeEventLogger.logSessionEnter(sessionId = SESSION_ID, EnterReason.UNKNOWN_ENTER) + + ExtendedMockito.verify { + FrameworkStatsLog.write( + eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED), + /* event */ + eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__ENTER), + /* enter_reason */ + eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__UNKNOWN_ENTER), + /* exit_reason */ + eq(0), + /* sessionId */ + eq(SESSION_ID) + ) + } + } + + @Test + fun logSessionExit_exitReason() = runBlocking { + desktopModeEventLogger.logSessionExit(sessionId = SESSION_ID, ExitReason.UNKNOWN_EXIT) + + ExtendedMockito.verify { + FrameworkStatsLog.write( + eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED), + /* event */ + eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__EXIT), + /* enter_reason */ + eq(0), + /* exit_reason */ + eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__UNKNOWN_EXIT), + /* sessionId */ + eq(SESSION_ID) + ) + } + } + + @Test + fun logTaskAdded_taskUpdate() = runBlocking { + desktopModeEventLogger.logTaskAdded(sessionId = SESSION_ID, TASK_UPDATE) + + ExtendedMockito.verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), + /* task_event */ + eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED), + /* instance_id */ + eq(TASK_UPDATE.instanceId), + /* uid */ + eq(TASK_UPDATE.uid), + /* task_height */ + eq(TASK_UPDATE.taskHeight), + /* task_width */ + eq(TASK_UPDATE.taskWidth), + /* task_x */ + eq(TASK_UPDATE.taskX), + /* task_y */ + eq(TASK_UPDATE.taskY), + /* session_id */ + eq(SESSION_ID)) + } + } + + @Test + fun logTaskRemoved_taskUpdate() = runBlocking { + desktopModeEventLogger.logTaskRemoved(sessionId = SESSION_ID, TASK_UPDATE) + + ExtendedMockito.verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), + /* task_event */ + eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED), + /* instance_id */ + eq(TASK_UPDATE.instanceId), + /* uid */ + eq(TASK_UPDATE.uid), + /* task_height */ + eq(TASK_UPDATE.taskHeight), + /* task_width */ + eq(TASK_UPDATE.taskWidth), + /* task_x */ + eq(TASK_UPDATE.taskX), + /* task_y */ + eq(TASK_UPDATE.taskY), + /* session_id */ + eq(SESSION_ID)) + } + } + + @Test + fun logTaskInfoChanged_taskUpdate() = runBlocking { + desktopModeEventLogger.logTaskInfoChanged(sessionId = SESSION_ID, TASK_UPDATE) + + ExtendedMockito.verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), + /* task_event */ + eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + /* instance_id */ + eq(TASK_UPDATE.instanceId), + /* uid */ + eq(TASK_UPDATE.uid), + /* task_height */ + eq(TASK_UPDATE.taskHeight), + /* task_width */ + eq(TASK_UPDATE.taskWidth), + /* task_x */ + eq(TASK_UPDATE.taskX), + /* task_y */ + eq(TASK_UPDATE.taskY), + /* session_id */ + eq(SESSION_ID)) + } + } + + companion object { + private const val SESSION_ID = 1 + private const val TASK_ID = 1 + private const val TASK_UID = 1 + private const val TASK_X = 0 + private const val TASK_Y = 0 + private const val TASK_HEIGHT = 100 + private const val TASK_WIDTH = 100 + + private val TASK_UPDATE = TaskUpdate( + TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y + ) + } +}
\ No newline at end of file diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index e4f3e2defb25..40239b8c2719 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -155,6 +155,7 @@ cc_defaults { host: { static_libs: [ "libandroidfw", + "libhostgraphics", "libutils", ], }, @@ -427,6 +428,7 @@ cc_defaults { "jni/MovieImpl.cpp", "jni/pdf/PdfDocument.cpp", "jni/pdf/PdfEditor.cpp", + "jni/pdf/PdfRenderer.cpp", "jni/pdf/PdfUtils.cpp", ], shared_libs: [ @@ -501,6 +503,17 @@ cc_library_headers { ], header_libs: ["android_graphics_jni_headers"], export_header_lib_headers: ["android_graphics_jni_headers"], + target: { + android: { + export_include_dirs: ["platform/android"], + }, + host: { + export_include_dirs: ["platform/host"], + }, + windows: { + enabled: true, + }, + }, } cc_defaults { @@ -538,6 +551,7 @@ cc_defaults { "utils/Blur.cpp", "utils/Color.cpp", "utils/LinearAllocator.cpp", + "utils/StringUtils.cpp", "utils/TypefaceUtils.cpp", "utils/VectorDrawableUtils.cpp", "AnimationContext.cpp", @@ -552,6 +566,7 @@ cc_defaults { "Mesh.cpp", "MemoryPolicy.cpp", "PathParser.cpp", + "ProfileData.cpp", "Properties.cpp", "PropertyValuesAnimatorSet.cpp", "PropertyValuesHolder.cpp", @@ -569,12 +584,13 @@ cc_defaults { export_proto_headers: true, }, + header_libs: ["libandroid_headers_private"], + target: { android: { - header_libs: [ - "libandroid_headers_private", - "libtonemap_headers", - ], + header_libs: ["libtonemap_headers"], + + local_include_dirs: ["platform/android"], srcs: [ "hwui/AnimatedImageThread.cpp", @@ -605,7 +621,6 @@ cc_defaults { "thread/CommonPool.cpp", "utils/GLUtils.cpp", "utils/NdkUtils.cpp", - "utils/StringUtils.cpp", "AutoBackendTextureRelease.cpp", "DeferredLayerUpdater.cpp", "DeviceInfo.cpp", @@ -617,7 +632,6 @@ cc_defaults { "FrameMetricsReporter.cpp", "Layer.cpp", "LayerUpdateQueue.cpp", - "ProfileData.cpp", "ProfileDataContainer.cpp", "Readback.cpp", "TreeInfo.cpp", @@ -628,6 +642,21 @@ cc_defaults { // Allow implicit fallthroughs in HardwareBitmapUploader.cpp until they are fixed. cflags: ["-Wno-implicit-fallthrough"], }, + host: { + header_libs: ["libnativebase_headers"], + + local_include_dirs: ["platform/host"], + + srcs: [ + "platform/host/renderthread/CacheManager.cpp", + "platform/host/renderthread/RenderThread.cpp", + "platform/host/ProfileDataContainer.cpp", + "platform/host/Readback.cpp", + "platform/host/WebViewFunctorManager.cpp", + ], + + cflags: ["-Wno-unused-private-field"], + }, }, } @@ -663,6 +692,7 @@ cc_defaults { header_libs: ["libandroid_headers_private"], target: { android: { + local_include_dirs: ["platform/android"], shared_libs: [ "libgui", "libui", diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in index d21f07efe36a..b12486e32bd4 100644 --- a/libs/hwui/DisplayListOps.in +++ b/libs/hwui/DisplayListOps.in @@ -26,6 +26,7 @@ X(ClipPath) X(ClipRect) X(ClipRRect) X(ClipRegion) +X(ClipShader) X(ResetClip) X(DrawPaint) X(DrawBehind) diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp index 3d0ca0a10851..7be9541f6b99 100644 --- a/libs/hwui/ProfileData.cpp +++ b/libs/hwui/ProfileData.cpp @@ -110,6 +110,7 @@ void ProfileData::mergeWith(const ProfileData& other) { } void ProfileData::dump(int fd) const { +#ifdef __ANDROID__ dprintf(fd, "\nStats since: %" PRIu64 "ns", mStatStartTime); dprintf(fd, "\nTotal frames rendered: %u", mTotalFrameCount); dprintf(fd, "\nJanky frames: %u (%.2f%%)", mJankFrameCount, @@ -138,6 +139,7 @@ void ProfileData::dump(int fd) const { dprintf(fd, " %ums=%u", entry.renderTimeMs, entry.frameCount); }); dprintf(fd, "\n"); +#endif } uint32_t ProfileData::findPercentile(int percentile) const { diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 3b694c5d399b..54aef55f8b90 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -207,6 +207,13 @@ struct ClipRegion final : Op { SkClipOp op; void draw(SkCanvas* c, const SkMatrix&) const { c->clipRegion(region, op); } }; +struct ClipShader final : Op { + static const auto kType = Type::ClipShader; + ClipShader(const sk_sp<SkShader>& shader, SkClipOp op) : shader(shader), op(op) {} + sk_sp<SkShader> shader; + SkClipOp op; + void draw(SkCanvas* c, const SkMatrix&) const { c->clipShader(shader, op); } +}; struct ResetClip final : Op { static const auto kType = Type::ResetClip; ResetClip() {} @@ -822,6 +829,9 @@ void DisplayListData::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { void DisplayListData::clipRegion(const SkRegion& region, SkClipOp op) { this->push<ClipRegion>(0, region, op); } +void DisplayListData::clipShader(const sk_sp<SkShader>& shader, SkClipOp op) { + this->push<ClipShader>(0, shader, op); +} void DisplayListData::resetClip() { this->push<ResetClip>(0); } @@ -1134,6 +1144,11 @@ void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) { fDL->clipRegion(region, op); this->INHERITED::onClipRegion(region, op); } +void RecordingCanvas::onClipShader(sk_sp<SkShader> shader, SkClipOp op) { + setClipMayBeComplex(); + fDL->clipShader(shader, op); + this->INHERITED::onClipShader(shader, op); +} void RecordingCanvas::onResetClip() { // This is part of "replace op" emulation, but rely on the following intersection // clip to potentially mark the clip as complex. If we are already complex, we do diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index afadbfda7471..965264f31119 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -140,6 +140,7 @@ private: void translateZ(SkScalar); void clipPath(const SkPath&, SkClipOp, bool aa); + void clipShader(const sk_sp<SkShader>& shader, SkClipOp); void clipRect(const SkRect&, SkClipOp, bool aa); void clipRRect(const SkRRect&, SkClipOp, bool aa); void clipRegion(const SkRegion&, SkClipOp); @@ -216,6 +217,7 @@ public: void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override; void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override; void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override; + void onClipShader(sk_sp<SkShader>, SkClipOp) override; void onClipRegion(const SkRegion&, SkClipOp) override; void onResetClip() override; diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp index fb0cdb034575..883f273b5d3d 100644 --- a/libs/hwui/apex/jni_runtime.cpp +++ b/libs/hwui/apex/jni_runtime.cpp @@ -70,6 +70,7 @@ extern int register_android_graphics_fonts_Font(JNIEnv* env); extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); +extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); extern int register_android_graphics_text_MeasuredText(JNIEnv* env); extern int register_android_graphics_text_LineBreaker(JNIEnv *env); extern int register_android_graphics_text_TextShaper(JNIEnv *env); @@ -141,6 +142,7 @@ extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env); REG_JNI(register_android_graphics_fonts_FontFamily), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), + REG_JNI(register_android_graphics_pdf_PdfRenderer), REG_JNI(register_android_graphics_text_MeasuredText), REG_JNI(register_android_graphics_text_LineBreaker), REG_JNI(register_android_graphics_text_TextShaper), diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h index 02bf0d8d5e95..1fcb6920db14 100644 --- a/libs/hwui/hwui/DrawTextFunctor.h +++ b/libs/hwui/hwui/DrawTextFunctor.h @@ -92,6 +92,7 @@ public: // high contrast draw path int color = paint.getColor(); bool darken; + // This equation should match the one in core/java/android/text/Layout.java if (flags::high_contrast_text_luminance()) { uirenderer::Lab lab = uirenderer::sRGBToLab(color); darken = lab.L <= 50; diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp index 1fc34d633370..9b63a46822ac 100644 --- a/libs/hwui/jni/android_graphics_Canvas.cpp +++ b/libs/hwui/jni/android_graphics_Canvas.cpp @@ -88,6 +88,10 @@ static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHand get_canvas(canvasHandle)->setBitmap(bitmap); } +static jboolean isHighContrastText(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) { + return get_canvas(canvasHandle)->isHighContrastText() ? JNI_TRUE : JNI_FALSE; +} + static jboolean isOpaque(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) { return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE; } @@ -792,6 +796,7 @@ static const JNINativeMethod gMethods[] = { // ------------ @CriticalNative ---------------- {"nIsOpaque", "(J)Z", (void*)CanvasJNI::isOpaque}, + {"nIsHighContrastText", "(J)Z", (void*)CanvasJNI::isHighContrastText}, {"nGetWidth", "(J)I", (void*)CanvasJNI::getWidth}, {"nGetHeight", "(J)I", (void*)CanvasJNI::getHeight}, {"nSave", "(JI)I", (void*)CanvasJNI::save}, diff --git a/libs/hwui/jni/pdf/PdfRenderer.cpp b/libs/hwui/jni/pdf/PdfRenderer.cpp new file mode 100644 index 000000000000..cc1f96197c74 --- /dev/null +++ b/libs/hwui/jni/pdf/PdfRenderer.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PdfUtils.h" + +#include "GraphicsJNI.h" +#include "SkBitmap.h" +#include "SkMatrix.h" +#include "fpdfview.h" + +#include <vector> +#include <utils/Log.h> +#include <unistd.h> +#include <sys/types.h> +#include <unistd.h> + +namespace android { + +static const int RENDER_MODE_FOR_DISPLAY = 1; +static const int RENDER_MODE_FOR_PRINT = 2; + +static struct { + jfieldID x; + jfieldID y; +} gPointClassInfo; + +static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr, + jint pageIndex, jobject outSize) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot load page"); + return -1; + } + + double width = 0; + double height = 0; + + int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); + if (!result) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot get page size"); + return -1; + } + + env->SetIntField(outSize, gPointClassInfo.x, width); + env->SetIntField(outSize, gPointClassInfo.y, height); + + return reinterpret_cast<jlong>(page); +} + +static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { + FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); + FPDF_ClosePage(page); +} + +static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, + jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, + jlong transformPtr, jint renderMode) { + FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); + + SkBitmap skBitmap; + bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap); + + const int stride = skBitmap.width() * 4; + + FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), + FPDFBitmap_BGRA, skBitmap.getPixels(), stride); + + int renderFlags = FPDF_REVERSE_BYTE_ORDER; + if (renderMode == RENDER_MODE_FOR_DISPLAY) { + renderFlags |= FPDF_LCD_TEXT; + } else if (renderMode == RENDER_MODE_FOR_PRINT) { + renderFlags |= FPDF_PRINTING; + } + + SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr); + SkScalar transformValues[6]; + if (!matrix.asAffine(transformValues)) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "transform matrix has perspective. Only affine matrices are allowed."); + return; + } + + FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], + transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], + transformValues[SkMatrix::kATransX], + transformValues[SkMatrix::kATransY]}; + + FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; + + FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags); + + skBitmap.notifyPixelsChanged(); +} + +static const JNINativeMethod gPdfRenderer_Methods[] = { + {"nativeCreate", "(IJ)J", (void*) nativeOpen}, + {"nativeClose", "(J)V", (void*) nativeClose}, + {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, + {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, + {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage}, + {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, + {"nativeClosePage", "(J)V", (void*) nativeClosePage} +}; + +int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) { + int result = RegisterMethodsOrDie( + env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods, + NELEM(gPdfRenderer_Methods)); + + jclass clazz = FindClassOrDie(env, "android/graphics/Point"); + gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I"); + gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I"); + + return result; +}; + +}; diff --git a/libs/hwui/thread/ThreadBase.h b/libs/hwui/platform/android/thread/ThreadBase.h index 0289d3fd2ef7..2f3581f8b355 100644 --- a/libs/hwui/thread/ThreadBase.h +++ b/libs/hwui/platform/android/thread/ThreadBase.h @@ -17,14 +17,14 @@ #ifndef HWUI_THREADBASE_H #define HWUI_THREADBASE_H -#include "WorkQueue.h" -#include "utils/Macros.h" - #include <utils/Looper.h> #include <utils/Thread.h> #include <algorithm> +#include "thread/WorkQueue.h" +#include "utils/Macros.h" + namespace android::uirenderer { class ThreadBase : public Thread { diff --git a/libs/hwui/platform/host/ProfileDataContainer.cpp b/libs/hwui/platform/host/ProfileDataContainer.cpp new file mode 100644 index 000000000000..9ed1b02a8082 --- /dev/null +++ b/libs/hwui/platform/host/ProfileDataContainer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ProfileDataContainer.h" + +#include <log/log.h> + +namespace android { +namespace uirenderer { + +void ProfileDataContainer::freeData() REQUIRES(mJankDataMutex) { + delete mData; + mIsMapped = false; + mData = nullptr; +} + +void ProfileDataContainer::rotateStorage() { + std::lock_guard lock(mJankDataMutex); + mData->reset(); +} + +void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) { + ALOGE("Ashmem is not supported for non-Android configurations"); +} + +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/platform/host/Readback.cpp b/libs/hwui/platform/host/Readback.cpp new file mode 100644 index 000000000000..b024ec02efc3 --- /dev/null +++ b/libs/hwui/platform/host/Readback.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Readback.h" + +using namespace android::uirenderer::renderthread; + +namespace android { +namespace uirenderer { + +void Readback::copySurfaceInto(ANativeWindow* window, const std::shared_ptr<CopyRequest>& request) { +} + +CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) { + return CopyResult::UnknownError; +} + +CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) { + return CopyResult::UnknownError; +} + +CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) { + return CopyResult::UnknownError; +} + +CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, const Rect& srcRect, + SkBitmap* bitmap) { + return CopyResult::UnknownError; +} + +bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect, + SkBitmap* bitmap) { + return false; +} + +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/platform/host/WebViewFunctorManager.cpp b/libs/hwui/platform/host/WebViewFunctorManager.cpp new file mode 100644 index 000000000000..1d16655bf73c --- /dev/null +++ b/libs/hwui/platform/host/WebViewFunctorManager.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebViewFunctorManager.h" + +namespace android::uirenderer { + +WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, + RenderMode functorMode) + : mData(data) {} + +WebViewFunctor::~WebViewFunctor() {} + +void WebViewFunctor::sync(const WebViewSyncData& syncData) const {} + +void WebViewFunctor::onRemovedFromTree() {} + +bool WebViewFunctor::prepareRootSurfaceControl() { + return true; +} + +void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {} + +void WebViewFunctor::initVk(const VkFunctorInitParams& params) {} + +void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) {} + +void WebViewFunctor::postDrawVk() {} + +void WebViewFunctor::destroyContext() {} + +void WebViewFunctor::removeOverlays() {} + +ASurfaceControl* WebViewFunctor::getSurfaceControl() { + return mSurfaceControl; +} + +void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) {} + +void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) {} + +WebViewFunctorManager& WebViewFunctorManager::instance() { + static WebViewFunctorManager sInstance; + return sInstance; +} + +int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, + RenderMode functorMode) { + return 0; +} + +void WebViewFunctorManager::releaseFunctor(int functor) {} + +void WebViewFunctorManager::onContextDestroyed() {} + +void WebViewFunctorManager::destroyFunctor(int functor) {} + +sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) { + return nullptr; +} + +} // namespace android::uirenderer diff --git a/libs/hwui/platform/host/renderthread/CacheManager.cpp b/libs/hwui/platform/host/renderthread/CacheManager.cpp new file mode 100644 index 000000000000..b03f400cd7d6 --- /dev/null +++ b/libs/hwui/platform/host/renderthread/CacheManager.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "renderthread/CacheManager.h" + +namespace android { +namespace uirenderer { +namespace renderthread { + +CacheManager::CacheManager(RenderThread& thread) + : mRenderThread(thread), mMemoryPolicy(loadMemoryPolicy()) {} + +void CacheManager::setupCacheLimits() {} + +void CacheManager::destroy() {} + +void CacheManager::trimMemory(TrimLevel mode) {} + +void CacheManager::trimCaches(CacheTrimLevel mode) {} + +void CacheManager::trimStaleResources() {} + +void CacheManager::getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage) {} + +void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState) {} + +void CacheManager::onFrameCompleted() {} + +void CacheManager::onThreadIdle() {} + +void CacheManager::scheduleDestroyContext() {} + +void CacheManager::cancelDestroyContext() {} + +bool CacheManager::areAllContextsStopped() { + return false; +} + +void CacheManager::checkUiHidden() {} + +void CacheManager::registerCanvasContext(CanvasContext* context) {} + +void CacheManager::unregisterCanvasContext(CanvasContext* context) {} + +void CacheManager::onContextStopped(CanvasContext* context) {} + +void CacheManager::notifyNextFrameSize(int width, int height) {} + +} /* namespace renderthread */ +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/platform/host/renderthread/RenderThread.cpp b/libs/hwui/platform/host/renderthread/RenderThread.cpp new file mode 100644 index 000000000000..6f08b5979772 --- /dev/null +++ b/libs/hwui/platform/host/renderthread/RenderThread.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "renderthread/RenderThread.h" + +#include "Readback.h" +#include "renderthread/VulkanManager.h" + +namespace android { +namespace uirenderer { +namespace renderthread { + +static bool gHasRenderThreadInstance = false; +static JVMAttachHook gOnStartHook = nullptr; + +ASurfaceControlFunctions::ASurfaceControlFunctions() {} + +bool RenderThread::hasInstance() { + return gHasRenderThreadInstance; +} + +void RenderThread::setOnStartHook(JVMAttachHook onStartHook) { + LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started..."); + gOnStartHook = onStartHook; +} + +JVMAttachHook RenderThread::getOnStartHook() { + return gOnStartHook; +} + +RenderThread& RenderThread::getInstance() { + [[clang::no_destroy]] static sp<RenderThread> sInstance = []() { + sp<RenderThread> thread = sp<RenderThread>::make(); + thread->start("RenderThread"); + return thread; + }(); + gHasRenderThreadInstance = true; + return *sInstance; +} + +RenderThread::RenderThread() + : ThreadBase() + , mVsyncSource(nullptr) + , mVsyncRequested(false) + , mFrameCallbackTaskPending(false) + , mRenderState(nullptr) + , mEglManager(nullptr) + , mFunctorManager(WebViewFunctorManager::instance()) + , mGlobalProfileData(mJankDataMutex) { + Properties::load(); +} + +RenderThread::~RenderThread() {} + +void RenderThread::initThreadLocals() { + mCacheManager = new CacheManager(*this); +} + +void RenderThread::requireGlContext() {} + +void RenderThread::requireVkContext() {} + +void RenderThread::initGrContextOptions(GrContextOptions& options) {} + +void RenderThread::destroyRenderingContext() {} + +VulkanManager& RenderThread::vulkanManager() { + return *mVkManager; +} + +void RenderThread::dumpGraphicsMemory(int fd, bool includeProfileData) {} + +void RenderThread::getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage) {} + +Readback& RenderThread::readback() { + if (!mReadback) { + mReadback = new Readback(*this); + } + + return *mReadback; +} + +void RenderThread::setGrContext(sk_sp<GrDirectContext> context) {} + +sk_sp<GrDirectContext> RenderThread::requireGrContext() { + return mGrContext; +} + +bool RenderThread::threadLoop() { + if (gOnStartHook) { + gOnStartHook("RenderThread"); + } + initThreadLocals(); + + while (true) { + waitForWork(); + processQueue(); + mCacheManager->onThreadIdle(); + } + + return false; +} + +void RenderThread::postFrameCallback(IFrameCallback* callback) {} + +bool RenderThread::removeFrameCallback(IFrameCallback* callback) { + return false; +} + +void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {} + +sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) { + return nullptr; +} + +bool RenderThread::isCurrent() { + return true; +} + +void RenderThread::preload() {} + +void RenderThread::trimMemory(TrimLevel level) {} + +void RenderThread::trimCaches(CacheTrimLevel level) {} + +} /* namespace renderthread */ +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/platform/host/thread/ThreadBase.h b/libs/hwui/platform/host/thread/ThreadBase.h new file mode 100644 index 000000000000..d709430cc9b6 --- /dev/null +++ b/libs/hwui/platform/host/thread/ThreadBase.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HWUI_THREADBASE_H +#define HWUI_THREADBASE_H + +#include <utils/Thread.h> + +#include <algorithm> + +#include "thread/WorkQueue.h" +#include "utils/Macros.h" + +namespace android::uirenderer { + +class ThreadBase : public Thread { + PREVENT_COPY_AND_ASSIGN(ThreadBase); + +public: + ThreadBase() : Thread(false), mQueue([this]() { mCondition.notify_all(); }, mLock) {} + + WorkQueue& queue() { return mQueue; } + + void requestExit() { Thread::requestExit(); } + + void start(const char* name = "ThreadBase") { Thread::run(name); } + + void join() { Thread::join(); } + + bool isRunning() const { return Thread::isRunning(); } + +protected: + void waitForWork() { + std::unique_lock lock{mLock}; + nsecs_t nextWakeup = mQueue.nextWakeup(lock); + std::chrono::nanoseconds duration = std::chrono::nanoseconds::max(); + if (nextWakeup < std::numeric_limits<nsecs_t>::max()) { + int timeout = nextWakeup - WorkQueue::clock::now(); + if (timeout < 0) timeout = 0; + duration = std::chrono::nanoseconds(timeout); + } + mCondition.wait_for(lock, duration); + } + + void processQueue() { mQueue.process(); } + + virtual bool threadLoop() override { + while (!exitPending()) { + waitForWork(); + processQueue(); + } + return false; + } + +private: + WorkQueue mQueue; + std::mutex mLock; + std::condition_variable mCondition; +}; + +} // namespace android::uirenderer + +#endif // HWUI_THREADBASE_H diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h index 22ae59e5137b..493c943079ab 100644 --- a/libs/hwui/private/hwui/WebViewFunctor.h +++ b/libs/hwui/private/hwui/WebViewFunctor.h @@ -17,15 +17,7 @@ #ifndef FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H #define FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H -#ifdef __ANDROID__ // Layoutlib does not support surface control #include <android/surface_control.h> -#else -// To avoid ifdefs around overlay implementation all over the place we typedef these to void *. They -// won't be used. -typedef void* ASurfaceControl; -typedef void* ASurfaceTransaction; -#endif - #include <cutils/compiler.h> #include <private/hwui/DrawGlInfo.h> #include <private/hwui/DrawVkInfo.h> diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 623ee4e6c27e..a024aeb285f9 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -17,11 +17,12 @@ #include "RenderThread.h" #include <GrContextOptions.h> -#include <include/gpu/ganesh/gl/GrGLDirectContext.h> #include <android-base/properties.h> #include <dlfcn.h> #include <gl/GrGLInterface.h> #include <gui/TraceUtils.h> +#include <include/gpu/ganesh/gl/GrGLDirectContext.h> +#include <private/android/choreographer.h> #include <sys/resource.h> #include <ui/FatVector.h> #include <utils/Condition.h> diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 79e57de9d66f..045d26f1d329 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -20,10 +20,7 @@ #include <GrDirectContext.h> #include <SkBitmap.h> #include <cutils/compiler.h> -#include <private/android/choreographer.h> #include <surface_control_private.h> -#include <thread/ThreadBase.h> -#include <utils/Looper.h> #include <utils/Thread.h> #include <memory> diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index f84107e8792c..f9dc5fac7e21 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -41,6 +41,8 @@ namespace android { namespace { +static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer(); + const ui::Transform kIdentityTransform; } // namespace @@ -224,7 +226,7 @@ void PointerController::setPresentation(Presentation presentation) { mLocked.presentation = presentation; - if (input_flags::enable_pointer_choreographer()) { + if (ENABLE_POINTER_CHOREOGRAPHER) { // When pointer choreographer is enabled, the presentation mode is only set once when the // PointerController is constructed, before the display viewport is provided. // TODO(b/293587049): Clean up the PointerController interface after pointer choreographer diff --git a/media/java/android/media/FadeManagerConfiguration.java b/media/java/android/media/FadeManagerConfiguration.java index 4f1a8ee5e728..e6ec2c330340 100644 --- a/media/java/android/media/FadeManagerConfiguration.java +++ b/media/java/android/media/FadeManagerConfiguration.java @@ -21,6 +21,7 @@ import static android.media.audiopolicy.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURA import android.annotation.DurationMillisLong; import android.annotation.FlaggedApi; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -274,7 +275,7 @@ public final class FadeManagerConfiguration implements Parcelable { * @throws IllegalArgumentException if the usage is invalid * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED} */ - @DurationMillisLong + @IntRange(from = 0) @DurationMillisLong public long getFadeOutDurationForUsage(@AudioAttributes.AttributeUsage int usage) { ensureFadingIsEnabled(); validateUsage(usage); @@ -290,7 +291,7 @@ public final class FadeManagerConfiguration implements Parcelable { * @throws IllegalArgumentException if the usage is invalid * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED} */ - @DurationMillisLong + @IntRange(from = 0) @DurationMillisLong public long getFadeInDurationForUsage(@AudioAttributes.AttributeUsage int usage) { ensureFadingIsEnabled(); validateUsage(usage); @@ -345,7 +346,7 @@ public final class FadeManagerConfiguration implements Parcelable { * @throws NullPointerException if the audio attributes is {@code null} * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED} */ - @DurationMillisLong + @IntRange(from = 0) @DurationMillisLong public long getFadeOutDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes) { ensureFadingIsEnabled(); return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper( @@ -361,7 +362,7 @@ public final class FadeManagerConfiguration implements Parcelable { * @throws NullPointerException if the audio attributes is {@code null} * @throws IllegalStateException if the fade state is set to {@link #FADE_STATE_DISABLED} */ - @DurationMillisLong + @IntRange(from = 0) @DurationMillisLong public long getFadeInDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes) { ensureFadingIsEnabled(); return getDurationForVolumeShaperConfig(getVolumeShaperConfigFromWrapper( @@ -428,7 +429,7 @@ public final class FadeManagerConfiguration implements Parcelable { * * @return delay in milliseconds */ - @DurationMillisLong + @IntRange(from = 0) @DurationMillisLong public long getFadeInDelayForOffenders() { return mFadeInDelayForOffendersMillis; } @@ -517,14 +518,14 @@ public final class FadeManagerConfiguration implements Parcelable { /** * Returns the default fade out duration (in milliseconds) */ - public static @DurationMillisLong long getDefaultFadeOutDurationMillis() { + public static @IntRange(from = 1) @DurationMillisLong long getDefaultFadeOutDurationMillis() { return DEFAULT_FADE_OUT_DURATION_MS; } /** * Returns the default fade in duration (in milliseconds) */ - public static @DurationMillisLong long getDefaultFadeInDurationMillis() { + public static @IntRange(from = 1) @DurationMillisLong long getDefaultFadeInDurationMillis() { return DEFAULT_FADE_IN_DURATION_MS; } @@ -820,8 +821,8 @@ public final class FadeManagerConfiguration implements Parcelable { * @param fadeOutDurationMillis duration in milliseconds used for fading out * @param fadeInDurationMills duration in milliseconds used for fading in */ - public Builder(@DurationMillisLong long fadeOutDurationMillis, - @DurationMillisLong long fadeInDurationMills) { + public Builder(@IntRange(from = 1) @DurationMillisLong long fadeOutDurationMillis, + @IntRange(from = 1) @DurationMillisLong long fadeInDurationMills) { mFadeOutDurationMillis = fadeOutDurationMillis; mFadeInDurationMillis = fadeInDurationMills; } @@ -939,7 +940,7 @@ public final class FadeManagerConfiguration implements Parcelable { */ @NonNull public Builder setFadeOutDurationForUsage(@AudioAttributes.AttributeUsage int usage, - @DurationMillisLong long fadeOutDurationMillis) { + @IntRange(from = 0) @DurationMillisLong long fadeOutDurationMillis) { validateUsage(usage); VolumeShaper.Configuration fadeOutVShaperConfig = createVolShaperConfigForDuration(fadeOutDurationMillis, /* isFadeIn= */ false); @@ -970,7 +971,7 @@ public final class FadeManagerConfiguration implements Parcelable { */ @NonNull public Builder setFadeInDurationForUsage(@AudioAttributes.AttributeUsage int usage, - @DurationMillisLong long fadeInDurationMillis) { + @IntRange(from = 0) @DurationMillisLong long fadeInDurationMillis) { validateUsage(usage); VolumeShaper.Configuration fadeInVShaperConfig = createVolShaperConfigForDuration(fadeInDurationMillis, /* isFadeIn= */ true); @@ -1055,7 +1056,7 @@ public final class FadeManagerConfiguration implements Parcelable { @NonNull public Builder setFadeOutDurationForAudioAttributes( @NonNull AudioAttributes audioAttributes, - @DurationMillisLong long fadeOutDurationMillis) { + @IntRange(from = 0) @DurationMillisLong long fadeOutDurationMillis) { Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null"); VolumeShaper.Configuration fadeOutVShaperConfig = createVolShaperConfigForDuration(fadeOutDurationMillis, /* isFadeIn= */ false); @@ -1087,7 +1088,7 @@ public final class FadeManagerConfiguration implements Parcelable { */ @NonNull public Builder setFadeInDurationForAudioAttributes(@NonNull AudioAttributes audioAttributes, - @DurationMillisLong long fadeInDurationMillis) { + @IntRange(from = 0) @DurationMillisLong long fadeInDurationMillis) { Objects.requireNonNull(audioAttributes, "Audio attribute cannot be null"); VolumeShaper.Configuration fadeInVShaperConfig = createVolShaperConfigForDuration(fadeInDurationMillis, /* isFadeIn= */ true); @@ -1336,7 +1337,8 @@ public final class FadeManagerConfiguration implements Parcelable { * @see #getFadeInDelayForOffenders() */ @NonNull - public Builder setFadeInDelayForOffenders(@DurationMillisLong long delayMillis) { + public Builder setFadeInDelayForOffenders( + @IntRange(from = 0) @DurationMillisLong long delayMillis) { Preconditions.checkArgument(delayMillis >= 0, "Delay cannot be negative"); mFadeInDelayForOffendersMillis = delayMillis; return this; diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index d1453975f801..ed543e67fdf1 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -519,7 +519,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand @Override public void stopPlayback(int mode) { - mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_STOP_PLAYBACK, mode)); + mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_STOP_PLAYBACK, mode)); } @Override diff --git a/nfc/api/current.txt b/nfc/api/current.txt index 7b53ca6ea7e9..0fb7c95e3680 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -204,7 +204,7 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForAid(android.content.ComponentName, String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, String); method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>); - method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String); + method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean); method public boolean removeAidsForService(android.content.ComponentName, String); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index 65d0625f251e..64f7fa44c12f 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -32,7 +32,7 @@ interface INfcCardEmulation boolean setDefaultForNextTap(int userHandle, in ComponentName service); boolean setDefaultToObserveModeForService(int userId, in android.content.ComponentName service, boolean enable); boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup); - boolean registerPollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter); + boolean registerPollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter, boolean autoTransact); boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement); boolean unsetOffHostForService(int userHandle, in ComponentName service); AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category); diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java index 5242a7d32930..e62e37bd4ca0 100644 --- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -176,11 +176,25 @@ public final class ApduServiceInfo implements Parcelable { List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid, String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled) { + this(info, onHost, description, staticAidGroups, dynamicAidGroups, + requiresUnlock, requiresScreenOn, bannerResource, uid, + settingsActivityName, offHost, staticOffHost, isEnabled, + new HashMap<String, Boolean>()); + } + + /** + * @hide + */ + public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, + List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, + boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid, + String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled, + HashMap<String, Boolean> autoTransact) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); this.mDynamicAidGroups = new HashMap<String, AidGroup>(); - this.mAutoTransact = new HashMap<String, Boolean>(); + this.mAutoTransact = autoTransact; this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; this.mOnHost = onHost; @@ -196,7 +210,6 @@ public final class ApduServiceInfo implements Parcelable { this.mUid = uid; this.mSettingsActivityName = settingsActivityName; this.mCategoryOtherServiceEnabled = isEnabled; - } /** @@ -668,31 +681,15 @@ public final class ApduServiceInfo implements Parcelable { /** * Add a Polling Loop Filter. Custom NFC polling frames that match this filter will be - * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this or - * {@link ApduServiceInfo#addPollingLoopFilterToAutoTransact(String)} multiple times will - * cause the value to be overwritten each time. + * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this + * multiple times will cause the value to be overwritten each time. * @param pollingLoopFilter the polling loop filter to add, must be a valide hexadecimal string */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public void addPollingLoopFilter(@NonNull String pollingLoopFilter) { - mAutoTransact.put(pollingLoopFilter.toUpperCase(Locale.ROOT), false); - - } + public void addPollingLoopFilter(@NonNull String pollingLoopFilter, + boolean autoTransact) { + mAutoTransact.put(pollingLoopFilter, autoTransact); - /** - * Add a Polling Loop Filter. Custom NFC polling frames that match this filter will cause the - * device to exit observe mode, just as if - * {@link android.nfc.NfcAdapter#setObserveModeEnabled(boolean)} had been called with true, - * allowing transactions to proceed. The matching frame will also be delivered to - * {@link HostApduService#processPollingFrames(List)}. Adding a key with this or - * {@link ApduServiceInfo#addPollingLoopFilter(String)} multiple times will - * cause the value to be overwritten each time. - * - * @param pollingLoopFilter the polling loop filter to add, must be a valide hexadecimal string - */ - @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public void addPollingLoopFilterToAutoTransact(@NonNull String pollingLoopFilter) { - mAutoTransact.put(pollingLoopFilter.toUpperCase(Locale.ROOT), true); } /** @@ -857,6 +854,8 @@ public final class ApduServiceInfo implements Parcelable { dest.writeString(mSettingsActivityName); dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0); + dest.writeInt(mAutoTransact.size()); + dest.writeMap(mAutoTransact); }; @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @@ -885,10 +884,15 @@ public final class ApduServiceInfo implements Parcelable { int uid = source.readInt(); String settingsActivityName = source.readString(); boolean isEnabled = source.readInt() != 0; + int autoTransactSize = source.readInt(); + HashMap<String, Boolean> autoTransact = + new HashMap<String, Boolean>(autoTransactSize); + source.readMap(autoTransact, getClass().getClassLoader(), + String.class, Boolean.class); return new ApduServiceInfo(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, settingsActivityName, offHostName, staticOffHostName, - isEnabled); + isEnabled, autoTransact); } @Override diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index e681a8568300..47ddd9de224f 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -42,6 +42,7 @@ import android.provider.Settings.SettingNotFoundException; import android.util.Log; import java.util.HashMap; +import java.util.HexFormat; import java.util.List; import java.util.regex.Pattern; @@ -59,7 +60,6 @@ import java.util.regex.Pattern; */ public final class CardEmulation { private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?"); - private static final Pattern PLF_PATTERN = Pattern.compile("[0-9A-Fa-f]{1,32}"); static final String TAG = "CardEmulation"; @@ -360,21 +360,28 @@ public final class CardEmulation { } /** - * Register a polling loop filter (PLF) for a HostApduService. The PLF can be sequence of an - * even number of hexadecimal numbers (0-9, A-F or a-f). When non-standard polling loop frame - * matches this sequence exactly, it may be delivered to - * {@link HostApduService#processPollingFrames(List)} if this service is currently - * preferred or there are no other services registered for this filter. + * Register a polling loop filter (PLF) for a HostApduService and indicate whether it should + * auto-transact or not. The PLF can be sequence of an + * even number of at least 2 hexadecimal numbers (0-9, A-F or a-f), representing a series of + * bytes. When non-standard polling loop frame matches this sequence exactly, it may be + * delivered to {@link HostApduService#processPollingFrames(List)}. If auto-transact is set to + * true, then observe mode will also be disabled. if this service is currently preferred or + * there are no other services registered for this filter. * @param service The HostApduService to register the filter for * @param pollingLoopFilter The filter to register + * @param autoTransact true to have the NFC stack automatically disable observe mode and allow + * transactions to proceed when this filter matches, false otherwise * @return true if the filter was registered, false otherwise + * @throws IllegalArgumentException if the passed in string doesn't parse to at least one byte */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) public boolean registerPollingLoopFilterForService(@NonNull ComponentName service, - @NonNull String pollingLoopFilter) { + @NonNull String pollingLoopFilter, boolean autoTransact) { + pollingLoopFilter = validatePollingLoopFilter(pollingLoopFilter); + try { return sService.registerPollingLoopFilterForService(mContext.getUser().getIdentifier(), - service, pollingLoopFilter); + service, pollingLoopFilter, autoTransact); } catch (RemoteException e) { // Try one more time recoverService(); @@ -384,7 +391,8 @@ public final class CardEmulation { } try { return sService.registerPollingLoopFilterForService( - mContext.getUser().getIdentifier(), service, pollingLoopFilter); + mContext.getUser().getIdentifier(), service, + pollingLoopFilter, autoTransact); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; @@ -979,15 +987,14 @@ public final class CardEmulation { * @hide */ @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) - public static boolean isValidPollingLoopFilter(@NonNull String pollingLoopFilter) { + public static @NonNull String validatePollingLoopFilter(@NonNull String pollingLoopFilter) { // Verify hex characters - if (!PLF_PATTERN.matcher(pollingLoopFilter).matches()) { - Log.e(TAG, "Polling Loop Filter " + pollingLoopFilter - + " is not a valid Polling Loop Filter."); - return false; + byte[] plfBytes = HexFormat.of().parseHex(pollingLoopFilter); + if (plfBytes.length == 0) { + throw new IllegalArgumentException( + "Polling loop filter must contain at least one byte."); } - - return true; + return HexFormat.of().withUpperCase().formatHex(plfBytes); } /** diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java index eccf6047b90c..72f67d93383b 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java @@ -494,6 +494,10 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{ } private void onUserCanceled(@NonNull Context context, @NonNull Intent intent) { + if (!isIntentValid(intent)) { + loge("Ignoring onUserCanceled called with invalid intent."); + return; + } int capability = intent.getIntExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY, SlicePurchaseController.PREMIUM_CAPABILITY_INVALID); logd("onUserCanceled: " + TelephonyManager.convertPremiumCapabilityToString(capability)); diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java index 3c8ef6ed0550..8989aab61f1b 100644 --- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java +++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java @@ -262,10 +262,10 @@ public class SlicePurchaseBroadcastReceiverTest { @Test public void testNotificationCanceled() { + displayPerformanceBoostNotification(); + // send ACTION_NOTIFICATION_CANCELED doReturn("com.android.phone.slice.action.NOTIFICATION_CANCELED").when(mIntent).getAction(); - doReturn(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY).when(mIntent).getIntExtra( - eq(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY), anyInt()); mSlicePurchaseBroadcastReceiver.onReceive(mContext, mIntent); // verify notification was canceled @@ -276,7 +276,7 @@ public class SlicePurchaseBroadcastReceiverTest { } @Test - public void testNotificationTimeout() throws Exception { + public void testNotificationTimeout() { displayPerformanceBoostNotification(); // send ACTION_SLICE_PURCHASE_APP_RESPONSE_TIMEOUT @@ -353,7 +353,7 @@ public class SlicePurchaseBroadcastReceiverTest { verify(mNotificationManager, never()).notifyAsUser( eq(SlicePurchaseBroadcastReceiver.PERFORMANCE_BOOST_NOTIFICATION_TAG), eq(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY), - any(), + any(Notification.class), eq(UserHandle.ALL)); verify(mNotificationShownIntent, never()).send(); diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml index d910f2fc9904..bc3ad0615ada 100644 --- a/packages/CompanionDeviceManager/res/values-nb/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml @@ -72,6 +72,6 @@ <string name="permission_storage_summary" msgid="3918240895519506417"></string> <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Strøm apper og andre systemfunksjoner fra telefonen"</string> <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Se en liste over tilgjengelige enheter, og kontroller hvilken enhet som strømmer eller caster lyd eller video fra andre apper"</string> - <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string> - <string name="device_type" product="tablet" msgid="5038791954983067774">"nettbrett"</string> + <string name="device_type" product="default" msgid="8268703872070046263">"telefonen"</string> + <string name="device_type" product="tablet" msgid="5038791954983067774">"nettbrettet"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index 88f1204641ff..0af108052137 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -59,8 +59,10 @@ <style name="VendorHelperBackButton" parent="@android:style/Widget.Material.Button.Borderless.Colored"> - <item name="android:layout_width">70dp</item> + <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">48dp</item> + <item name="android:layout_marginStart">12dp</item> + <item name="android:layout_marginEnd">12dp</item> <item name="android:textAllCaps">false</item> <item name="android:textSize">14sp</item> <item name="android:textColor">@android:color/system_neutral1_900</item> diff --git a/packages/CredentialManager/res/values/colors.xml b/packages/CredentialManager/res/values/colors.xml index 7cb1d01972b7..b4d2eeb3bd0f 100644 --- a/packages/CredentialManager/res/values/colors.xml +++ b/packages/CredentialManager/res/values/colors.xml @@ -22,4 +22,7 @@ <color name="dropdown_container">#F3F3FA</color> <color name="sign_in_options_container">#DADADA</color> <color name="sign_in_options_icon_color">#1B1B1B</color> + + <!-- These colors are used for Inline Suggestions. --> + <color name="inline_background">#FFFFFF</color> </resources>
\ No newline at end of file diff --git a/packages/CredentialManager/res/values/dimens.xml b/packages/CredentialManager/res/values/dimens.xml index b47a4dc2b76f..350920b23c69 100644 --- a/packages/CredentialManager/res/values/dimens.xml +++ b/packages/CredentialManager/res/values/dimens.xml @@ -28,4 +28,6 @@ <dimen name="dropdown_layout_horizontal_margin">24dp</dimen> <integer name="autofill_max_visible_datasets">5</integer> <dimen name="dropdown_touch_target_min_height">48dp</dimen> + <dimen name="horizontal_chip_padding">8dp</dimen> + <dimen name="vertical_chip_padding">6dp</dimen> </resources>
\ No newline at end of file diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt index 121f207122a0..0f1721790295 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt @@ -40,6 +40,7 @@ import android.service.autofill.Field import android.service.autofill.FillCallback import android.service.autofill.FillRequest import android.service.autofill.FillResponse +import android.service.autofill.Flags import android.service.autofill.InlinePresentation import android.service.autofill.Presentations import android.service.autofill.SaveCallback @@ -56,6 +57,7 @@ import androidx.credentials.provider.CustomCredentialEntry import androidx.credentials.provider.PasswordCredentialEntry import androidx.credentials.provider.PublicKeyCredentialEntry import com.android.credentialmanager.GetFlowUtils +import com.android.credentialmanager.common.ui.InlinePresentationsFactory import com.android.credentialmanager.common.ui.RemoteViewsFactory import com.android.credentialmanager.getflow.ProviderDisplayInfo import com.android.credentialmanager.getflow.toProviderDisplayInfo @@ -250,7 +252,7 @@ class CredentialAutofillService : AutofillService() { maxInlineItemCount = maxInlineItemCount.coerceAtMost(inlineMaxSuggestedCount) val lastDropdownDatasetIndex = Settings.Global.getInt(this.contentResolver, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, - (maxDropdownDisplayLimit - 1)).coerceAtMost(totalEntryCount - 1) + (maxDropdownDisplayLimit - 1)).coerceAtMost(totalEntryCount) var i = 0 var datasetAdded = false @@ -293,8 +295,12 @@ class CredentialAutofillService : AutofillService() { } else { inlinePresentationSpecs[inlinePresentationSpecsCount - 1] } - inlinePresentation = createInlinePresentation(primaryEntry, pendingIntent, icon, - spec!!, duplicateDisplayNamesForPasskeys) + if (spec != null) { + inlinePresentation = createInlinePresentation(primaryEntry, pendingIntent, icon, + InlinePresentationsFactory.modifyInlinePresentationSpec + (this@CredentialAutofillService, spec), + duplicateDisplayNamesForPasskeys) + } } var dropdownPresentation: RemoteViews? = null if (i < lastDropdownDatasetIndex) { @@ -479,18 +485,28 @@ class CredentialAutofillService : AutofillService() { val autofillIdToCredentialEntries: MutableMap<AutofillId, ArrayList<Entry>> = mutableMapOf() credentialEntryList.forEach entryLoop@{ credentialEntry -> - val autofillId: AutofillId? = credentialEntry - .frameworkExtrasIntent - ?.getParcelableExtra( - CredentialProviderService.EXTRA_AUTOFILL_ID, - AutofillId::class.java) - if (autofillId == null) { - Log.e(TAG, "AutofillId is missing from credential entry. Credential" + - " Integration might be disabled.") - return@entryLoop - } - autofillIdToCredentialEntries.getOrPut(autofillId) { ArrayList() } - .add(credentialEntry) + val intent = credentialEntry.frameworkExtrasIntent + intent?.getParcelableExtra( + CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST, + android.service.credentials.GetCredentialRequest::class.java) + ?.credentialOptions + ?.forEach { credentialOption -> + credentialOption.candidateQueryData.getParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId::class.java) + ?.forEach { autofillId -> + intent.putExtra( + CredentialProviderService.EXTRA_AUTOFILL_ID, + autofillId) + val entry = Entry( + credentialEntry.key, + credentialEntry.subkey, + credentialEntry.slice, + intent) + autofillIdToCredentialEntries + .getOrPut(autofillId) { ArrayList() } + .add(entry) + } + } } return autofillIdToCredentialEntries } @@ -573,23 +589,31 @@ class CredentialAutofillService : AutofillService() { cmRequests: MutableList<CredentialOption>, responseClientState: Bundle ) { + val traversedViewNodes: MutableSet<AutofillId> = mutableSetOf() + val credentialOptionsFromHints: MutableMap<String, CredentialOption> = mutableMapOf() val windowNodes: List<AssistStructure.WindowNode> = structure.run { (0 until windowNodeCount).map { getWindowNodeAt(it) } } windowNodes.forEach { windowNode: AssistStructure.WindowNode -> - traverseNodeForRequest(windowNode.rootViewNode, cmRequests, responseClientState) + traverseNodeForRequest( + windowNode.rootViewNode, cmRequests, responseClientState, traversedViewNodes, + credentialOptionsFromHints) } } private fun traverseNodeForRequest( viewNode: AssistStructure.ViewNode, cmRequests: MutableList<CredentialOption>, - responseClientState: Bundle + responseClientState: Bundle, + traversedViewNodes: MutableSet<AutofillId>, + credentialOptionsFromHints: MutableMap<String, CredentialOption> ) { viewNode.autofillId?.let { - cmRequests.addAll(getCredentialOptionsFromViewNode(viewNode, it, responseClientState)) + cmRequests.addAll(getCredentialOptionsFromViewNode(viewNode, it, responseClientState, + traversedViewNodes, credentialOptionsFromHints)) + traversedViewNodes.add(it) } val children: List<AssistStructure.ViewNode> = @@ -598,22 +622,37 @@ class CredentialAutofillService : AutofillService() { } children.forEach { childNode: AssistStructure.ViewNode -> - traverseNodeForRequest(childNode, cmRequests, responseClientState) + traverseNodeForRequest(childNode, cmRequests, responseClientState, traversedViewNodes, + credentialOptionsFromHints) } } private fun getCredentialOptionsFromViewNode( viewNode: AssistStructure.ViewNode, autofillId: AutofillId, - responseClientState: Bundle + responseClientState: Bundle, + traversedViewNodes: MutableSet<AutofillId>, + credentialOptionsFromHints: MutableMap<String, CredentialOption> ): MutableList<CredentialOption> { - if (viewNode.credentialManagerRequest != null && - viewNode.credentialManagerCallback != null) { - val options = viewNode.credentialManagerRequest?.getCredentialOptions() - if (options != null) { - return options + val credentialOptions: MutableList<CredentialOption> = mutableListOf() + if (Flags.autofillCredmanDevIntegration() && viewNode.credentialManagerRequest != null) { + viewNode.credentialManagerRequest + ?.getCredentialOptions() + ?.forEach { credentialOption -> + credentialOption.candidateQueryData + .getParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId::class.java) + ?.let { associatedAutofillIds -> + // Check whether any of the associated autofill ids have already been + // traversed. If so, skip, to dedupe on duplicate credential options. + if ((traversedViewNodes intersect associatedAutofillIds.toSet()) + .isEmpty()) { + credentialOptions.add(credentialOption) + } + } } } + // TODO(b/325502552): clean up cred option logic in autofill hint val credentialHints: MutableList<String> = mutableListOf() if (viewNode.autofillHints != null) { @@ -627,10 +666,10 @@ class CredentialAutofillService : AutofillService() { } } - val credentialOptions: MutableList<CredentialOption> = mutableListOf() for (credentialHint in credentialHints) { try { - convertJsonToCredentialOption(credentialHint, autofillId) + convertJsonToCredentialOption( + credentialHint, autofillId, credentialOptionsFromHints) .let { credentialOptions.addAll(it) } } catch (e: JSONException) { Log.i(TAG, "Exception while parsing response: " + e.message) @@ -639,10 +678,11 @@ class CredentialAutofillService : AutofillService() { return credentialOptions } - private fun convertJsonToCredentialOption(jsonString: String, autofillId: AutofillId): - List<CredentialOption> { - // TODO(b/302000646) Move this logic to jetpack so that is consistent - // with building the json + private fun convertJsonToCredentialOption( + jsonString: String, + autofillId: AutofillId, + credentialOptionsFromHints: MutableMap<String, CredentialOption> + ): List<CredentialOption> { val credentialOptions: MutableList<CredentialOption> = mutableListOf() val json = JSONObject(jsonString) @@ -650,16 +690,34 @@ class CredentialAutofillService : AutofillService() { val options = jsonGet.getJSONArray(CRED_OPTIONS_KEY) for (i in 0 until options.length()) { val option = options.getJSONObject(i) - val candidateBundle = convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY)) - candidateBundle.putParcelable( + val optionString = option.toString() + credentialOptionsFromHints[optionString] + ?.let { credentialOption -> + // if the current credential option was seen before, add the current + // viewNode to the credential option, but do not add it to the option list + // again. This will result in the same result as deduping based on + // traversed viewNode. + credentialOption.candidateQueryData.getParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId::class.java) + ?.let { + it.add(autofillId) + credentialOption.candidateQueryData.putParcelableArrayList( + CredentialProviderService.EXTRA_AUTOFILL_ID, it) + } + } ?: run { + val candidateBundle = convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY)) + candidateBundle.putParcelableArrayList( CredentialProviderService.EXTRA_AUTOFILL_ID, - autofillId) - credentialOptions.add(CredentialOption( + arrayListOf(autofillId)) + val credentialOption = CredentialOption( option.getString(TYPE_KEY), convertJsonToBundle(option.getJSONObject(REQUEST_DATA_KEY)), candidateBundle, option.getBoolean(SYS_PROVIDER_REQ_KEY), - )) + ) + credentialOptions.add(credentialOption) + credentialOptionsFromHints[optionString] = credentialOption + } } return credentialOptions } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/InlinePresentationFactory.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/InlinePresentationFactory.kt new file mode 100644 index 000000000000..3ebdd204b640 --- /dev/null +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/InlinePresentationFactory.kt @@ -0,0 +1,84 @@ +/* +* Copyright (C) 2024 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +package com.android.credentialmanager.common.ui + + +import android.content.Context +import android.util.Size +import android.widget.inline.InlinePresentationSpec +import androidx.autofill.inline.common.TextViewStyle +import androidx.autofill.inline.common.ViewStyle +import androidx.autofill.inline.UiVersions +import androidx.autofill.inline.UiVersions.Style +import androidx.autofill.inline.v1.InlineSuggestionUi +import androidx.core.content.ContextCompat +import android.util.TypedValue +import android.graphics.Typeface + + +class InlinePresentationsFactory { + companion object { + private const val googleSansMediumFontFamily = "google-sans-medium" + private const val googleSansTextFontFamily = "google-sans-text" + // There is no min width required for now but this is needed for the spec builder + private const val minInlineWidth = 5000 + + + fun modifyInlinePresentationSpec(context: Context, + originalSpec: InlinePresentationSpec): InlinePresentationSpec { + return InlinePresentationSpec.Builder(Size(originalSpec.minSize.width, originalSpec + .minSize.height), + Size(minInlineWidth, originalSpec + .maxSize.height)) + .setStyle(UiVersions.newStylesBuilder().addStyle(getStyle(context)).build()) + .build() + } + + + fun getStyle(context: Context): Style { + val textColorPrimary = ContextCompat.getColor(context, + com.android.credentialmanager.R.color.text_primary) + val textColorSecondary = ContextCompat.getColor(context, + com.android.credentialmanager.R.color.text_secondary) + val textColorBackground = ContextCompat.getColor(context, + com.android.credentialmanager.R.color.inline_background) + val chipHorizontalPadding = context.resources.getDimensionPixelSize(com.android + .credentialmanager.R.dimen.horizontal_chip_padding) + val chipVerticalPadding = context.resources.getDimensionPixelSize(com.android + .credentialmanager.R.dimen.vertical_chip_padding) + return InlineSuggestionUi.newStyleBuilder() + .setChipStyle( + ViewStyle.Builder().setPadding(chipHorizontalPadding, + chipVerticalPadding, + chipHorizontalPadding, chipVerticalPadding).build() + ) + .setTitleStyle( + TextViewStyle.Builder().setTextColor(textColorPrimary).setTextSize + (TypedValue.COMPLEX_UNIT_DIP, 14F) + .setTypeface(googleSansMediumFontFamily, + Typeface.NORMAL).setBackgroundColor(textColorBackground) + .build() + ) + .setSubtitleStyle(TextViewStyle.Builder().setTextColor(textColorSecondary) + .setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12F).setTypeface + (googleSansTextFontFamily, Typeface.NORMAL).setBackgroundColor + (textColorBackground).build()) + .build() + } + } +}
\ No newline at end of file diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml index 05561d79c3d5..158c33ae2035 100644 --- a/packages/FusedLocation/AndroidManifest.xml +++ b/packages/FusedLocation/AndroidManifest.xml @@ -28,6 +28,7 @@ <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <application android:label="@string/app_label" @@ -49,5 +50,17 @@ <meta-data android:name="serviceVersion" android:value="0" /> <meta-data android:name="serviceIsMultiuser" android:value="true" /> </service> + + <!-- GNSS overlay Service that LocationManagerService binds to. + LocationManagerService will bind to the service with the highest + version. --> + <service android:name="com.android.location.gnss.GnssOverlayLocationService" + android:exported="false"> + <intent-filter> + <action android:name="android.location.provider.action.GNSS_PROVIDER" /> + </intent-filter> + <meta-data android:name="serviceVersion" android:value="0" /> + <meta-data android:name="serviceIsMultiuser" android:value="true" /> + </service> </application> </manifest> diff --git a/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationProvider.java b/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationProvider.java new file mode 100644 index 000000000000..c6576e39de99 --- /dev/null +++ b/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationProvider.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.location.gnss; + +import static android.location.provider.ProviderProperties.ACCURACY_FINE; +import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH; + +import android.annotation.Nullable; +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.LocationRequest; +import android.location.provider.LocationProviderBase; +import android.location.provider.ProviderProperties; +import android.location.provider.ProviderRequest; +import android.os.Bundle; +import android.util.SparseArray; + + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ConcurrentUtils; + +import java.util.List; + +/** Basic pass-through GNSS location provider implementation. */ +public class GnssOverlayLocationProvider extends LocationProviderBase { + + private static final String TAG = "GnssOverlay"; + + private static final ProviderProperties PROPERTIES = new ProviderProperties.Builder() + .setHasAltitudeSupport(true) + .setHasSpeedSupport(true) + .setHasBearingSupport(true) + .setPowerUsage(POWER_USAGE_HIGH) + .setAccuracy(ACCURACY_FINE) + .build(); + + @GuardedBy("mPendingFlushes") + private final SparseArray<OnFlushCompleteCallback> mPendingFlushes = new SparseArray<>(); + + private final LocationManager mLocationManager; + + private final GnssLocationListener mGnssLocationListener = new GnssLocationListener(); + + @GuardedBy("mPendingFlushes") + private int mFlushCode = 0; + + /** Location listener for receiving locations from LocationManager. */ + private class GnssLocationListener implements LocationListener { + @Override + public void onLocationChanged(Location location) { + reportLocation(location); + } + + @Override + public void onLocationChanged(List<Location> locations) { + reportLocations(locations); + } + + @Override + public void onFlushComplete(int requestCode) { + OnFlushCompleteCallback flushCompleteCallback; + synchronized (mPendingFlushes) { + flushCompleteCallback = mPendingFlushes.get(requestCode); + mPendingFlushes.remove(requestCode); + } + if (flushCompleteCallback != null) { + flushCompleteCallback.onFlushComplete(); + } + } + } + + public GnssOverlayLocationProvider(Context context) { + super(context, TAG, PROPERTIES); + mLocationManager = context.getSystemService(LocationManager.class); + } + + void start() { + } + + void stop() { + mLocationManager.removeUpdates(mGnssLocationListener); + } + + @Override + public void onSendExtraCommand(String command, @Nullable Bundle extras) { + mLocationManager.sendExtraCommand(LocationManager.GPS_HARDWARE_PROVIDER, command, extras); + } + + @Override + public void onFlush(OnFlushCompleteCallback callback) { + int flushCodeCopy; + synchronized (mPendingFlushes) { + flushCodeCopy = mFlushCode++; + mPendingFlushes.put(flushCodeCopy, callback); + } + mLocationManager.requestFlush( + LocationManager.GPS_HARDWARE_PROVIDER, mGnssLocationListener, flushCodeCopy); + } + + @Override + public void onSetRequest(ProviderRequest request) { + if (request.isActive()) { + mLocationManager.requestLocationUpdates( + LocationManager.GPS_HARDWARE_PROVIDER, + new LocationRequest.Builder(request.getIntervalMillis()) + .setMaxUpdateDelayMillis(request.getMaxUpdateDelayMillis()) + .setLowPower(request.isLowPower()) + .setLocationSettingsIgnored(request.isLocationSettingsIgnored()) + .setWorkSource(request.getWorkSource()) + .setQuality(request.getQuality()) + .build(), + ConcurrentUtils.DIRECT_EXECUTOR, + mGnssLocationListener); + } else { + mLocationManager.removeUpdates(mGnssLocationListener); + } + } +} diff --git a/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationService.java b/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationService.java new file mode 100644 index 000000000000..dd034fec9495 --- /dev/null +++ b/packages/FusedLocation/src/com/android/location/gnss/GnssOverlayLocationService.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.location.gnss; + +import android.annotation.Nullable; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +public class GnssOverlayLocationService extends Service { + + @Nullable private GnssOverlayLocationProvider mProvider; + + @Override + public IBinder onBind(Intent intent) { + if (mProvider == null) { + mProvider = new GnssOverlayLocationProvider(this); + mProvider.start(); + } + + return mProvider.getBinder(); + } + + @Override + public void onDestroy() { + if (mProvider != null) { + mProvider.stop(); + mProvider = null; + } + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + } +} diff --git a/packages/FusedLocation/test/src/com/android/location/gnss/tests/GnssOverlayLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/gnss/tests/GnssOverlayLocationServiceTest.java new file mode 100644 index 000000000000..5b33deb60759 --- /dev/null +++ b/packages/FusedLocation/test/src/com/android/location/gnss/tests/GnssOverlayLocationServiceTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.location.gnss.tests; + +import static android.location.LocationManager.GPS_HARDWARE_PROVIDER; + +import static androidx.test.ext.truth.location.LocationSubject.assertThat; + +import android.content.Context; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.location.LocationRequest; +import android.location.provider.ILocationProvider; +import android.location.provider.ILocationProviderManager; +import android.location.provider.ProviderProperties; +import android.location.provider.ProviderRequest; +import android.os.ParcelFileDescriptor; +import android.os.SystemClock; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.runner.AndroidJUnit4; + +import com.android.location.gnss.GnssOverlayLocationProvider; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Random; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +public class GnssOverlayLocationServiceTest { + + private static final String TAG = "GnssOverlayLocationServiceTest"; + + private static final long TIMEOUT_MS = 5000; + + private Random mRandom; + private LocationManager mLocationManager; + + private ILocationProvider mProvider; + private LocationProviderManagerCapture mManager; + + @Before + public void setUp() throws Exception { + long seed = System.currentTimeMillis(); + Log.i(TAG, "location seed: " + seed); + + Context context = ApplicationProvider.getApplicationContext(); + mRandom = new Random(seed); + mLocationManager = context.getSystemService(LocationManager.class); + + setMockLocation(true); + + mManager = new LocationProviderManagerCapture(); + mProvider = ILocationProvider.Stub.asInterface( + new GnssOverlayLocationProvider(context).getBinder()); + mProvider.setLocationProviderManager(mManager); + + mLocationManager.addTestProvider(GPS_HARDWARE_PROVIDER, + true, + false, + true, + false, + false, + false, + false, + Criteria.POWER_MEDIUM, + Criteria.ACCURACY_FINE); + mLocationManager.setTestProviderEnabled(GPS_HARDWARE_PROVIDER, true); + } + + @After + public void tearDown() throws Exception { + for (String provider : mLocationManager.getAllProviders()) { + mLocationManager.removeTestProvider(provider); + } + + setMockLocation(false); + } + + @Test + public void testGpsRequest() throws Exception { + mProvider.setRequest( + new ProviderRequest.Builder() + .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY) + .setIntervalMillis(1000) + .build()); + + Location location = createLocation(GPS_HARDWARE_PROVIDER, mRandom); + mLocationManager.setTestProviderLocation(GPS_HARDWARE_PROVIDER, location); + + assertThat(mManager.getNextLocation(TIMEOUT_MS)).isEqualTo(location); + } + + private static class LocationProviderManagerCapture extends ILocationProviderManager.Stub { + + private final LinkedBlockingQueue<Location> mLocations; + + private LocationProviderManagerCapture() { + mLocations = new LinkedBlockingQueue<>(); + } + + @Override + public void onInitialize(boolean allowed, ProviderProperties properties, + String attributionTag) {} + + @Override + public void onSetAllowed(boolean allowed) {} + + @Override + public void onSetProperties(ProviderProperties properties) {} + + @Override + public void onReportLocation(Location location) { + mLocations.add(location); + } + + @Override + public void onReportLocations(List<Location> locations) { + mLocations.addAll(locations); + } + + @Override + public void onFlushComplete() {} + + public Location getNextLocation(long timeoutMs) throws InterruptedException { + return mLocations.poll(timeoutMs, TimeUnit.MILLISECONDS); + } + } + + private static final double MIN_LATITUDE = -90D; + private static final double MAX_LATITUDE = 90D; + private static final double MIN_LONGITUDE = -180D; + private static final double MAX_LONGITUDE = 180D; + + private static final float MIN_ACCURACY = 1; + private static final float MAX_ACCURACY = 100; + + private static Location createLocation(String provider, Random random) { + return createLocation(provider, + MIN_LATITUDE + random.nextDouble() * (MAX_LATITUDE - MIN_LATITUDE), + MIN_LONGITUDE + random.nextDouble() * (MAX_LONGITUDE - MIN_LONGITUDE), + MIN_ACCURACY + random.nextFloat() * (MAX_ACCURACY - MIN_ACCURACY)); + } + + private static Location createLocation(String provider, double latitude, double longitude, + float accuracy) { + Location location = new Location(provider); + location.setLatitude(latitude); + location.setLongitude(longitude); + location.setAccuracy(accuracy); + location.setTime(System.currentTimeMillis()); + location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); + return location; + } + + private static void setMockLocation(boolean allowed) throws IOException { + ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand("appops set " + + InstrumentationRegistry.getTargetContext().getPackageName() + + " android:mock_location " + (allowed ? "allow" : "deny")); + try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[32768]; + int count; + try { + while ((count = fis.read(buffer)) != -1) { + os.write(buffer, 0, count); + } + fis.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + Log.e(TAG, new String(os.toByteArray())); + } + } +} diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml index 628b406e281b..531190327165 100644 --- a/packages/PackageInstaller/res/values-fr/strings.xml +++ b/packages/PackageInstaller/res/values-fr/strings.xml @@ -85,7 +85,7 @@ <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Suppression du clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string> <string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"Impossible de désinstaller une application d\'administration de l\'appareil active"</string> <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"Impossible de désinstaller une application d\'administration de l\'appareil active pour <xliff:g id="USERNAME">%1$s</xliff:g>"</string> - <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"Cette application nécessaire pour certains utilisateurs ou profils a été désinstallée pour d\'autres"</string> + <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"Cette application est requise pour certains utilisateurs ou profils et a été désinstallée pour d\'autres"</string> <string name="uninstall_blocked_profile_owner" msgid="6373897407002404848">"Impossible de désinstaller l\'application, car elle est nécessaire pour votre profil."</string> <string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"Impossible désinstaller appli, car elle est requise par administrateur appareil."</string> <string name="manage_device_administrators" msgid="3092696419363842816">"Gérer les applis d\'administration de l\'appareil"</string> diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml index b96593e261d6..332517a775f4 100644 --- a/packages/PackageInstaller/res/values-pt-rBR/strings.xml +++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml @@ -40,7 +40,7 @@ <string name="install_failed_msg" product="tv" msgid="1920009940048975221">"Não foi possível instalar o app <xliff:g id="APP_NAME">%1$s</xliff:g> na sua TV."</string> <string name="install_failed_msg" product="default" msgid="6484461562647915707">"Não foi possível instalar o app <xliff:g id="APP_NAME">%1$s</xliff:g> no seu smartphone."</string> <string name="launch" msgid="3952550563999890101">"Abrir"</string> - <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"Seu administrador não permite a instalação de apps transferidos por download de fontes desconhecidas"</string> + <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"Seu administrador não permite a instalação de apps baixados de fontes desconhecidas"</string> <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Apps desconhecidos não podem ser instalados por este usuário"</string> <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuário não tem permissão para instalar apps"</string> <string name="ok" msgid="7871959885003339302">"OK"</string> diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml index b96593e261d6..332517a775f4 100644 --- a/packages/PackageInstaller/res/values-pt/strings.xml +++ b/packages/PackageInstaller/res/values-pt/strings.xml @@ -40,7 +40,7 @@ <string name="install_failed_msg" product="tv" msgid="1920009940048975221">"Não foi possível instalar o app <xliff:g id="APP_NAME">%1$s</xliff:g> na sua TV."</string> <string name="install_failed_msg" product="default" msgid="6484461562647915707">"Não foi possível instalar o app <xliff:g id="APP_NAME">%1$s</xliff:g> no seu smartphone."</string> <string name="launch" msgid="3952550563999890101">"Abrir"</string> - <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"Seu administrador não permite a instalação de apps transferidos por download de fontes desconhecidas"</string> + <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"Seu administrador não permite a instalação de apps baixados de fontes desconhecidas"</string> <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Apps desconhecidos não podem ser instalados por este usuário"</string> <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuário não tem permissão para instalar apps"</string> <string name="ok" msgid="7871959885003339302">"OK"</string> diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java index 904e1843dd44..cf6aab641fc9 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -403,7 +403,7 @@ public class PackageInstallerActivity extends Activity { resolvedPath = info.getResolvedBaseApkPath(); } if (info == null || !info.isSealed() || resolvedPath == null) { - Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring"); + Log.w(TAG, "Session " + sessionId + " in funky state; ignoring"); finish(); return; } @@ -418,7 +418,7 @@ public class PackageInstallerActivity extends Activity { -1 /* defaultValue */); final SessionInfo info = mInstaller.getSessionInfo(sessionId); if (info == null || !info.isPreApprovalRequested()) { - Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring"); + Log.w(TAG, "Session " + sessionId + " in funky state; ignoring"); finish(); return; } @@ -839,7 +839,9 @@ public class PackageInstallerActivity extends Activity { // work for the multiple user case, i.e. the caller task user and started // Activity user are not the same. To avoid having multiple PIAs in the task, // finish the current PackageInstallerActivity - finish(); + // Because finish() is overridden to set the installation result, we must use + // the original finish() method, or the confirmation dialog fails to appear. + PackageInstallerActivity.super.finish(); } }, 500); diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml index 2bab1b65529b..b6c45b7a23c8 100644 --- a/packages/PrintRecommendationService/res/values/strings.xml +++ b/packages/PrintRecommendationService/res/values/strings.xml @@ -18,7 +18,6 @@ --> <resources> - <string name="plugin_vendor_google_cloud_print">Cloud Print</string> <string name="plugin_vendor_hp">HP</string> <string name="plugin_vendor_lexmark">Lexmark</string> <string name="plugin_vendor_brother">Brother</string> diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java index 5a756fe50209..4ec88830386b 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java @@ -23,7 +23,6 @@ import android.printservice.recommendation.RecommendationInfo; import android.printservice.recommendation.RecommendationService; import android.util.Log; -import com.android.printservice.recommendation.plugin.google.CloudPrintPlugin; import com.android.printservice.recommendation.plugin.hp.HPRecommendationPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig; @@ -77,14 +76,6 @@ public class RecommendationServiceImpl extends RecommendationService } try { - mPlugins.add(new RemotePrintServicePlugin(new CloudPrintPlugin(this), this, - true)); - } catch (Exception e) { - Log.e(LOG_TAG, "Could not initiate " - + getString(R.string.plugin_vendor_google_cloud_print) + " plugin", e); - } - - try { mPlugins.add(new RemotePrintServicePlugin(new HPRecommendationPlugin(this), this, false)); } catch (Exception e) { diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java deleted file mode 100644 index 3029d10d4cf3..000000000000 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.printservice.recommendation.plugin.google; - -import static com.android.printservice.recommendation.util.MDNSUtils.ATTRIBUTE_TY; - -import android.content.Context; -import android.util.ArrayMap; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; - -import com.android.printservice.recommendation.PrintServicePlugin; -import com.android.printservice.recommendation.R; -import com.android.printservice.recommendation.util.MDNSFilteredDiscovery; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Plugin detecting <a href="https://developers.google.com/cloud-print/docs/privet">Google Cloud - * Print</a> printers. - */ -public class CloudPrintPlugin implements PrintServicePlugin { - private static final String LOG_TAG = CloudPrintPlugin.class.getSimpleName(); - private static final boolean DEBUG = false; - - private static final String ATTRIBUTE_TXTVERS = "txtvers"; - private static final String ATTRIBUTE_URL = "url"; - private static final String ATTRIBUTE_TYPE = "type"; - private static final String ATTRIBUTE_ID = "id"; - private static final String ATTRIBUTE_CS = "cs"; - - private static final String TYPE = "printer"; - - private static final String PRIVET_SERVICE = "_privet._tcp"; - - /** The required mDNS service types */ - private static final Set<String> PRINTER_SERVICE_TYPE = Set.of( - PRIVET_SERVICE); // Not checking _printer_._sub - - /** All possible connection states */ - private static final Set<String> POSSIBLE_CONNECTION_STATES = Set.of( - "online", - "offline", - "connecting", - "not-configured"); - - private static final byte SUPPORTED_TXTVERS = '1'; - - /** The mDNS filtered discovery */ - private final MDNSFilteredDiscovery mMDNSFilteredDiscovery; - - /** - * Create a plugin detecting Google Cloud Print printers. - * - * @param context The context the plugin runs in - */ - public CloudPrintPlugin(@NonNull Context context) { - mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPE, - nsdServiceInfo -> { - // The attributes are case insensitive. For faster searching create a clone of - // the map with the attribute-keys all in lower case. - ArrayMap<String, byte[]> caseInsensitiveAttributes = - new ArrayMap<>(nsdServiceInfo.getAttributes().size()); - for (Map.Entry<String, byte[]> entry : nsdServiceInfo.getAttributes() - .entrySet()) { - caseInsensitiveAttributes.put(entry.getKey().toLowerCase(), - entry.getValue()); - } - - if (DEBUG) { - Log.i(LOG_TAG, nsdServiceInfo.getServiceName() + ":"); - Log.i(LOG_TAG, "type: " + nsdServiceInfo.getServiceType()); - Log.i(LOG_TAG, "host: " + nsdServiceInfo.getHost()); - for (Map.Entry<String, byte[]> entry : caseInsensitiveAttributes.entrySet()) { - if (entry.getValue() == null) { - Log.i(LOG_TAG, entry.getKey() + "= null"); - } else { - Log.i(LOG_TAG, entry.getKey() + "=" + new String(entry.getValue(), - StandardCharsets.UTF_8)); - } - } - } - - byte[] txtvers = caseInsensitiveAttributes.get(ATTRIBUTE_TXTVERS); - if (txtvers == null || txtvers.length != 1 || txtvers[0] != SUPPORTED_TXTVERS) { - // The spec requires this to be the first attribute, but at this time we - // lost the order of the attributes - return false; - } - - if (caseInsensitiveAttributes.get(ATTRIBUTE_TY) == null) { - return false; - } - - byte[] url = caseInsensitiveAttributes.get(ATTRIBUTE_URL); - if (url == null || url.length == 0) { - return false; - } - - byte[] type = caseInsensitiveAttributes.get(ATTRIBUTE_TYPE); - if (type == null || !TYPE.equals( - new String(type, StandardCharsets.UTF_8).toLowerCase())) { - return false; - } - - if (caseInsensitiveAttributes.get(ATTRIBUTE_ID) == null) { - return false; - } - - byte[] cs = caseInsensitiveAttributes.get(ATTRIBUTE_CS); - if (cs == null || !POSSIBLE_CONNECTION_STATES.contains( - new String(cs, StandardCharsets.UTF_8).toLowerCase())) { - return false; - } - - InetAddress address = nsdServiceInfo.getHost(); - if (!(address instanceof Inet4Address)) { - // Not checking for link local address - return false; - } - - return true; - }); - } - - @Override - @NonNull public CharSequence getPackageName() { - return "com.google.android.apps.cloudprint"; - } - - @Override - public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception { - mMDNSFilteredDiscovery.start(callback); - } - - @Override - @StringRes public int getName() { - return R.string.plugin_vendor_google_cloud_print; - } - - @Override - public void stop() throws Exception { - mMDNSFilteredDiscovery.stop(); - } -} diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts index 463e9be391b6..335725cdad5e 100644 --- a/packages/SettingsLib/Spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/build.gradle.kts @@ -29,7 +29,7 @@ val androidTop: String = File(rootDir, "../../../../..").canonicalPath allprojects { extra["androidTop"] = androidTop - extra["jetpackComposeVersion"] = "1.7.0-alpha02" + extra["jetpackComposeVersion"] = "1.7.0-alpha03" } subprojects { diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt index e1853675d6d4..761bb7918afd 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt @@ -27,7 +27,7 @@ import com.android.settingslib.spa.gallery.chart.ChartPageProvider import com.android.settingslib.spa.gallery.dialog.DialogMainPageProvider import com.android.settingslib.spa.gallery.dialog.NavDialogProvider import com.android.settingslib.spa.gallery.editor.EditorMainPageProvider -import com.android.settingslib.spa.gallery.editor.SettingsExposedDropdownMenuBoxPageProvider +import com.android.settingslib.spa.gallery.editor.SettingsDropdownBoxPageProvider import com.android.settingslib.spa.gallery.editor.SettingsDropdownCheckBoxProvider import com.android.settingslib.spa.gallery.home.HomePageProvider import com.android.settingslib.spa.gallery.itemList.ItemListPageProvider @@ -99,7 +99,7 @@ class GallerySpaEnvironment(context: Context) : SpaEnvironment(context) { OperateListPageProvider, EditorMainPageProvider, SettingsOutlinedTextFieldPageProvider, - SettingsExposedDropdownMenuBoxPageProvider, + SettingsDropdownBoxPageProvider, SettingsDropdownCheckBoxProvider, SettingsTextFieldPasswordPageProvider, SearchScaffoldPageProvider, diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/EditorMainPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/EditorMainPageProvider.kt index 9f2158a13f25..c511542f265a 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/EditorMainPageProvider.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/EditorMainPageProvider.kt @@ -35,7 +35,7 @@ object EditorMainPageProvider : SettingsPageProvider { return listOf( SettingsOutlinedTextFieldPageProvider.buildInjectEntry().setLink(fromPage = owner) .build(), - SettingsExposedDropdownMenuBoxPageProvider.buildInjectEntry().setLink(fromPage = owner) + SettingsDropdownBoxPageProvider.buildInjectEntry().setLink(fromPage = owner) .build(), SettingsDropdownCheckBoxProvider.buildInjectEntry().setLink(fromPage = owner) .build(), diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/SettingsExposedDropdownMenuBoxPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/SettingsDropdownBoxPageProvider.kt index 5ffbe8ba8a26..2ebb5f5eba27 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/SettingsExposedDropdownMenuBoxPageProvider.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/editor/SettingsDropdownBoxPageProvider.kt @@ -28,16 +28,15 @@ import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.createSettingsPage import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.theme.SettingsTheme -import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox +import com.android.settingslib.spa.widget.editor.SettingsDropdownBox import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.scaffold.RegularScaffold -private const val TITLE = "Sample SettingsExposedDropdownMenuBox" +private const val TITLE = "Sample SettingsDropdownBox" -object SettingsExposedDropdownMenuBoxPageProvider : SettingsPageProvider { - override val name = "SettingsExposedDropdownMenuBox" - private const val exposedDropdownMenuBoxLabel = "ExposedDropdownMenuBoxLabel" +object SettingsDropdownBoxPageProvider : SettingsPageProvider { + override val name = "SettingsDropdownBox" override fun getTitle(arguments: Bundle?): String { return TITLE @@ -45,18 +44,44 @@ object SettingsExposedDropdownMenuBoxPageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { - var selectedItem by remember { mutableIntStateOf(-1) } - val options = listOf("item1", "item2", "item3") RegularScaffold(title = TITLE) { - SettingsExposedDropdownMenuBox( - label = exposedDropdownMenuBoxLabel, - options = options, - selectedOptionIndex = selectedItem, - enabled = true, - onselectedOptionTextChange = { selectedItem = it }) + Regular() + NotEnabled() + Empty() } } + @Composable + private fun Regular() { + var selectedItem by remember { mutableIntStateOf(-1) } + SettingsDropdownBox( + label = "SettingsDropdownBox", + options = listOf("item1", "item2", "item3"), + selectedOptionIndex = selectedItem, + ) { selectedItem = it } + } + + @Composable + private fun NotEnabled() { + var selectedItem by remember { mutableIntStateOf(0) } + SettingsDropdownBox( + label = "Not enabled", + options = listOf("item1", "item2", "item3"), + enabled = false, + selectedOptionIndex = selectedItem, + ) { selectedItem = it } + } + + @Composable + private fun Empty() { + var selectedItem by remember { mutableIntStateOf(-1) } + SettingsDropdownBox( + label = "Empty", + options = emptyList(), + selectedOptionIndex = selectedItem, + ) { selectedItem = it } + } + fun buildInjectEntry(): SettingsEntryBuilder { return SettingsEntryBuilder.createInject(owner = createSettingsPage()) .setUiLayoutFn { @@ -70,8 +95,8 @@ object SettingsExposedDropdownMenuBoxPageProvider : SettingsPageProvider { @Preview(showBackground = true) @Composable -private fun SettingsExposedDropdownMenuBoxPagePreview() { +private fun SettingsDropdownBoxPagePreview() { SettingsTheme { - SettingsExposedDropdownMenuBoxPageProvider.Page(null) + SettingsDropdownBoxPageProvider.Page(null) } } diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml index fe378c27523c..609a82e79827 100644 --- a/packages/SettingsLib/Spa/gradle/libs.versions.toml +++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml @@ -16,7 +16,7 @@ [versions] agp = "8.2.2" -compose-compiler = "1.5.9" +compose-compiler = "1.5.10" dexmaker-mockito = "2.28.3" jvm = "17" kotlin = "1.9.22" diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_slider.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_slider.png Binary files differindex a038779b0e79..e1f5c742dab7 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_slider.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_slider.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_slider.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_slider.png Binary files differindex 03db688f6799..928e9268292b 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_slider.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_slider.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_slider.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_slider.png Binary files differindex 1345c379cfb0..05213688b0a8 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_slider.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_slider.png diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts index 2259bd74d56e..a193a2f9970d 100644 --- a/packages/SettingsLib/Spa/spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/spa/build.gradle.kts @@ -57,7 +57,7 @@ dependencies { api("androidx.slice:slice-builders:1.1.0-alpha02") api("androidx.slice:slice-core:1.1.0-alpha02") api("androidx.slice:slice-view:1.1.0-alpha02") - api("androidx.compose.material3:material3:1.2.0") + api("androidx.compose.material3:material3:1.3.0-alpha01") api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion") api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion") api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion") diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuBox.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt index f6692a356899..679c562ac92d 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuBox.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package com.android.settingslib.spa.widget.editor import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuDefaults @@ -31,80 +30,58 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension -import com.android.settingslib.spa.framework.theme.SettingsTheme -@Composable +internal interface DropdownTextBoxScope { + fun dismiss() +} + @OptIn(ExperimentalMaterial3Api::class) -fun SettingsExposedDropdownMenuBox( +@Composable +internal fun DropdownTextBox( label: String, - options: List<String>, - selectedOptionIndex: Int, - enabled: Boolean, - onselectedOptionTextChange: (Int) -> Unit, + text: String, + enabled: Boolean = true, + errorMessage: String? = null, + content: @Composable DropdownTextBoxScope.() -> Unit, ) { var expanded by remember { mutableStateOf(false) } + val scope = remember { + object : DropdownTextBoxScope { + override fun dismiss() { + expanded = false + } + } + } ExposedDropdownMenuBox( expanded = expanded, - onExpandedChange = { expanded = it }, + onExpandedChange = { expanded = enabled && it }, modifier = Modifier - .width(350.dp) - .padding(SettingsDimension.menuFieldPadding), + .padding(SettingsDimension.menuFieldPadding) + .width(Width), ) { OutlinedTextField( // The `menuAnchor` modifier must be passed to the text field for correctness. modifier = Modifier .menuAnchor() .fillMaxWidth(), - value = options.getOrElse(selectedOptionIndex) { "" }, + value = text, onValueChange = { }, label = { Text(text = label) }, - trailingIcon = { - ExposedDropdownMenuDefaults.TrailingIcon( - expanded = expanded - ) - }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, singleLine = true, readOnly = true, - enabled = enabled + enabled = enabled, + isError = errorMessage != null, + supportingText = errorMessage?.let { { Text(text = it) } }, ) - if (options.isNotEmpty()) { - ExposedDropdownMenu( - expanded = expanded, - modifier = Modifier - .fillMaxWidth(), - onDismissRequest = { expanded = false }, - ) { - options.forEach { option -> - DropdownMenuItem( - text = { Text(option) }, - onClick = { - onselectedOptionTextChange(options.indexOf(option)) - expanded = false - }, - contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, - ) - } - } - } + ExposedDropdownMenu( + expanded = expanded, + modifier = Modifier.width(Width), + onDismissRequest = { expanded = false }, + ) { scope.content() } } } -@Preview -@Composable -private fun SettingsExposedDropdownMenuBoxsPreview() { - val item1 = "item1" - val item2 = "item2" - val item3 = "item3" - val options = listOf(item1, item2, item3) - SettingsTheme { - SettingsExposedDropdownMenuBox( - label = "ExposedDropdownMenuBoxLabel", - options = options, - selectedOptionIndex = 0, - enabled = true, - onselectedOptionTextChange = {}) - } -}
\ No newline at end of file +private val Width = 310.dp diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBox.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBox.kt new file mode 100644 index 000000000000..ff141c2b383c --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBox.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.widget.editor + +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import com.android.settingslib.spa.framework.theme.SettingsTheme + +@Composable +@OptIn(ExperimentalMaterial3Api::class) +fun SettingsDropdownBox( + label: String, + options: List<String>, + selectedOptionIndex: Int, + enabled: Boolean = true, + onSelectedOptionChange: (Int) -> Unit, +) { + DropdownTextBox( + label = label, + text = options.getOrElse(selectedOptionIndex) { "" }, + enabled = enabled && options.isNotEmpty(), + ) { + options.forEachIndexed { index, option -> + DropdownMenuItem( + text = { Text(option) }, + onClick = { + dismiss() + onSelectedOptionChange(index) + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, + ) + } + } +} + +@Preview +@Composable +private fun SettingsDropdownBoxPreview() { + val item1 = "item1" + val item2 = "item2" + val item3 = "item3" + val options = listOf(item1, item2, item3) + SettingsTheme { + SettingsDropdownBox( + label = "ExposedDropdownMenuBoxLabel", + options = options, + selectedOptionIndex = 0, + enabled = true, + ) {} + } +} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownCheckBox.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownCheckBox.kt index 57963e6eaa40..0e7e49960be1 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownCheckBox.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsDropdownCheckBox.kt @@ -19,28 +19,15 @@ package com.android.settingslib.spa.widget.editor import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material3.Checkbox -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExposedDropdownMenuBox -import androidx.compose.material3.ExposedDropdownMenuDefaults -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.onSizeChanged -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled import com.android.settingslib.spa.framework.theme.SettingsTheme @@ -68,7 +55,6 @@ data class SettingsDropdownCheckOption( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsDropdownCheckBox( label: String, @@ -78,43 +64,18 @@ fun SettingsDropdownCheckBox( errorMessage: String? = null, onSelectedStateChange: () -> Unit = {}, ) { - var dropDownWidth by remember { mutableIntStateOf(0) } - var expanded by remember { mutableStateOf(false) } - val changeable = enabled && options.changeable - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = changeable && it }, - modifier = Modifier - .width(350.dp) - .padding(SettingsDimension.textFieldPadding) - .onSizeChanged { dropDownWidth = it.width }, + DropdownTextBox( + label = label, + text = getDisplayText(options) ?: emptyText, + enabled = enabled && options.changeable, + errorMessage = errorMessage, ) { - OutlinedTextField( - // The `menuAnchor` modifier must be passed to the text field for correctness. - modifier = Modifier - .menuAnchor() - .fillMaxWidth(), - value = getDisplayText(options) ?: emptyText, - onValueChange = {}, - label = { Text(text = label) }, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) }, - readOnly = true, - enabled = changeable, - isError = errorMessage != null, - supportingText = errorMessage?.let { { Text(text = it) } }, - ) - ExposedDropdownMenu( - expanded = expanded, - modifier = Modifier.width(with(LocalDensity.current) { dropDownWidth.toDp() }), - onDismissRequest = { expanded = false }, - ) { - for (option in options) { - CheckboxItem(option) { - option.onClick() - if (option.changeable) { - checkboxItemOnClick(options, option) - onSelectedStateChange() - } + for (option in options) { + CheckboxItem(option) { + option.onClick() + if (option.changeable) { + checkboxItemOnClick(options, option) + onSelectedStateChange() } } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/RadioPreferences.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/RadioPreferences.kt new file mode 100644 index 000000000000..8300ce855988 --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/RadioPreferences.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.widget.preference + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material3.RadioButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.Role +import com.android.settingslib.spa.framework.theme.SettingsDimension +import com.android.settingslib.spa.widget.ui.CategoryTitle +import com.android.settingslib.spa.widget.ui.SettingsListItem + +@Composable +fun RadioPreferences(model: ListPreferenceModel) { + CategoryTitle(title = model.title) + Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) + Column(modifier = Modifier.selectableGroup()) { + for (option in model.options) { + Radio2(option, model.selectedId.intValue, model.enabled()) { + model.onIdSelected(it) + } + } + } +} + +@Composable +fun Radio2( + option: ListPreferenceOption, + selectedId: Int, + enabled: Boolean, + onIdSelected: (id: Int) -> Unit, +) { + val selected = option.id == selectedId + Row( + modifier = Modifier + .fillMaxWidth() + .selectable( + selected = selected, + enabled = enabled, + onClick = { onIdSelected(option.id) }, + role = Role.RadioButton, + ) + .padding(SettingsDimension.dialogItemPadding), + verticalAlignment = Alignment.CenterVertically, + ) { + RadioButton(selected = selected, onClick = null, enabled = enabled) + Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) + SettingsListItem(text = option.text, enabled = enabled) + } +}
\ No newline at end of file diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt index 4f6196648634..56534f41c3df 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt @@ -180,7 +180,7 @@ private class TopAppBarColors( * @param colorTransitionFraction a `0.0` to `1.0` value that represents a color transition * percentage */ - @Composable + @Stable fun containerColor(colorTransitionFraction: Float): Color { return lerp( containerColor, @@ -519,7 +519,7 @@ private fun TopAppBarLayout( 0 } - val layoutHeight = if (heightPx.isNaN()) 0 else heightPx.roundToInt() + val layoutHeight = if (heightPx > 0) heightPx.roundToInt() else 0 layout(constraints.maxWidth, layoutHeight) { // Navigation icon diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt index b4a6a0d00720..a59b95a60879 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt @@ -66,6 +66,19 @@ fun SettingsDialogItem(text: String, enabled: Boolean = true) { } @Composable +fun SettingsListItem(text: String, enabled: Boolean = true) { + Text( + text = text, + modifier = Modifier + .alphaForEnabled(enabled) + .padding(vertical = SettingsDimension.paddingTiny), + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.titleMedium, + overflow = TextOverflow.Ellipsis, + ) +} + +@Composable fun SettingsBody( body: String, maxLines: Int = Int.MAX_VALUE, diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBoxTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBoxTest.kt new file mode 100644 index 000000000000..c34742461774 --- /dev/null +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsDropdownBoxTest.kt @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.widget.editor + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SettingsDropdownBoxTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun dropdownMenuBox_displayed() { + composeTestRule.setContent { + var selectedItem by remember { mutableStateOf(0) } + SettingsDropdownBox( + label = LABEL, + options = options, + selectedOptionIndex = selectedItem, + ) { selectedItem = it } + } + + composeTestRule.onNodeWithText(LABEL).assertIsDisplayed() + } + + @Test + fun dropdownMenuBox_enabled_expanded() { + composeTestRule.setContent { + var selectedItem by remember { mutableIntStateOf(0) } + SettingsDropdownBox( + label = LABEL, + options = options, + selectedOptionIndex = selectedItem + ) { selectedItem = it } + } + composeTestRule.onNodeWithText(ITEM2).assertDoesNotExist() + + composeTestRule.onNodeWithText(LABEL).performClick() + + composeTestRule.onNodeWithText(ITEM2).assertIsDisplayed() + } + + @Test + fun dropdownMenuBox_notEnabled_notExpanded() { + composeTestRule.setContent { + var selectedItem by remember { mutableIntStateOf(0) } + SettingsDropdownBox( + label = LABEL, + options = options, + enabled = false, + selectedOptionIndex = selectedItem + ) { selectedItem = it } + } + composeTestRule.onNodeWithText(ITEM2).assertDoesNotExist() + + composeTestRule.onNodeWithText(LABEL).performClick() + + composeTestRule.onNodeWithText(ITEM2).assertDoesNotExist() + } + + @Test + fun dropdownMenuBox_valueChanged() { + composeTestRule.setContent { + var selectedItem by remember { mutableIntStateOf(0) } + SettingsDropdownBox( + label = LABEL, + options = options, + selectedOptionIndex = selectedItem + ) { selectedItem = it } + } + composeTestRule.onNodeWithText(ITEM2).assertDoesNotExist() + + composeTestRule.onNodeWithText(LABEL).performClick() + composeTestRule.onNodeWithText(ITEM2).performClick() + + composeTestRule.onNodeWithText(ITEM2).assertIsDisplayed() + } + private companion object { + const val LABEL = "Label" + const val ITEM2 = "item2" + val options = listOf("item1", ITEM2, "item3") + } +} diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuBoxTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuBoxTest.kt deleted file mode 100644 index bc67e4c61ea5..000000000000 --- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuBoxTest.kt +++ /dev/null @@ -1,95 +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.settingslib.spa.widget.editor - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performClick -import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class SettingsExposedDropdownMenuBoxTest { - @get:Rule - val composeTestRule = createComposeRule() - private val options = listOf("item1", "item2", "item3") - private val item2 = "item2" - private val exposedDropdownMenuBoxLabel = "ExposedDropdownMenuBoxLabel" - - @Test - fun exposedDropdownMenuBoxs_displayed() { - composeTestRule.setContent { - var selectedItem by remember { mutableStateOf(0) } - SettingsExposedDropdownMenuBox( - label = exposedDropdownMenuBoxLabel, - options = options, - selectedOptionIndex = selectedItem, - enabled = true, - onselectedOptionTextChange = { selectedItem = it }) - } - composeTestRule.onNodeWithText(exposedDropdownMenuBoxLabel, substring = true) - .assertIsDisplayed() - } - - @Test - fun exposedDropdownMenuBoxs_expanded() { - composeTestRule.setContent { - var selectedItem by remember { mutableIntStateOf(0) } - SettingsExposedDropdownMenuBox( - label = exposedDropdownMenuBoxLabel, - options = options, - selectedOptionIndex = selectedItem, - enabled = true, - onselectedOptionTextChange = { selectedItem = it }) - } - composeTestRule.onNodeWithText(item2, substring = true) - .assertDoesNotExist() - composeTestRule.onNodeWithText(exposedDropdownMenuBoxLabel, substring = true) - .performClick() - composeTestRule.onNodeWithText(item2, substring = true) - .assertIsDisplayed() - } - - @Test - fun exposedDropdownMenuBoxs_valueChanged() { - composeTestRule.setContent { - var selectedItem by remember { mutableIntStateOf(0) } - SettingsExposedDropdownMenuBox( - label = exposedDropdownMenuBoxLabel, - options = options, - selectedOptionIndex = selectedItem, - enabled = true, - onselectedOptionTextChange = { selectedItem = it }) - } - composeTestRule.onNodeWithText(item2, substring = true) - .assertDoesNotExist() - composeTestRule.onNodeWithText(exposedDropdownMenuBoxLabel, substring = true) - .performClick() - composeTestRule.onNodeWithText(item2, substring = true) - .performClick() - composeTestRule.onNodeWithText(item2, substring = true) - .assertIsDisplayed() - } -}
\ No newline at end of file diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/RadioPreferencesTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/RadioPreferencesTest.kt new file mode 100644 index 000000000000..2f98b02b8dd5 --- /dev/null +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/RadioPreferencesTest.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.widget.preference + +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.assertIsNotSelected +import androidx.compose.ui.test.assertIsSelectable +import androidx.compose.ui.test.assertIsSelected +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RadioPreferencesTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun title_displayed() { + composeTestRule.setContent { + RadioPreferences(remember { + object : ListPreferenceModel { + override val title = TITLE + override val options = emptyList<ListPreferenceOption>() + override val selectedId = mutableIntStateOf(0) + override val onIdSelected: (Int) -> Unit = {} + } + }) + } + composeTestRule.onNodeWithText(TITLE).assertIsDisplayed() + } + + @Test + fun item_displayed() { + val selectedId = mutableIntStateOf(1) + composeTestRule.setContent { + RadioPreferences(remember { + object : ListPreferenceModel { + override val title = TITLE + override val options = listOf( + ListPreferenceOption(id = 1, text = "A"), + ListPreferenceOption(id = 2, text = "B"), + ) + override val selectedId = selectedId + override val onIdSelected = { id: Int -> selectedId.intValue = id } + } + }) + } + composeTestRule.onNodeWithText("A").assertIsDisplayed() + composeTestRule.onNodeWithText("B").assertIsDisplayed() + } + + @Test + fun item_selectable() { + val selectedId = mutableIntStateOf(1) + val enabledState = mutableStateOf(true) + composeTestRule.setContent { + RadioPreferences(remember { + object : ListPreferenceModel { + override val title = TITLE + override val enabled = { enabledState.value } + override val options = listOf( + ListPreferenceOption(id = 1, text = "A"), + ListPreferenceOption(id = 2, text = "B"), + ) + override val selectedId = selectedId + override val onIdSelected = { id: Int -> selectedId.intValue = id } + } + }) + } + composeTestRule.onNodeWithText("A").assertIsSelectable() + composeTestRule.onNodeWithText("B").assertIsSelectable() + } + + @Test + fun item_single_selected() { + val selectedId = mutableIntStateOf(1) + val enabledState = mutableStateOf(true) + composeTestRule.setContent { + RadioPreferences(remember { + object : ListPreferenceModel { + override val title = TITLE + override val enabled = { enabledState.value } + override val options = listOf( + ListPreferenceOption(id = 1, text = "A"), + ListPreferenceOption(id = 2, text = "B"), + ) + override val selectedId = selectedId + override val onIdSelected = { id: Int -> selectedId.intValue = id } + } + }) + } + composeTestRule.onNodeWithText("B").assertIsSelectable() + composeTestRule.onNodeWithText("B").performClick() + composeTestRule.onNodeWithText("B").assertIsSelected() + composeTestRule.onNodeWithText("A").assertIsNotSelected() + composeTestRule.onNodeWithText("A").performClick() + composeTestRule.onNodeWithText("A").assertIsSelected() + composeTestRule.onNodeWithText("B").assertIsNotSelected() + } + + @Test + fun select_itemDisabled() { + val selectedId = mutableIntStateOf(1) + val enabledState = mutableStateOf(true) + composeTestRule.setContent { + RadioPreferences(remember { + object : ListPreferenceModel { + override val title = TITLE + override val enabled = { enabledState.value } + override val options = listOf( + ListPreferenceOption(id = 1, text = "A"), + ListPreferenceOption(id = 2, text = "B"), + ) + override val selectedId = selectedId + override val onIdSelected = { id: Int -> selectedId.intValue = id } + } + }) + } + enabledState.value = false + composeTestRule.onNodeWithText("A").assertIsDisplayed().assertIsNotEnabled() + composeTestRule.onNodeWithText("B").assertIsDisplayed().assertIsNotEnabled() + } + + private companion object { + const val TITLE = "Title" + } +}
\ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_le_audio_sharing.xml b/packages/SettingsLib/res/drawable/ic_bt_le_audio_sharing.xml new file mode 100644 index 000000000000..618677389ce1 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_le_audio_sharing.xml @@ -0,0 +1,87 @@ +<!-- + ~ 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:autoMirrored="true" + android:height="24dp" + android:width="24dp" + android:viewportHeight="24" + android:viewportWidth="24" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#000000" + android:pathData="M16.984,24H7.279L12.131,15.508L16.984,24ZM10.481,22.144H13.781L12.131,19.257L10.481,22.144Z"/> + <path + android:fillColor="#000000" + android:pathData="M12.131,14.295C13.471,14.295 14.558,13.209 14.558,11.869C14.558,10.529 13.471,9.442 12.131,9.442C10.791,9.442 9.705,10.529 9.705,11.869C9.705,13.209 10.791,14.295 12.131,14.295Z"/> + <path + android:fillColor="#000000" + android:pathData="M4.573,21.368C4.052,20.943 3.967,20.179 4.379,19.657C4.804,19.136 5.568,19.051 6.09,19.463C6.611,19.876 6.696,20.64 6.284,21.174C6.041,21.465 5.689,21.623 5.338,21.623C5.071,21.623 4.804,21.538 4.573,21.368Z"/> + <path + android:fillColor="#000000" + android:pathData="M17.991,21.162C17.579,20.628 17.663,19.876 18.185,19.451C18.707,19.039 19.471,19.124 19.896,19.646C20.308,20.167 20.223,20.931 19.702,21.344C19.471,21.526 19.204,21.611 18.949,21.611C18.586,21.611 18.234,21.453 17.991,21.162Z"/> + <path + android:fillColor="#000000" + android:pathData="M1.213,17.145C0.91,16.551 1.165,15.823 1.771,15.532C2.378,15.241 3.093,15.495 3.397,16.09C3.688,16.697 3.433,17.424 2.827,17.715C2.657,17.8 2.475,17.837 2.305,17.837C1.844,17.837 1.419,17.582 1.213,17.145Z"/> + <path + android:fillColor="#000000" + android:pathData="M21.449,17.691C20.842,17.4 20.588,16.684 20.879,16.077C21.17,15.471 21.898,15.216 22.504,15.507C23.099,15.798 23.354,16.526 23.062,17.133C22.856,17.557 22.419,17.812 21.971,17.812C21.789,17.812 21.619,17.776 21.449,17.691Z"/> + <path + android:fillColor="#000000" + android:pathData="M0,11.892C0,11.225 0.546,10.679 1.213,10.679C1.88,10.679 2.426,11.212 2.426,11.892C2.426,12.559 1.88,13.105 1.213,13.105C0.546,13.105 0,12.559 0,11.892Z"/> + <path + android:fillColor="#000000" + android:pathData="M21.837,11.869C21.837,11.857 21.837,11.845 21.837,11.833C21.824,11.153 22.37,10.62 23.05,10.607C23.717,10.607 24.251,11.153 24.263,11.821C24.263,11.833 24.263,11.845 24.263,11.845C24.263,11.857 24.263,11.869 24.263,11.869C24.263,12.536 23.717,13.082 23.05,13.082C22.382,13.082 21.837,12.536 21.837,11.869Z"/> + <path + android:fillColor="#000000" + android:pathData="M1.759,8.242C1.152,7.963 0.898,7.235 1.189,6.628C1.48,6.022 2.196,5.767 2.802,6.058C3.409,6.349 3.664,7.077 3.372,7.684C3.166,8.108 2.729,8.363 2.281,8.363C2.099,8.363 1.929,8.327 1.759,8.242Z"/> + <path + android:fillColor="#000000" + android:pathData="M20.866,7.622C20.563,7.028 20.818,6.3 21.424,6.009C22.019,5.706 22.747,5.96 23.038,6.567C23.038,6.567 23.038,6.567 23.05,6.567C23.341,7.161 23.087,7.889 22.48,8.181C22.31,8.265 22.128,8.302 21.958,8.302C21.509,8.302 21.073,8.059 20.866,7.622Z"/> + <path + android:fillColor="#000000" + android:pathData="M4.355,4.104C3.931,3.582 4.016,2.818 4.537,2.406C5.071,1.981 5.823,2.066 6.248,2.588C6.672,3.109 6.588,3.874 6.066,4.298C5.835,4.48 5.569,4.565 5.302,4.565C4.95,4.565 4.598,4.407 4.355,4.104Z"/> + <path + android:fillColor="#000000" + android:pathData="M18.161,4.262C17.627,3.838 17.542,3.073 17.955,2.552C18.379,2.03 19.132,1.945 19.666,2.358C20.187,2.77 20.272,3.534 19.86,4.068C19.617,4.359 19.265,4.517 18.913,4.517C18.646,4.517 18.379,4.432 18.161,4.262Z"/> + <path + android:fillColor="#000000" + android:pathData="M8.492,1.497C8.334,0.854 8.747,0.199 9.402,0.041C10.057,-0.105 10.7,0.308 10.858,0.963C11.003,1.606 10.591,2.261 9.948,2.407C9.851,2.431 9.754,2.443 9.669,2.443C9.123,2.443 8.613,2.067 8.492,1.497Z"/> + <path + android:fillColor="#000000" + android:pathData="M14.267,2.395C13.599,2.249 13.199,1.606 13.345,0.951C13.49,0.296 14.133,-0.116 14.788,0.029C15.443,0.175 15.856,0.83 15.71,1.485C15.589,2.043 15.08,2.431 14.534,2.431C14.437,2.431 14.352,2.419 14.267,2.395Z"/> + <path + android:fillColor="#000000" + android:pathData="M7,17.037C6.527,16.564 6.527,15.8 7,15.326C7.473,14.841 8.237,14.841 8.71,15.314C9.196,15.787 9.196,16.552 8.723,17.025C8.48,17.267 8.177,17.389 7.861,17.389C7.546,17.389 7.242,17.267 7,17.037Z"/> + <path + android:fillColor="#000000" + android:pathData="M15.565,17.012C15.092,16.539 15.092,15.762 15.565,15.289C16.038,14.816 16.814,14.816 17.288,15.289C17.761,15.762 17.761,16.539 17.288,17.012C17.045,17.243 16.742,17.364 16.426,17.364C16.111,17.364 15.807,17.243 15.565,17.012Z"/> + <path + android:fillColor="#000000" + android:pathData="M4.853,11.917C4.853,11.237 5.386,10.691 6.054,10.691C6.721,10.691 7.279,11.225 7.279,11.892C7.279,12.56 6.745,13.106 6.078,13.118C5.398,13.118 4.853,12.584 4.853,11.917Z"/> + <path + android:fillColor="#000000" + android:pathData="M16.984,11.868C16.984,11.856 16.984,11.844 16.984,11.832C16.984,11.832 16.984,11.82 16.984,11.807C16.972,11.14 17.506,10.582 18.185,10.582C18.852,10.57 19.398,11.116 19.41,11.783C19.41,11.795 19.41,11.82 19.41,11.832C19.41,11.844 19.41,11.856 19.41,11.868C19.41,12.535 18.865,13.081 18.197,13.081C17.53,13.081 16.984,12.535 16.984,11.868Z"/> + <path + android:fillColor="#000000" + android:pathData="M6.952,8.471C6.478,7.997 6.478,7.233 6.952,6.76C6.952,6.76 6.952,6.76 6.939,6.76C7.413,6.275 8.189,6.275 8.662,6.748C9.135,7.221 9.147,7.985 8.674,8.458C8.432,8.701 8.116,8.822 7.813,8.822C7.497,8.822 7.194,8.701 6.952,8.471Z"/> + <path + android:fillColor="#000000" + android:pathData="M15.529,8.399C15.043,7.938 15.043,7.161 15.504,6.688C15.977,6.203 16.742,6.203 17.227,6.664C17.7,7.137 17.712,7.901 17.239,8.387C17.009,8.629 16.693,8.751 16.378,8.751C16.075,8.751 15.759,8.629 15.529,8.399Z"/> + <path + android:fillColor="#000000" + android:pathData="M10.87,5.815C10.858,5.148 11.392,4.59 12.071,4.59C12.738,4.578 13.284,5.124 13.284,5.791C13.296,6.458 12.762,7.016 12.083,7.016C11.416,7.016 10.87,6.483 10.87,5.815Z"/> +</vector> diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 3729b00b8baf..8d3582a736fe 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses word geoptimeer"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses word geoptimeer"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 87916340f739..f6931ad30353 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g> ይቀራል"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት እንዲተባ ተደርጓል"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት እንዲተባ ተደርጓል"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index e0b56074dba2..92dc69ca54fe 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"يتبقّى <xliff:g id="TIME">%1$s</xliff:g> حتى اكتمال شحن البطارية."</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم تحسين الشحن"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم تحسين الشحن"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 9a4268a84e38..48d3df4621f3 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index a217406fb0f0..e27a40cdf7b1 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tam şarj edilənədək <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj optimallaşdırılıb"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj optimallaşdırılıb"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 76429ca3fe20..dd48b70bd8ed 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do kraja punjenja"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizovano"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizovano"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index e6bb3061b269..48247a01034f 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарадка аптымізавана"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарадка аптымізавана"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 9f406ee2a8fd..035b1dd19c5a 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зареждането е оптимизирано"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зареждането е оптимизирано"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 1262c1efa804..9a2f88c1eb1f 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং অপ্টিমাইজ করা হয়েছে"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং অপ্টিমাইজ করা হয়েছে"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index d806e6213c05..01662dd8bed6 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizirano"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizirano"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 3e7a5a1ebb1f..61898881baac 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: càrrega optimitzada"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g>: càrrega optimitzada"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 23b0c823104c..ec104b4a95e4 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabití"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimalizované nabíjení"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimalizované nabíjení"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 972073fd6ada..b92fc040cd30 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladning er optimeret"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladning optimeres"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 52cdba17c924..debdb1e6b361 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Voll in <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laden wird optimiert"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laden wird optimiert"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string> @@ -599,7 +600,7 @@ <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kannst dieses Gerät zusammen mit anderen nutzen, indem du weitere Nutzer erstellst. Jeder erhält einen eigenen Bereich, in dem er Apps, den Hintergrund usw. personalisieren kann. Außerdem lassen sich Geräteeinstellungen wie WLAN ändern, die sich auf alle Nutzer auswirken.\n\nWenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren. Einstellungen und Dienste für die Bedienungshilfen werden möglicherweise nicht auf den neuen Nutzer übertragen."</string> <string name="user_add_user_message_short" msgid="3295959985795716166">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string> <string name="user_grant_admin_title" msgid="5157031020083343984">"Diesen Nutzer als Administrator festlegen?"</string> - <string name="user_grant_admin_message" msgid="1673791931033486709">"Im Gegensatz zu anderen Nutzern haben Administratoren besondere Berechtigungen. Ein Administrator kann alle Nutzer verwalten, dieses Gerät aktualisieren oder zurücksetzen, Einstellungen ändern, alle installierten Apps sehen und anderen Administratorberechtigungen gewähren oder diese widerrufen."</string> + <string name="user_grant_admin_message" msgid="1673791931033486709">"Im Gegensatz zu anderen Nutzern haben Administratoren besondere Berechtigungen. Ein Administrator kann alle Nutzer verwalten, dieses Gerät aktualisieren oder zurücksetzen, Einstellungen ändern, alle installierten Apps sehen und anderen Administratorberechtigungen gewähren oder diese widerrufen."</string> <string name="user_grant_admin_button" msgid="5441486731331725756">"Als Administrator festlegen"</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Nutzer jetzt einrichten?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Die Person muss Zugang zum Gerät haben und bereit sein, ihren Bereich einzurichten."</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 3c93c6218121..6cf05597feb2 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για πλήρη φόρτιση"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση βελτιστοποιήθηκε"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση βελτιστοποιήθηκε"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 199f30f1f8e4..b2c5718c999f 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 6a118876e75e..21fff5e1e3be 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -478,7 +478,7 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> + <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 199f30f1f8e4..b2c5718c999f 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 199f30f1f8e4..b2c5718c999f 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index f4bdc120bc49..25e2779c4f5c 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -478,7 +478,7 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string> + <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 6d2bd55d0612..d0ba34c4c8f4 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 0e689f88d921..77049e0c6837 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> hasta la carga completa"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index e4d192575b8b..6a3c208efa59 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Täislaadimiseks kulub <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on optimeeritud"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on optimeeritud"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index d4346f7ab3dc..64e372ac182a 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatzeko modu optimizatua"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatzeko modu optimizatua"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 68f3d3d74957..01d4618a319e 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ کامل باقی مانده است"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ بهینه شده است"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ بهینه شده است"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index dc23e14b6190..529bed536f1f 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus optimoitu"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus optimoitu"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 78f0ded467af..ea2383425dc9 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la recharge complète"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index d3bd3d1b3b42..dbf107acf46e 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Chargée à 100 %% dans <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index fef8f803b03b..233c9d4d6a1b 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> (carga optimizada)"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> (carga optimizada)"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index f664a9873c10..762ed28a4317 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 31b14ce31247..6a0e3e0f706f 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को ऑप्टिमाइज़ किया गया"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को ऑप्टिमाइज़ किया गया"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 98e2f0197263..f019936ed9c4 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do napunjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje se optimizira"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje se optimizira"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 4f9452ad1716..d3d2960b22b9 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizált töltés"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizált töltés"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index ad4ca1b3ec72..4c14ae12fbb1 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումն օպտիմալացված է"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումն օպտիմալացված է"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 449540a1a059..1379ecfc99b7 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sampai penuh"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dioptimalkan"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dioptimalkan"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index f1ce78b6dc35..e48d063d9d3c 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> fram að fullri hleðslu"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Hleðsla fínstillt"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Hleðsla fínstillt"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 60455a169063..b33551440684 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> alla ricarica completa"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica ottimizzata"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica ottimizzata"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 18fec960877c..a559cc616105 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה עברה אופטימיזציה"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה עברה אופטימיזציה"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 7a4eaf133b48..a7be818b3f85 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電が最適化されています"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電が最適化されています"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 7c4d736be98f..eb06df31e676 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ოპტიმიზირებულია"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ოპტიმიზირებულია"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index df0474fdedc0..86da0a4c0179 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Толық зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды."</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: толық зарядталуға <xliff:g id="TIME">%2$s</xliff:g> қалды"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау оңтайландырылды"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау оңтайландырылды."</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядтау"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index ce1738ddfcce..848e9049df33 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានបង្កើនប្រសិទ្ធភាពនៃការសាក"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានបង្កើនប្រសិទ្ធភាពនៃការសាក"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងសាកថ្ម"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 203cc6d04ea4..d13019c28fe5 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> - ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index d52d71692f0b..3c8ad01f0f02 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> 후 충전 완료"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 최적화됨"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 최적화됨"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 20c476ad473a..cec61bbdf764 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталат"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — Кубаттоо жакшыртылды"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> — Кубаттоо жакшыртылды"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index e0b7e8442478..420925920982 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ຍັງເຫຼືອອີກ <xliff:g id="TIME">%1$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກຖືກປັບໃຫ້ເໝາະສົມແລ້ວ"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກຖືກປັບໃຫ້ເໝາະສົມແລ້ວ"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index de2f1c34801c..cb0069d66e42 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Liko <xliff:g id="TIME">%1$s</xliff:g>, kol bus visiškai įkrauta"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas optimizuotas"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas optimizuotas"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 8f09595c86eb..db566881f016 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde optimizēta"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde optimizēta"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 0e03472d6703..6738e2068ae1 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 5a1bcff7a8c0..a5c38bc22d1f 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"പൂർണ്ണമാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 81636be50a8e..c03c89f68b18 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Дүүрэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэх явцыг оновчилсон"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэх явцыг оновчилсон"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index a85042dd2042..bbe782da8f85 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -52,7 +52,7 @@ <string name="wifi_remembered" msgid="3266709779723179188">"सेव्ह केले"</string> <string name="wifi_disconnected" msgid="7054450256284661757">"डिस्कनेक्ट केले"</string> <string name="wifi_disabled_generic" msgid="2651916945380294607">"अक्षम"</string> - <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉंफिगरेशन अयशस्वी"</string> + <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्फिगरेशन अयशस्वी"</string> <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"कनेक्ट करू शकत नाही"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'शी कनेक्ट करू शकत नाही"</string> @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहेत"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग ऑप्टिमाइझ केले"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग ऑप्टिमाइझ केले"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 8292b6947b64..3da4f08be11b 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sebelum penuh"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dioptimumkan"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dioptimumkan"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 656cf599a37b..f4b669773aeb 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုသည်"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 6023c848ada8..fbdc9e33f576 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fulladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladingen er optimalisert"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladingen er optimalisert"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index e488df723478..245a31f9fcae 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूरा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> लाग्ने छ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै छ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै छ"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 92fb1052bb30..4eafb5740e05 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Vol over <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen geoptimaliseerd"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen geoptimaliseerd"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 621d8e10f828..5a8bed43faf7 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index b32c07737ab8..df1fea17f645 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index aa84b69f0b6e..e9f9da8e095b 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zoptymalizowane"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zoptymalizowane"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 49607a44c55a..4ee1cbd417ef 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 485c29601782..eae5cc965f7f 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até à carga máxima"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: carregamento otimizado"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g>: carregamento otimizado"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 49607a44c55a..4ee1cbd417ef 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 5fa52bbe08d6..91261d49f15e 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> până la finalizare"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcare optimizată"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcare optimizată"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 3a404882a57d..87b2a938fa31 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядка оптимизирована"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядка оптимизирована"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index bf55a30c67f5..72bd507a5175 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"සම්පූර්ණ වීමට <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරියි"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය ප්රශස්ත කර ඇත"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය ප්රශස්ත කර ඇත"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 045a7243bf26..dd8be3a1d7a0 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je optimalizované"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je optimalizované"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 1b13195fc7f6..eefb119eca02 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Še <xliff:g id="TIME">%1$s</xliff:g> do napolnjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje je optimizirano"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje je optimizirano"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index d14772b259cb..e847c515bb7e 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> derisa të mbushet"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi u optimizua"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi u optimizua"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Karikim i shpejtë"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index fe8c11f58024..ed0e9a6ea975 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до краја пуњења"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – пуњење је оптимизовано"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – пуњење је оптимизовано"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 7606b41e1d2f..b4de50408daa 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kvar tills fulladdat"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har optimerats"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har optimerats"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 4c1816dd2c52..40725c92d6ea 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hali ya kuchaji imeboreshwa"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hali ya kuchaji imeboreshwa"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 1248205442d5..2fe243aee324 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"முழுவதும் சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜிங் மேம்படுத்தப்பட்டது"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜிங் மேம்படுத்தப்பட்டது"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 440ed0fdb618..43f2b835bc44 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 68a7db63622e..8395a5185363 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ปรับการชาร์จให้เหมาะสมแล้ว"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - ปรับการชาร์จให้เหมาะสมแล้ว"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index f5430ee852cf..a337bd8a69f2 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> na lang bago mapuno"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-optimize ang pag-charge"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-optimize ang pag-charge"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 3cd35963ebea..43e18edca594 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tamamen şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 080765c9edcb..984bb7978294 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджання оптимізовано"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджання оптимізовано"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index fd22bb69df49..bc8a46748d8b 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"مکمل چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string> <string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ کو بہتر بنایا گیا"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ کو بہتر بنایا گیا"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index cdf5c282ad2b..a655dc0f0304 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Toʻlishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash optimallashtirildi"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash optimallashtirildi"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 16dbbabce8d3..643f8ca85499 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> nữa là pin đầy"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quá trình sạc được tối ưu hoá"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quá trình sạc được tối ưu hoá"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index feb738dbca35..3b08e1f27bd6 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电方式已优化"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电方式已优化"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 2b59ac8519be..eba782e54e48 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充滿電"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已優化充電"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已優化充電"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 02a254fd55a9..099ad0364b0e 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充飽"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電效能已最佳化"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電效能將最佳化"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 6a7033ef7063..4d652f819ff3 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -478,7 +478,8 @@ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string> <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kuthuthukisiwe"</string> - <string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kuthuthukisiwe"</string> + <!-- no translation found for power_charging_future_paused (1809543660923642799) --> + <skip /> <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 9588e502f28e..a4bc235aaa7a 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1085,7 +1085,7 @@ <!-- [CHAR_LIMIT=NONE] Label for charging on hold on main page of settings --> <string name="power_charging_on_hold_settings_home_page"><xliff:g id="level">%1$s</xliff:g> - Charging on hold to protect battery</string> <!-- [CHAR_LIMIT=NONE] Label for incompatible charging accessory on main page of settings --> - <string name="power_incompatible_charging_settings_home_page"><xliff:g id="level">%1$s</xliff:g> - Checking charging accessory</string> + <string name="power_incompatible_charging_settings_home_page"><xliff:g id="level">%1$s</xliff:g> - Check charging accessory</string> <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery discharging --> <string name="power_remaining_duration_only">About <xliff:g id="time_remaining">%1$s</xliff:g> left</string> <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration --> diff --git a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java index 0f08605a50d0..df03167cd0f9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -64,6 +65,8 @@ public final class RouterInfoMediaManager extends InfoMediaManager { refreshDevices(); }; + private final AtomicReference<MediaRouter2.ScanToken> mScanToken = new AtomicReference<>(); + // TODO (b/321969740): Plumb target UserHandle between UMO and RouterInfoMediaManager. /* package */ RouterInfoMediaManager( Context context, @@ -101,12 +104,24 @@ public final class RouterInfoMediaManager extends InfoMediaManager { mExecutor, mRouteListingPreferenceCallback); mRouter.registerTransferCallback(mExecutor, mTransferCallback); mRouter.registerControllerCallback(mExecutor, mControllerCallback); - mRouter.startScan(); + if (Flags.enableScreenOffScanning()) { + MediaRouter2.ScanRequest request = new MediaRouter2.ScanRequest.Builder().build(); + mScanToken.compareAndSet(null, mRouter.requestScan(request)); + } else { + mRouter.startScan(); + } } @Override public void stopScan() { - mRouter.stopScan(); + if (Flags.enableScreenOffScanning()) { + MediaRouter2.ScanToken token = mScanToken.getAndSet(null); + if (token != null) { + mRouter.cancelScanRequest(token); + } + } else { + mRouter.stopScan(); + } mRouter.unregisterControllerCallback(mControllerCallback); mRouter.unregisterTransferCallback(mTransferCallback); mRouter.unregisterRouteListingPreferenceUpdatedCallback(mRouteListingPreferenceCallback); diff --git a/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/data/repository/FakeNotificationsSoundPolicyRepository.kt b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/data/repository/FakeNotificationsSoundPolicyRepository.kt index 60983070b1cf..2a44511599f1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/data/repository/FakeNotificationsSoundPolicyRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/data/repository/FakeNotificationsSoundPolicyRepository.kt @@ -40,3 +40,21 @@ class FakeNotificationsSoundPolicyRepository : NotificationsSoundPolicyRepositor mutableZenMode.value = zenMode } } + +fun FakeNotificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories: Int = 0, + priorityCallSenders: Int = NotificationManager.Policy.PRIORITY_SENDERS_ANY, + priorityMessageSenders: Int = NotificationManager.Policy.CONVERSATION_SENDERS_NONE, + suppressedVisualEffects: Int = NotificationManager.Policy.SUPPRESSED_EFFECTS_UNSET, + state: Int = NotificationManager.Policy.STATE_UNSET, + priorityConversationSenders: Int = NotificationManager.Policy.CONVERSATION_SENDERS_NONE, +) = updateNotificationPolicy( + NotificationManager.Policy( + priorityCategories, + priorityCallSenders, + priorityMessageSenders, + suppressedVisualEffects, + state, + priorityConversationSenders, + ) +)
\ No newline at end of file diff --git a/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt new file mode 100644 index 000000000000..794cf832f48b --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.statusbar.notification.domain.interactor + +import android.app.NotificationManager +import android.media.AudioManager +import android.provider.Settings +import android.service.notification.ZenModeConfig +import com.android.settingslib.statusbar.notification.data.model.ZenMode +import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepository +import com.android.settingslib.volume.shared.model.AudioStream +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.map + +/** Determines notification sounds state and limitations. */ +class NotificationsSoundPolicyInteractor( + private val repository: NotificationsSoundPolicyRepository +) { + + /** @see NotificationManager.getNotificationPolicy */ + val notificationPolicy: StateFlow<NotificationManager.Policy?> + get() = repository.notificationPolicy + + /** @see NotificationManager.getZenMode */ + val zenMode: StateFlow<ZenMode?> + get() = repository.zenMode + + /** Checks if [notificationPolicy] allows alarms. */ + val areAlarmsAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowAlarms() } + + /** Checks if [notificationPolicy] allows media. */ + val isMediaAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowMedia() } + + /** Checks if [notificationPolicy] allows ringer. */ + val isRingerAllowed: Flow<Boolean?> = + notificationPolicy.map { policy -> + policy ?: return@map null + !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(policy) + } + + /** Checks if the [stream] is muted by either [zenMode] or [notificationPolicy]. */ + fun isZenMuted(stream: AudioStream): Flow<Boolean> { + return combine( + zenMode.filterNotNull(), + areAlarmsAllowed.filterNotNull(), + isMediaAllowed.filterNotNull(), + isRingerAllowed.filterNotNull(), + ) { zenMode, areAlarmsAllowed, isMediaAllowed, isRingerAllowed -> + if (zenMode.zenMode == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) { + return@combine true + } + + val isNotificationOrRing = + stream.value == AudioManager.STREAM_RING || + stream.value == AudioManager.STREAM_NOTIFICATION + if (isNotificationOrRing && zenMode.zenMode == Settings.Global.ZEN_MODE_ALARMS) { + return@combine true + } + if (zenMode.zenMode != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + return@combine false + } + + if (stream.value == AudioManager.STREAM_ALARM && !areAlarmsAllowed) { + return@combine true + } + if (stream.value == AudioManager.STREAM_MUSIC && !isMediaAllowed) { + return@combine true + } + if (isNotificationOrRing && !isRingerAllowed) { + return@combine true + } + + return@combine false + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt index f729c04fb849..0df4615c8b7c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt @@ -21,10 +21,12 @@ import android.media.AudioManager import android.media.AudioManager.OnCommunicationDeviceChangedListener import androidx.concurrent.futures.DirectExecutor import com.android.internal.util.ConcurrentUtils -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver +import com.android.settingslib.volume.shared.model.AudioManagerEvent import com.android.settingslib.volume.shared.model.AudioStream import com.android.settingslib.volume.shared.model.AudioStreamModel import com.android.settingslib.volume.shared.model.RingerMode +import com.android.settingslib.volume.shared.model.StreamAudioManagerEvent import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose @@ -33,9 +35,11 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -61,10 +65,10 @@ interface AudioRepository { val communicationDevice: StateFlow<AudioDeviceInfo?> /** State of the [AudioStream]. */ - suspend fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> + fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> - /** Current state of the [AudioStream]. */ - suspend fun getCurrentAudioStream(audioStream: AudioStream): AudioStreamModel + /** Returns the last audible volume before stream was muted. */ + suspend fun getLastAudibleVolume(audioStream: AudioStream): Int suspend fun setVolume(audioStream: AudioStream, volume: Int) @@ -72,7 +76,7 @@ interface AudioRepository { } class AudioRepositoryImpl( - private val audioManagerIntentsReceiver: AudioManagerIntentsReceiver, + private val audioManagerEventsReceiver: AudioManagerEventsReceiver, private val audioManager: AudioManager, private val backgroundCoroutineContext: CoroutineContext, private val coroutineScope: CoroutineScope, @@ -89,8 +93,8 @@ class AudioRepositoryImpl( .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), audioManager.mode) override val ringerMode: StateFlow<RingerMode> = - audioManagerIntentsReceiver.intents - .filter { AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION == it.action } + audioManagerEventsReceiver.events + .filterIsInstance(AudioManagerEvent.InternalRingerModeChanged::class) .map { RingerMode(audioManager.ringerModeInternal) } .flowOn(backgroundCoroutineContext) .stateIn( @@ -119,23 +123,34 @@ class AudioRepositoryImpl( audioManager.communicationDevice, ) - override suspend fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> { - return audioManagerIntentsReceiver.intents + override fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> { + return audioManagerEventsReceiver.events + .filter { + if (it is StreamAudioManagerEvent) { + it.audioStream == audioStream + } else { + true + } + } .map { getCurrentAudioStream(audioStream) } + .onStart { emit(getCurrentAudioStream(audioStream)) } .flowOn(backgroundCoroutineContext) } - override suspend fun getCurrentAudioStream(audioStream: AudioStream): AudioStreamModel { + private fun getCurrentAudioStream(audioStream: AudioStream): AudioStreamModel { + return AudioStreamModel( + audioStream = audioStream, + minVolume = getMinVolume(audioStream), + maxVolume = audioManager.getStreamMaxVolume(audioStream.value), + volume = audioManager.getStreamVolume(audioStream.value), + isAffectedByRingerMode = audioManager.isStreamAffectedByRingerMode(audioStream.value), + isMuted = audioManager.isStreamMute(audioStream.value), + ) + } + + override suspend fun getLastAudibleVolume(audioStream: AudioStream): Int { return withContext(backgroundCoroutineContext) { - AudioStreamModel( - audioStream = audioStream, - minVolume = getMinVolume(audioStream), - maxVolume = audioManager.getStreamMaxVolume(audioStream.value), - volume = audioManager.getStreamVolume(audioStream.value), - isAffectedByRingerMode = - audioManager.isStreamAffectedByRingerMode(audioStream.value), - isMuted = audioManager.isStreamMute(audioStream.value) - ) + audioManager.getLastAudibleStreamVolume(audioStream.value) } } diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt index aa9ae76c66c4..298dd71e555e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt @@ -15,13 +15,13 @@ */ package com.android.settingslib.volume.data.repository -import android.media.AudioManager import android.media.MediaRouter2Manager import android.media.RoutingSessionInfo import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.volume.data.model.RoutingSession -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver +import com.android.settingslib.volume.shared.model.AudioManagerEvent import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose @@ -29,7 +29,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull @@ -54,7 +54,7 @@ interface LocalMediaRepository { } class LocalMediaRepositoryImpl( - audioManagerIntentsReceiver: AudioManagerIntentsReceiver, + audioManagerEventsReceiver: AudioManagerEventsReceiver, private val localMediaManager: LocalMediaManager, private val mediaRouter2Manager: MediaRouter2Manager, coroutineScope: CoroutineScope, @@ -62,9 +62,9 @@ class LocalMediaRepositoryImpl( ) : LocalMediaRepository { private val devicesChanges = - audioManagerIntentsReceiver.intents.filter { - AudioManager.STREAM_DEVICES_CHANGED_ACTION == it.action - } + audioManagerEventsReceiver.events.filterIsInstance( + AudioManagerEvent.StreamDevicesChanged::class + ) private val mediaDevicesUpdates: Flow<DevicesUpdate> = callbackFlow { val callback = @@ -109,6 +109,7 @@ class LocalMediaRepositoryImpl( override val currentConnectedDevice: StateFlow<MediaDevice?> = merge(devicesChanges, mediaDevicesUpdates) .map { localMediaManager.currentConnectedDevice } + .onStart { emit(localMediaManager.currentConnectedDevice) } .stateIn( coroutineScope, SharingStarted.WhileSubscribed(), diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt index 6925c71fc68f..7c231d1fad4e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt @@ -16,21 +16,19 @@ package com.android.settingslib.volume.data.repository -import android.content.Intent -import android.media.AudioManager import android.media.session.MediaController import android.media.session.MediaSessionManager -import android.media.session.PlaybackState import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.settingslib.bluetooth.headsetAudioModeChanges import com.android.settingslib.media.session.activeMediaChanges -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver +import com.android.settingslib.volume.shared.model.AudioManagerEvent import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onStart @@ -44,7 +42,7 @@ interface MediaControllerRepository { } class MediaControllerRepositoryImpl( - audioManagerIntentsReceiver: AudioManagerIntentsReceiver, + audioManagerEventsReceiver: AudioManagerEventsReceiver, private val mediaSessionManager: MediaSessionManager, localBluetoothManager: LocalBluetoothManager?, coroutineScope: CoroutineScope, @@ -52,9 +50,9 @@ class MediaControllerRepositoryImpl( ) : MediaControllerRepository { private val devicesChanges = - audioManagerIntentsReceiver.intents.filter { - AudioManager.STREAM_DEVICES_CHANGED_ACTION == it.action - } + audioManagerEventsReceiver.events.filterIsInstance( + AudioManagerEvent.StreamDevicesChanged::class + ) override val activeLocalMediaController: StateFlow<MediaController?> = combine( @@ -63,7 +61,7 @@ class MediaControllerRepositoryImpl( }, localBluetoothManager?.headsetAudioModeChanges?.onStart { emit(Unit) } ?: flowOf(null), - devicesChanges.onStart { emit(Intent()) }, + devicesChanges.onStart { emit(AudioManagerEvent.StreamDevicesChanged) }, ) { controllers, _, _ -> controllers?.let(::findLocalMediaController) } @@ -98,9 +96,4 @@ class MediaControllerRepositoryImpl( } return localController } - - private companion object { - val inactivePlaybackStates = - setOf(PlaybackState.STATE_STOPPED, PlaybackState.STATE_NONE, PlaybackState.STATE_ERROR) - } } diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/domain/interactor/AudioVolumeInteractor.kt b/packages/SettingsLib/src/com/android/settingslib/volume/domain/interactor/AudioVolumeInteractor.kt new file mode 100644 index 000000000000..56b0bf74574f --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/volume/domain/interactor/AudioVolumeInteractor.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.volume.domain.interactor + +import android.media.AudioManager +import com.android.settingslib.statusbar.notification.domain.interactor.NotificationsSoundPolicyInteractor +import com.android.settingslib.volume.data.repository.AudioRepository +import com.android.settingslib.volume.shared.model.AudioStream +import com.android.settingslib.volume.shared.model.AudioStreamModel +import com.android.settingslib.volume.shared.model.RingerMode +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map + +/** Provides audio stream state and an ability to change it */ +class AudioVolumeInteractor( + private val audioRepository: AudioRepository, + private val notificationsSoundPolicyInteractor: NotificationsSoundPolicyInteractor, +) { + + /** State of the [AudioStream]. */ + fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> = + combine( + audioRepository.getAudioStream(audioStream), + audioRepository.ringerMode, + notificationsSoundPolicyInteractor.isZenMuted(audioStream) + ) { streamModel: AudioStreamModel, ringerMode: RingerMode, isZenMuted: Boolean -> + streamModel.copy(volume = processVolume(streamModel, ringerMode, isZenMuted)) + } + + suspend fun setVolume(audioStream: AudioStream, volume: Int) = + audioRepository.setVolume(audioStream, volume) + + suspend fun setMuted(audioStream: AudioStream, isMuted: Boolean) = + audioRepository.setMuted(audioStream, isMuted) + + /** Checks if the volume can be changed via the UI. */ + fun canChangeVolume(audioStream: AudioStream): Flow<Boolean> { + return if (audioStream.value == AudioManager.STREAM_NOTIFICATION) { + getAudioStream(AudioStream(AudioManager.STREAM_RING)).map { !it.isMuted } + } else { + flowOf(true) + } + } + + private suspend fun processVolume( + audioStreamModel: AudioStreamModel, + ringerMode: RingerMode, + isZenMuted: Boolean, + ): Int { + if (isZenMuted) { + return audioRepository.getLastAudibleVolume(audioStreamModel.audioStream) + } + val isNotificationOrRing = + audioStreamModel.audioStream.value == AudioManager.STREAM_RING || + audioStreamModel.audioStream.value == AudioManager.STREAM_NOTIFICATION + if (isNotificationOrRing && ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) { + // For ringer-mode affected streams, show volume as zero when ringer mode is vibrate + if ( + audioStreamModel.audioStream.value == AudioManager.STREAM_RING || + (audioStreamModel.audioStream.value == AudioManager.STREAM_NOTIFICATION && + audioStreamModel.isMuted) + ) { + return 0 + } + } else if (audioStreamModel.isMuted) { + return 0 + } + return audioStreamModel.volume + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioManagerIntentsReceiver.kt b/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioManagerEventsReceiver.kt index 9fa4c86cdea1..c3b1a7cb16e3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioManagerIntentsReceiver.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioManagerEventsReceiver.kt @@ -21,6 +21,9 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.media.AudioManager +import android.util.Log +import com.android.settingslib.volume.shared.model.AudioManagerEvent +import com.android.settingslib.volume.shared.model.AudioStream import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.SharedFlow @@ -28,19 +31,20 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch -/** Exposes [AudioManager] intents as a observable shared flow. */ -interface AudioManagerIntentsReceiver { +/** Exposes [AudioManager] events as a observable shared flow. */ +interface AudioManagerEventsReceiver { - val intents: SharedFlow<Intent> + val events: SharedFlow<AudioManagerEvent> } -class AudioManagerIntentsReceiverImpl( +class AudioManagerEventsReceiverImpl( private val context: Context, coroutineScope: CoroutineScope, -) : AudioManagerIntentsReceiver { +) : AudioManagerEventsReceiver { private val allActions: Collection<String> get() = @@ -50,9 +54,10 @@ class AudioManagerIntentsReceiverImpl( AudioManager.VOLUME_CHANGED_ACTION, AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, AudioManager.STREAM_DEVICES_CHANGED_ACTION, + AudioManager.ACTION_VOLUME_CHANGED, ) - override val intents: SharedFlow<Intent> = + override val events: SharedFlow<AudioManagerEvent> = callbackFlow { val receiver = object : BroadcastReceiver() { @@ -73,5 +78,34 @@ class AudioManagerIntentsReceiverImpl( } .filterNotNull() .filter { intent -> allActions.contains(intent.action) } + .mapNotNull { it.toAudioManagerEvent() } .shareIn(coroutineScope, SharingStarted.WhileSubscribed()) + + private fun Intent.toAudioManagerEvent(): AudioManagerEvent? { + when (action) { + AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION -> + return AudioManagerEvent.InternalRingerModeChanged + AudioManager.STREAM_DEVICES_CHANGED_ACTION -> + return AudioManagerEvent.StreamDevicesChanged + AudioManager.MASTER_MUTE_CHANGED_ACTION -> + return AudioManagerEvent.StreamMasterMuteChanged + } + + val audioStreamType: Int = + getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.ERROR) + if (audioStreamType == AudioManager.ERROR) { + Log.e( + "AudioManagerIntentsReceiver", + "Intent doesn't have AudioManager.EXTRA_VOLUME_STREAM_TYPE extra", + ) + return null + } + val audioStream = AudioStream(audioStreamType) + return when (action) { + AudioManager.STREAM_MUTE_CHANGED_ACTION -> + AudioManagerEvent.StreamMuteChanged(audioStream) + AudioManager.VOLUME_CHANGED_ACTION -> AudioManagerEvent.StreamVolumeChanged(audioStream) + else -> null + } + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioManagerEvent.kt b/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioManagerEvent.kt new file mode 100644 index 000000000000..e19896bc5e87 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioManagerEvent.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.volume.shared.model + +/** Model events happening with the [android.media.AudioManager]. */ +sealed interface AudioManagerEvent { + + data class StreamMuteChanged(override val audioStream: AudioStream) : StreamAudioManagerEvent + + data class StreamVolumeChanged(override val audioStream: AudioStream) : StreamAudioManagerEvent + + data object StreamMasterMuteChanged : AudioManagerEvent + + data object InternalRingerModeChanged : AudioManagerEvent + + data object StreamDevicesChanged : AudioManagerEvent +} + +/** [AudioManagerEvent] that happens for a specific [AudioStream]. */ +sealed interface StreamAudioManagerEvent : AudioManagerEvent { + + val audioStream: AudioStream +} diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioStream.kt b/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioStream.kt index 58f3c2d61f3b..9c48299d81be 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioStream.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/shared/model/AudioStream.kt @@ -25,7 +25,7 @@ value class AudioStream(val value: Int) { require(value in supportedStreamTypes) { "Unsupported stream=$value" } } - private companion object { + companion object { val supportedStreamTypes = setOf( AudioManager.STREAM_VOICE_CALL, diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt index 48b04db5b50b..1728a8022ce5 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt @@ -20,7 +20,8 @@ import android.media.AudioDeviceInfo import android.media.AudioManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.settingslib.volume.shared.FakeAudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.FakeAudioManagerEventsReceiver +import com.android.settingslib.volume.shared.model.AudioManagerEvent import com.android.settingslib.volume.shared.model.AudioStream import com.android.settingslib.volume.shared.model.AudioStreamModel import com.android.settingslib.volume.shared.model.RingerMode @@ -46,7 +47,6 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@Suppress("UnspecifiedRegisterReceiverFlag") @RunWith(AndroidJUnit4::class) class AudioRepositoryTest { @@ -59,7 +59,7 @@ class AudioRepositoryTest { @Mock private lateinit var audioManager: AudioManager @Mock private lateinit var communicationDevice: AudioDeviceInfo - private val intentsReceiver = FakeAudioManagerIntentsReceiver() + private val eventsReceiver = FakeAudioManagerEventsReceiver() private val volumeByStream: MutableMap<Int, Int> = mutableMapOf() private val isAffectedByRingerModeByStream: MutableMap<Int, Boolean> = mutableMapOf() private val isMuteByStream: MutableMap<Int, Boolean> = mutableMapOf() @@ -77,12 +77,14 @@ class AudioRepositoryTest { `when`(audioManager.getStreamMaxVolume(anyInt())).thenReturn(MAX_VOLUME) `when`(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL) `when`(audioManager.setStreamVolume(anyInt(), anyInt(), anyInt())).then { - volumeByStream[it.arguments[0] as Int] = it.arguments[1] as Int - triggerIntent(AudioManager.ACTION_VOLUME_CHANGED) + val streamType = it.arguments[1] as Int + volumeByStream[it.arguments[0] as Int] = streamType + triggerEvent(AudioManagerEvent.StreamVolumeChanged(AudioStream(streamType))) } `when`(audioManager.adjustStreamVolume(anyInt(), anyInt(), anyInt())).then { - isMuteByStream[it.arguments[0] as Int] = it.arguments[2] == AudioManager.ADJUST_MUTE - triggerIntent(AudioManager.STREAM_MUTE_CHANGED_ACTION) + val streamType = it.arguments[0] as Int + isMuteByStream[streamType] = it.arguments[2] == AudioManager.ADJUST_MUTE + triggerEvent(AudioManagerEvent.StreamMuteChanged(AudioStream(streamType))) } `when`(audioManager.getStreamVolume(anyInt())).thenAnswer { volumeByStream.getOrDefault(it.arguments[0] as Int, 0) @@ -96,7 +98,7 @@ class AudioRepositoryTest { underTest = AudioRepositoryImpl( - intentsReceiver, + eventsReceiver, audioManager, testScope.testScheduler, testScope.backgroundScope, @@ -125,7 +127,7 @@ class AudioRepositoryTest { runCurrent() `when`(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_SILENT) - triggerIntent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION) + triggerEvent(AudioManagerEvent.InternalRingerModeChanged) runCurrent() assertThat(modes) @@ -179,24 +181,6 @@ class AudioRepositoryTest { } @Test - fun adjustingVolume_currentModeIsUpToDate() { - testScope.runTest { - val audioStream = AudioStream(AudioManager.STREAM_SYSTEM) - var streamModel: AudioStreamModel? = null - underTest - .getAudioStream(audioStream) - .onEach { streamModel = it } - .launchIn(backgroundScope) - runCurrent() - - underTest.setVolume(audioStream, 50) - runCurrent() - - assertThat(underTest.getCurrentAudioStream(audioStream)).isEqualTo(streamModel) - } - } - - @Test fun muteStream_mutesTheStream() { testScope.runTest { val audioStream = AudioStream(AudioManager.STREAM_SYSTEM) @@ -267,8 +251,8 @@ class AudioRepositoryTest { modeListenerCaptor.value.onModeChanged(mode) } - private fun triggerIntent(action: String) { - testScope.launch { intentsReceiver.triggerIntent(action) } + private fun triggerEvent(event: AudioManagerEvent) { + testScope.launch { eventsReceiver.triggerEvent(event) } } private companion object { diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/LocalMediaRepositoryImplTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/LocalMediaRepositoryImplTest.kt index dc9ea10a1074..2d12dae36ff1 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/LocalMediaRepositoryImplTest.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/LocalMediaRepositoryImplTest.kt @@ -23,7 +23,7 @@ import androidx.test.filters.SmallTest import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.volume.data.model.RoutingSession -import com.android.settingslib.volume.shared.FakeAudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.FakeAudioManagerEventsReceiver import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.launchIn @@ -58,7 +58,7 @@ class LocalMediaRepositoryImplTest { @Captor private lateinit var deviceCallbackCaptor: ArgumentCaptor<LocalMediaManager.DeviceCallback> - private val intentsReceiver = FakeAudioManagerIntentsReceiver() + private val eventsReceiver = FakeAudioManagerEventsReceiver() private val testScope = TestScope() private lateinit var underTest: LocalMediaRepository @@ -69,7 +69,7 @@ class LocalMediaRepositoryImplTest { underTest = LocalMediaRepositoryImpl( - intentsReceiver, + eventsReceiver, localMediaManager, mediaRouter2Manager, testScope.backgroundScope, diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/MediaControllerRepositoryImplTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/MediaControllerRepositoryImplTest.kt index 7bd43d2cf8ab..f3d17141334e 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/MediaControllerRepositoryImplTest.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/MediaControllerRepositoryImplTest.kt @@ -16,7 +16,6 @@ package com.android.settingslib.volume.data.repository -import android.media.AudioManager import android.media.session.MediaController import android.media.session.MediaController.PlaybackInfo import android.media.session.MediaSessionManager @@ -26,7 +25,8 @@ import androidx.test.filters.SmallTest import com.android.settingslib.bluetooth.BluetoothCallback import com.android.settingslib.bluetooth.BluetoothEventManager import com.android.settingslib.bluetooth.LocalBluetoothManager -import com.android.settingslib.volume.shared.FakeAudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.FakeAudioManagerEventsReceiver +import com.android.settingslib.volume.shared.model.AudioManagerEvent import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.launchIn @@ -66,7 +66,7 @@ class MediaControllerRepositoryImplTest { @Mock private lateinit var localPlaybackInfo: PlaybackInfo private val testScope = TestScope() - private val intentsReceiver = FakeAudioManagerIntentsReceiver() + private val eventsReceiver = FakeAudioManagerEventsReceiver() private lateinit var underTest: MediaControllerRepository @@ -94,7 +94,7 @@ class MediaControllerRepositoryImplTest { underTest = MediaControllerRepositoryImpl( - intentsReceiver, + eventsReceiver, mediaSessionManager, localBluetoothManager, testScope.backgroundScope, @@ -121,7 +121,7 @@ class MediaControllerRepositoryImplTest { .launchIn(backgroundScope) runCurrent() - intentsReceiver.triggerIntent(AudioManager.STREAM_DEVICES_CHANGED_ACTION) + eventsReceiver.triggerEvent(AudioManagerEvent.StreamDevicesChanged) triggerOnAudioModeChanged() runCurrent() @@ -146,7 +146,7 @@ class MediaControllerRepositoryImplTest { .launchIn(backgroundScope) runCurrent() - intentsReceiver.triggerIntent(AudioManager.STREAM_DEVICES_CHANGED_ACTION) + eventsReceiver.triggerEvent(AudioManagerEvent.StreamDevicesChanged) triggerOnAudioModeChanged() runCurrent() diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/AudioManagerEventsReceiverTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/AudioManagerEventsReceiverTest.kt new file mode 100644 index 000000000000..35ee8287d52f --- /dev/null +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/AudioManagerEventsReceiverTest.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.volume.shared + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.media.AudioManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.settingslib.volume.shared.model.AudioManagerEvent +import com.android.settingslib.volume.shared.model.AudioStream +import com.google.common.truth.Expect +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +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.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@Suppress("UnspecifiedRegisterReceiverFlag") +@RunWith(AndroidJUnit4::class) +class AudioManagerEventsReceiverTest { + + @JvmField @Rule val expect = Expect.create() + private val testScope = TestScope() + + @Mock private lateinit var context: Context + @Captor private lateinit var receiverCaptor: ArgumentCaptor<BroadcastReceiver> + + private lateinit var underTest: AudioManagerEventsReceiver + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + + underTest = AudioManagerEventsReceiverImpl(context, testScope.backgroundScope) + } + + @Test + fun validIntent_translatedToEvent() { + testScope.runTest { + val events = mutableListOf<AudioManagerEvent>() + underTest.events.onEach { events.add(it) }.launchIn(backgroundScope) + runCurrent() + + triggerIntent( + Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION).apply { + putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_SYSTEM) + } + ) + triggerIntent( + Intent(AudioManager.VOLUME_CHANGED_ACTION).apply { + putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_SYSTEM) + } + ) + triggerIntent(Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION)) + triggerIntent(Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) + triggerIntent(Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) + runCurrent() + + expect + .that(events) + .containsExactly( + AudioManagerEvent.StreamMuteChanged( + AudioStream(AudioManager.STREAM_SYSTEM), + ), + AudioManagerEvent.StreamVolumeChanged( + AudioStream(AudioManager.STREAM_SYSTEM), + ), + AudioManagerEvent.StreamMasterMuteChanged, + AudioManagerEvent.InternalRingerModeChanged, + AudioManagerEvent.StreamDevicesChanged, + ) + } + } + + @Test + fun streamAudioManagerEvent_withoutAudioStream_areSkipped() { + testScope.runTest { + val events = mutableListOf<AudioManagerEvent>() + underTest.events.onEach { events.add(it) }.launchIn(backgroundScope) + runCurrent() + + triggerIntent(Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION)) + triggerIntent(Intent(AudioManager.VOLUME_CHANGED_ACTION)) + runCurrent() + + expect.that(events).isEmpty() + } + } + + @Test + fun invalidIntents_areSkipped() { + testScope.runTest { + val events = mutableListOf<AudioManagerEvent>() + underTest.events.onEach { events.add(it) }.launchIn(backgroundScope) + runCurrent() + + triggerIntent(null) + triggerIntent(Intent()) + triggerIntent(Intent("invalid_action")) + runCurrent() + + expect.that(events).isEmpty() + } + } + + private fun triggerIntent(intent: Intent?) { + verify(context).registerReceiver(receiverCaptor.capture(), any()) + receiverCaptor.value.onReceive(context, intent) + } +} diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/FakeAudioManagerIntentsReceiver.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/FakeAudioManagerEventsReceiver.kt index 530690a5faa9..b742df7afc46 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/FakeAudioManagerIntentsReceiver.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/shared/FakeAudioManagerEventsReceiver.kt @@ -16,21 +16,17 @@ package com.android.settingslib.volume.shared -import android.content.Intent +import com.android.settingslib.volume.shared.model.AudioManagerEvent import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow -class FakeAudioManagerIntentsReceiver : AudioManagerIntentsReceiver { +class FakeAudioManagerEventsReceiver : AudioManagerEventsReceiver { - private val mutableIntents = MutableSharedFlow<Intent>() - override val intents: SharedFlow<Intent> = mutableIntents.asSharedFlow() + private val mutableIntents = MutableSharedFlow<AudioManagerEvent>() + override val events: SharedFlow<AudioManagerEvent> = mutableIntents.asSharedFlow() - suspend fun triggerIntent(intent: Intent) { - mutableIntents.emit(intent) - } - - suspend fun triggerIntent(action: String) { - triggerIntent(Intent(action)) + suspend fun triggerEvent(event: AudioManagerEvent) { + mutableIntents.emit(event) } } diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index e424797c664e..2fa1c6eda458 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -227,6 +227,7 @@ public class SecureSettings { Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED, Settings.Secure.ACCESSIBILITY_PINCH_TO_ZOOM_ANYWHERE_ENABLED, + Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED, Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, Settings.Secure.NOTIFICATION_BUBBLES, Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index a32eeadc2982..2535fdb6e4d0 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -321,6 +321,7 @@ public class SecureSettingsValidators { Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_PINCH_TO_ZOOM_ANYWHERE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put( Secure.ACCESSIBILITY_BUTTON_TARGETS, ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index d27ff175ca25..02d212cb4996 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1865,6 +1865,10 @@ class SettingsProtoDumpUtil { SecureSettingsProto.Accessibility .ACCESSIBILITY_PINCH_TO_ZOOM_ANYWHERE_ENABLED); dumpSetting(s, p, + Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED, + SecureSettingsProto.Accessibility + .ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED); + dumpSetting(s, p, Settings.Secure.HEARING_AID_RINGTONE_ROUTING, SecureSettingsProto.Accessibility.HEARING_AID_RINGTONE_ROUTING); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index b58187d8e95e..28cdc6db192b 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -807,7 +807,9 @@ public class SettingsBackupTest { Settings.Secure.UI_TRANSLATION_ENABLED, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED, Settings.Secure.DND_CONFIGS_MIGRATED, - Settings.Secure.NAVIGATION_MODE_RESTORE); + Settings.Secure.NAVIGATION_MODE_RESTORE, + Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, + Settings.Secure.V_TO_U_RESTORE_DENYLIST); @Test public void systemSettingsBackedUpOrDenied() { diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index d1a3571a87c1..bed95a584c27 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -550,5 +550,6 @@ android_app { required: [ "privapp_whitelist_com.android.systemui", "wmshell.protolog.json.gz", + "wmshell.protolog.pb", ], } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sv/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sv/strings.xml index ef6966707fda..c02bbb2643d5 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sv/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sv/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="accessibility_menu_service_name" msgid="730136711554740131">"Tillgänglighetsmenyn"</string> + <string name="accessibility_menu_service_name" msgid="730136711554740131">"Till- gänglighetsmeny"</string> <string name="accessibility_menu_intro" msgid="3164193281544042394">"Tillgänglighetsmenyn är en stor meny på skärmen som du kan styra enheten med. Du kan låsa enheten, ställa in volym och ljusstyrka, ta skärmbilder och annat."</string> <string name="assistant_label" msgid="6796392082252272356">"Assistent"</string> <string name="assistant_utterance" msgid="65509599221141377">"Assistent"</string> diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 71f9ba2788a1..f5c4843e1324 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -377,6 +377,13 @@ flag { } flag { + name: "screenshot_action_dismiss_system_windows" + namespace: "systemui" + description: "Dismiss existing system windows when starting action from screenshot UI" + bug: "309933761" +} + +flag { name: "run_fingerprint_detect_on_dismissible_keyguard" namespace: "systemui" description: "Run fingerprint detect instead of authenticate if the keyguard is dismissible." @@ -529,3 +536,23 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "bind_keyguard_media_visibility" + namespace: "systemui" + description: "Binds Keyguard Media Controller Visibility to MediaContainerView" + bug: "298213983" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "notify_power_manager_user_activity_background" + namespace: "systemui" + description: "Decide whether to notify the user activity to power manager in the background thread." + bug: "325203885" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp index c1125f0b9e92..99b7c36d6fb9 100644 --- a/packages/SystemUI/animation/Android.bp +++ b/packages/SystemUI/animation/Android.bp @@ -45,6 +45,7 @@ android_library { "androidx.core_core-ktx", "androidx.annotation_annotation", "SystemUIShaderLib", + "WindowManager-Shell-shared", "animationlib", ], diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java index a78080fdabf2..e20425d4b98c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,10 +11,10 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.systemui.shared.system; +package com.android.systemui.animation; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.WindowManager.TRANSIT_CLOSE; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationTargetCompat.java index e4d924323bbd..e251af44727e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationTargetCompat.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.shared.system; +package com.android.systemui.animation; import android.util.ArrayMap; import android.view.RemoteAnimationTarget; diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt index 535c2d32ed09..e862f0c43a58 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt @@ -17,7 +17,6 @@ package com.android.systemui.surfaceeffects.turbulencenoise import android.view.View import androidx.annotation.VisibleForTesting -import java.util.Random /** Plays [TurbulenceNoiseView] in ease-in, main (no easing), and ease-out order. */ class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoiseView) { @@ -37,8 +36,6 @@ class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoise } } - private val random = Random() - /** Current state of the animation. */ @VisibleForTesting var state: AnimationState = AnimationState.NOT_PLAYING @@ -95,12 +92,7 @@ class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoise } state = AnimationState.EASE_IN - // Add offset to avoid repetitive noise. - turbulenceNoiseView.playEaseIn( - offsetX = random.nextFloat(), - offsetY = random.nextFloat(), - this::playMainAnimation - ) + turbulenceNoiseView.playEaseIn(this::playMainAnimation) } private fun playMainAnimation() { diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt index c59bc106ca91..5e72e3bd1e39 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt @@ -109,7 +109,7 @@ class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(contex /** Plays the turbulence noise with linear ease-in. */ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - fun playEaseIn(offsetX: Float = 0f, offsetY: Float = 0f, onAnimationEnd: Runnable? = null) { + fun playEaseIn(onAnimationEnd: Runnable? = null) { if (noiseConfig == null) { return } @@ -129,8 +129,8 @@ class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(contex val progress = updateListener.animatedValue as Float shader.setNoiseMove( - offsetX + initialX + timeInSec * config.noiseMoveSpeedX, - offsetY + initialY + timeInSec * config.noiseMoveSpeedY, + initialX + timeInSec * config.noiseMoveSpeedX, + initialY + timeInSec * config.noiseMoveSpeedY, initialZ + timeInSec * config.noiseMoveSpeedZ ) diff --git a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt index b8c4fae975af..62dd4ac8c230 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt @@ -57,9 +57,6 @@ import androidx.compose.ui.unit.dp import com.android.compose.modifiers.padding import com.android.compose.theme.LocalAndroidColorScheme -/** Indicator corner radius used when the user drags the [PlatformSlider]. */ -private val DefaultPlatformSliderDraggingCornerRadius = 8.dp - /** * Platform slider implementation that displays a slider with an [icon] and a [label] at the start. * @@ -83,10 +80,8 @@ fun PlatformSlider( valueRange: ClosedFloatingPointRange<Float> = 0f..1f, enabled: Boolean = true, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - colors: PlatformSliderColors = - if (isSystemInDarkTheme()) darkThemePlatformSliderColors() - else lightThemePlatformSliderColors(), - draggingCornersRadius: Dp = DefaultPlatformSliderDraggingCornerRadius, + colors: PlatformSliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(), + draggingCornersRadius: Dp = PlatformSliderDefaults.DefaultPlatformSliderDraggingCornerRadius, icon: (@Composable (isDragging: Boolean) -> Unit)? = null, label: (@Composable (isDragging: Boolean) -> Unit)? = null, ) { @@ -109,7 +104,7 @@ fun PlatformSlider( val paddingStart by animateDpAsState( targetValue = - if ((!isDragging && value == 0f) || icon == null) { + if ((!isDragging && value == valueRange.start) || icon == null) { 16.dp } else { 0.dp @@ -125,6 +120,7 @@ fun PlatformSlider( valueRange = valueRange, onValueChangeFinished = onValueChangeFinished, interactionSource = interactionSource, + enabled = enabled, track = { Track( sliderState = it, @@ -286,6 +282,17 @@ data class PlatformSliderColors( val disabledLabelColor: Color, ) +object PlatformSliderDefaults { + + /** Indicator corner radius used when the user drags the [PlatformSlider]. */ + val DefaultPlatformSliderDraggingCornerRadius = 8.dp + + @Composable + fun defaultPlatformSliderColors(): PlatformSliderColors = + if (isSystemInDarkTheme()) darkThemePlatformSliderColors() + else lightThemePlatformSliderColors() +} + /** [PlatformSliderColors] for the light theme */ @Composable private fun lightThemePlatformSliderColors() = diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt new file mode 100644 index 000000000000..b4cb0983f213 --- /dev/null +++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume + +import dagger.Module + +@Module interface VolumeSlidersModule diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index cddd4fa1c33d..622a4f04ee0d 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -73,6 +73,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color @@ -85,7 +86,10 @@ import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset @@ -110,6 +114,7 @@ import com.android.systemui.communal.widgets.WidgetConfigurator import com.android.systemui.res.R import kotlinx.coroutines.launch +@OptIn(ExperimentalComposeUiApi::class) @Composable fun CommunalHub( modifier: Modifier = Modifier, @@ -140,6 +145,8 @@ fun CommunalHub( Box( modifier = modifier + .semantics { testTagsAsResourceId = true } + .testTag(COMMUNAL_HUB_TEST_TAG) .fillMaxSize() .pointerInput(gridState, contentOffset, contentListState) { // If not in edit mode, don't allow selecting items. @@ -872,3 +879,6 @@ object Dimensions { ) val IconSize = 48.dp } + +/** The resource id of communal hub accessible from UiAutomator. */ +private const val COMMUNAL_HUB_TEST_TAG = "communal_hub" diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt index 3677cab890f5..53f400fac7e5 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt @@ -20,6 +20,8 @@ import com.android.systemui.keyguard.ui.composable.blueprint.CommunalBlueprintMo import com.android.systemui.keyguard.ui.composable.blueprint.DefaultBlueprintModule import com.android.systemui.keyguard.ui.composable.blueprint.ShortcutsBesideUdfpsBlueprintModule import com.android.systemui.keyguard.ui.composable.blueprint.SplitShadeBlueprintModule +import com.android.systemui.keyguard.ui.composable.blueprint.SplitShadeWeatherClockBlueprintModule +import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockBlueprintModule import com.android.systemui.keyguard.ui.composable.section.OptionalSectionModule import dagger.Module @@ -31,6 +33,8 @@ import dagger.Module OptionalSectionModule::class, ShortcutsBesideUdfpsBlueprintModule::class, SplitShadeBlueprintModule::class, + SplitShadeWeatherClockBlueprintModule::class, + WeatherClockBlueprintModule::class, ], ) interface LockscreenSceneBlueprintModule diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt index a07ab4a11731..452dc03facfd 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt @@ -33,7 +33,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.LockscreenLongPress import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection -import com.android.systemui.keyguard.ui.composable.section.ClockSection +import com.android.systemui.keyguard.ui.composable.section.DefaultClockSection import com.android.systemui.keyguard.ui.composable.section.LockSection import com.android.systemui.keyguard.ui.composable.section.NotificationSection import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection @@ -56,7 +56,7 @@ class DefaultBlueprint constructor( private val viewModel: LockscreenContentViewModel, private val statusBarSection: StatusBarSection, - private val clockSection: ClockSection, + private val clockSection: DefaultClockSection, private val smartSpaceSection: SmartSpaceSection, private val notificationSection: NotificationSection, private val lockSection: LockSection, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt index b035e4220a5b..71c60c70a655 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt @@ -33,7 +33,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.LockscreenLongPress import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection -import com.android.systemui.keyguard.ui.composable.section.ClockSection +import com.android.systemui.keyguard.ui.composable.section.DefaultClockSection import com.android.systemui.keyguard.ui.composable.section.LockSection import com.android.systemui.keyguard.ui.composable.section.NotificationSection import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection @@ -56,7 +56,7 @@ class ShortcutsBesideUdfpsBlueprint constructor( private val viewModel: LockscreenContentViewModel, private val statusBarSection: StatusBarSection, - private val clockSection: ClockSection, + private val clockSection: DefaultClockSection, private val smartSpaceSection: SmartSpaceSection, private val notificationSection: NotificationSection, private val lockSection: LockSection, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt index 44fe8831729c..af836b68544c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/SplitShadeBlueprint.kt @@ -39,7 +39,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.LockscreenLongPress import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection -import com.android.systemui.keyguard.ui.composable.section.ClockSection +import com.android.systemui.keyguard.ui.composable.section.DefaultClockSection import com.android.systemui.keyguard.ui.composable.section.LockSection import com.android.systemui.keyguard.ui.composable.section.NotificationSection import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection @@ -63,7 +63,7 @@ class SplitShadeBlueprint constructor( private val viewModel: LockscreenContentViewModel, private val statusBarSection: StatusBarSection, - private val clockSection: ClockSection, + private val clockSection: DefaultClockSection, private val smartSpaceSection: SmartSpaceSection, private val notificationSection: NotificationSection, private val lockSection: LockSection, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt new file mode 100644 index 000000000000..e2e7a950cdfd --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.composable.blueprint + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.Layout +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.dp +import com.android.compose.animation.scene.SceneScope +import com.android.compose.modifiers.padding +import com.android.systemui.Flags +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID +import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor +import com.android.systemui.keyguard.ui.composable.LockscreenLongPress +import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection +import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection +import com.android.systemui.keyguard.ui.composable.section.LockSection +import com.android.systemui.keyguard.ui.composable.section.NotificationSection +import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection +import com.android.systemui.keyguard.ui.composable.section.SmartSpaceSection +import com.android.systemui.keyguard.ui.composable.section.StatusBarSection +import com.android.systemui.keyguard.ui.composable.section.WeatherClockSection +import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel +import com.android.systemui.res.R +import com.android.systemui.shade.LargeScreenHeaderHelper +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoSet +import java.util.Optional +import javax.inject.Inject + +class WeatherClockBlueprint +@Inject +constructor( + private val viewModel: LockscreenContentViewModel, + private val statusBarSection: StatusBarSection, + private val weatherClockSection: WeatherClockSection, + private val smartSpaceSection: SmartSpaceSection, + private val notificationSection: NotificationSection, + private val lockSection: LockSection, + private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>, + private val bottomAreaSection: BottomAreaSection, + private val settingsMenuSection: SettingsMenuSection, + private val clockInteractor: KeyguardClockInteractor, +) : ComposableLockscreenSceneBlueprint { + + override val id: String = WEATHER_CLOCK_BLUEPRINT_ID + @Composable + override fun SceneScope.Content(modifier: Modifier) { + val isUdfpsVisible = viewModel.isUdfpsVisible + val burnIn = rememberBurnIn(clockInteractor) + val resources = LocalContext.current.resources + + LockscreenLongPress( + viewModel = viewModel.longPress, + modifier = modifier, + ) { onSettingsMenuPlaced -> + Layout( + content = { + // Constrained to above the lock icon. + Column( + modifier = Modifier.fillMaxWidth(), + ) { + with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) } + // TODO: Add weather clock for small and large clock + with(smartSpaceSection) { + SmartSpace( + burnInParams = burnIn.parameters, + onTopChanged = burnIn.onSmartspaceTopChanged, + modifier = + Modifier.fillMaxWidth() + .padding( + top = { viewModel.getSmartSpacePaddingTop(resources) }, + ) + .padding( + bottom = + dimensionResource( + R.dimen.keyguard_status_view_bottom_margin + ), + ), + ) + } + + if (viewModel.areNotificationsVisible) { + with(notificationSection) { + Notifications( + modifier = Modifier.fillMaxWidth().weight(weight = 1f) + ) + } + } + + if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + } + + with(lockSection) { LockIcon() } + + // Aligned to bottom and constrained to below the lock icon. + Column(modifier = Modifier.fillMaxWidth()) { + if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + + with(bottomAreaSection) { + IndicationArea(modifier = Modifier.fillMaxWidth()) + } + } + + // Aligned to bottom and NOT constrained by the lock icon. + with(bottomAreaSection) { + Shortcut(isStart = true, applyPadding = true) + Shortcut(isStart = false, applyPadding = true) + } + with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) } + }, + modifier = Modifier.fillMaxSize(), + ) { measurables, constraints -> + check(measurables.size == 6) + val aboveLockIconMeasurable = measurables[0] + val lockIconMeasurable = measurables[1] + val belowLockIconMeasurable = measurables[2] + val startShortcutMeasurable = measurables[3] + val endShortcutMeasurable = measurables[4] + val settingsMenuMeasurable = measurables[5] + + val noMinConstraints = + constraints.copy( + minWidth = 0, + minHeight = 0, + ) + val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) + val lockIconBounds = + IntRect( + left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left], + top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top], + right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right], + bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], + ) + + val aboveLockIconPlaceable = + aboveLockIconMeasurable.measure( + noMinConstraints.copy(maxHeight = lockIconBounds.top) + ) + val belowLockIconPlaceable = + belowLockIconMeasurable.measure( + noMinConstraints.copy( + maxHeight = + (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) + ) + ) + val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) + val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints) + val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) + + layout(constraints.maxWidth, constraints.maxHeight) { + aboveLockIconPlaceable.place( + x = 0, + y = 0, + ) + lockIconPlaceable.place( + x = lockIconBounds.left, + y = lockIconBounds.top, + ) + belowLockIconPlaceable.place( + x = 0, + y = constraints.maxHeight - belowLockIconPlaceable.height, + ) + startShortcutPleaceable.place( + x = 0, + y = constraints.maxHeight - startShortcutPleaceable.height, + ) + endShortcutPleaceable.place( + x = constraints.maxWidth - endShortcutPleaceable.width, + y = constraints.maxHeight - endShortcutPleaceable.height, + ) + settingsMenuPlaceable.place( + x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2, + y = constraints.maxHeight - settingsMenuPlaceable.height, + ) + } + } + } + } +} + +class SplitShadeWeatherClockBlueprint +@Inject +constructor( + private val viewModel: LockscreenContentViewModel, + private val statusBarSection: StatusBarSection, + private val smartSpaceSection: SmartSpaceSection, + private val notificationSection: NotificationSection, + private val lockSection: LockSection, + private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>, + private val bottomAreaSection: BottomAreaSection, + private val settingsMenuSection: SettingsMenuSection, + private val clockInteractor: KeyguardClockInteractor, + private val largeScreenHeaderHelper: LargeScreenHeaderHelper, + private val weatherClockSection: WeatherClockSection, +) : ComposableLockscreenSceneBlueprint { + override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID + + @Composable + override fun SceneScope.Content(modifier: Modifier) { + val isUdfpsVisible = viewModel.isUdfpsVisible + val burnIn = rememberBurnIn(clockInteractor) + val resources = LocalContext.current.resources + + LockscreenLongPress( + viewModel = viewModel.longPress, + modifier = modifier, + ) { onSettingsMenuPlaced -> + Layout( + content = { + // Constrained to above the lock icon. + Column( + modifier = Modifier.fillMaxSize(), + ) { + with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) } + Row( + modifier = Modifier.fillMaxSize(), + ) { + // TODO: Add weather clock for small and large clock + Column( + modifier = Modifier.fillMaxHeight().weight(weight = 1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + with(smartSpaceSection) { + SmartSpace( + burnInParams = burnIn.parameters, + onTopChanged = burnIn.onSmartspaceTopChanged, + modifier = + Modifier.fillMaxWidth() + .padding( + top = { + viewModel.getSmartSpacePaddingTop(resources) + }, + ) + .padding( + bottom = + dimensionResource( + R.dimen + .keyguard_status_view_bottom_margin + ) + ), + ) + } + } + with(notificationSection) { + val splitShadeTopMargin: Dp = + if (Flags.centralizedStatusBarHeightFix()) { + largeScreenHeaderHelper.getLargeScreenHeaderHeight().dp + } else { + dimensionResource( + id = R.dimen.large_screen_shade_header_height + ) + } + Notifications( + modifier = + Modifier.fillMaxHeight() + .weight(weight = 1f) + .padding(top = splitShadeTopMargin) + ) + } + } + + if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + } + + with(lockSection) { LockIcon() } + + // Aligned to bottom and constrained to below the lock icon. + Column(modifier = Modifier.fillMaxWidth()) { + if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { + with(ambientIndicationSectionOptional.get()) { + AmbientIndication(modifier = Modifier.fillMaxWidth()) + } + } + + with(bottomAreaSection) { + IndicationArea(modifier = Modifier.fillMaxWidth()) + } + } + + // Aligned to bottom and NOT constrained by the lock icon. + with(bottomAreaSection) { + Shortcut(isStart = true, applyPadding = true) + Shortcut(isStart = false, applyPadding = true) + } + with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) } + }, + modifier = Modifier.fillMaxSize(), + ) { measurables, constraints -> + check(measurables.size == 6) + val aboveLockIconMeasurable = measurables[0] + val lockIconMeasurable = measurables[1] + val belowLockIconMeasurable = measurables[2] + val startShortcutMeasurable = measurables[3] + val endShortcutMeasurable = measurables[4] + val settingsMenuMeasurable = measurables[5] + + val noMinConstraints = + constraints.copy( + minWidth = 0, + minHeight = 0, + ) + val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) + val lockIconBounds = + IntRect( + left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left], + top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top], + right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right], + bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], + ) + + val aboveLockIconPlaceable = + aboveLockIconMeasurable.measure( + noMinConstraints.copy(maxHeight = lockIconBounds.top) + ) + val belowLockIconPlaceable = + belowLockIconMeasurable.measure( + noMinConstraints.copy( + maxHeight = + (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) + ) + ) + val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) + val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints) + val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) + + layout(constraints.maxWidth, constraints.maxHeight) { + aboveLockIconPlaceable.place( + x = 0, + y = 0, + ) + lockIconPlaceable.place( + x = lockIconBounds.left, + y = lockIconBounds.top, + ) + belowLockIconPlaceable.place( + x = 0, + y = constraints.maxHeight - belowLockIconPlaceable.height, + ) + startShortcutPleaceable.place( + x = 0, + y = constraints.maxHeight - startShortcutPleaceable.height, + ) + endShortcutPleaceable.place( + x = constraints.maxWidth - endShortcutPleaceable.width, + y = constraints.maxHeight - endShortcutPleaceable.height, + ) + settingsMenuPlaceable.place( + x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2, + y = constraints.maxHeight - settingsMenuPlaceable.height, + ) + } + } + } + } +} + +@Module +interface WeatherClockBlueprintModule { + @Binds + @IntoSet + fun blueprint(blueprint: WeatherClockBlueprint): ComposableLockscreenSceneBlueprint +} + +@Module +interface SplitShadeWeatherClockBlueprintModule { + @Binds + @IntoSet + fun blueprint(blueprint: SplitShadeWeatherClockBlueprint): ComposableLockscreenSceneBlueprint +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt index 8bd0d45920f4..97d5b41000de 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt @@ -35,7 +35,6 @@ import com.android.systemui.animation.view.LaunchableImageView import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea -import com.android.systemui.keyguard.ui.viewmodel.AodAlphaViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel @@ -55,7 +54,6 @@ constructor( private val vibratorHelper: VibratorHelper, private val indicationController: KeyguardIndicationController, private val indicationAreaViewModel: KeyguardIndicationAreaViewModel, - private val alphaViewModel: AodAlphaViewModel, ) { /** * Renders a single lockscreen shortcut. @@ -104,7 +102,6 @@ constructor( content { IndicationArea( indicationAreaViewModel = indicationAreaViewModel, - alphaViewModel = alphaViewModel, indicationController = indicationController, ) } @@ -183,7 +180,6 @@ constructor( @Composable private fun IndicationArea( indicationAreaViewModel: KeyguardIndicationAreaViewModel, - alphaViewModel: AodAlphaViewModel, indicationController: KeyguardIndicationController, modifier: Modifier = Modifier, ) { @@ -196,7 +192,6 @@ constructor( KeyguardIndicationAreaBinder.bind( view = view, viewModel = indicationAreaViewModel, - aodAlphaViewModel = alphaViewModel, indicationController = indicationController, ) ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt index fa07bafda82c..335c915411ee 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/ClockSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.composable.section import android.view.ViewGroup import android.widget.FrameLayout +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -38,14 +39,17 @@ import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChange import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel +import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController import javax.inject.Inject -class ClockSection +/** Provides small clock and large clock composables for the default clock face. */ +class DefaultClockSection @Inject constructor( private val viewModel: KeyguardClockViewModel, private val clockInteractor: KeyguardClockInteractor, private val aodBurnInViewModel: AodBurnInViewModel, + private val lockscreenSmartspaceController: LockscreenSmartspaceController, ) { @Composable @@ -151,6 +155,7 @@ constructor( (newClockView.parent as? ViewGroup)?.removeView(newClockView) it.addView(newClockView) }, + modifier = Modifier.fillMaxSize() ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt index ed2cbb85ba1a..c7d43fcdf5e6 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt @@ -55,7 +55,7 @@ constructor( notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel, ambientState: AmbientState, notificationStackSizeCalculator: NotificationStackSizeCalculator, - @Main private val mainDispatcher: CoroutineDispatcher, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) { init { @@ -80,7 +80,7 @@ constructor( sceneContainerFlags, controller, notificationStackSizeCalculator, - mainDispatcher, + mainImmediateDispatcher = mainImmediateDispatcher, ) if (sceneContainerFlags.flexiNotifsEnabled()) { @@ -90,6 +90,7 @@ constructor( notificationStackAppearanceViewModel, ambientState, controller, + mainImmediateDispatcher = mainImmediateDispatcher, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt new file mode 100644 index 000000000000..2e7bc2a28c65 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.composable.section + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.android.compose.animation.scene.SceneScope +import javax.inject.Inject + +/** Provides small clock and large clock composables for the weather clock layout. */ +class WeatherClockSection @Inject constructor() { + @Composable + fun SceneScope.Time( + modifier: Modifier = Modifier, + ) { + // TODO: compose view + } + + @Composable + fun SceneScope.Date( + modifier: Modifier = Modifier, + ) { + // TODO: compose view + } + + @Composable + fun SceneScope.Weather( + modifier: Modifier = Modifier, + ) { + // TODO: compose view + } + + @Composable + fun SceneScope.DndAlarmStatus( + modifier: Modifier = Modifier, + ) { + // TODO: compose view + } + + @Composable + fun SceneScope.Temperature( + modifier: Modifier = Modifier, + ) { + // TODO: compose view + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ComposeAwareExtensions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ComposeAwareExtensions.kt index a7de1eede1f4..0de4650f1248 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ComposeAwareExtensions.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ComposeAwareExtensions.kt @@ -16,9 +16,6 @@ package com.android.systemui.scene.ui.composable -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.IntSize import com.android.compose.animation.scene.Back import com.android.compose.animation.scene.Edge as ComposeAwareEdge import com.android.compose.animation.scene.SceneKey as ComposeAwareSceneKey @@ -26,14 +23,12 @@ import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.TransitionKey as ComposeAwareTransitionKey import com.android.compose.animation.scene.UserAction as ComposeAwareUserAction -import com.android.compose.animation.scene.UserActionDistance as ComposeAwareUserActionDistance import com.android.compose.animation.scene.UserActionResult as ComposeAwareUserActionResult import com.android.systemui.scene.shared.model.Direction import com.android.systemui.scene.shared.model.Edge import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.TransitionKey import com.android.systemui.scene.shared.model.UserAction -import com.android.systemui.scene.shared.model.UserActionDistance import com.android.systemui.scene.shared.model.UserActionResult // TODO(b/293899074): remove this file once we can use the types from SceneTransitionLayout. @@ -82,22 +77,5 @@ fun UserActionResult.asComposeAware(): ComposeAwareUserActionResult { return ComposeAwareUserActionResult( toScene = composeUnaware.toScene.asComposeAware(), transitionKey = composeUnaware.transitionKey?.asComposeAware(), - distance = composeUnaware.distance?.asComposeAware(), ) } - -fun UserActionDistance.asComposeAware(): ComposeAwareUserActionDistance { - val composeUnware = this - return object : ComposeAwareUserActionDistance { - override fun Density.absoluteDistance( - fromSceneSize: IntSize, - orientation: Orientation, - ): Float { - return composeUnware.absoluteDistance( - fromSceneWidth = fromSceneSize.width, - fromSceneHeight = fromSceneSize.height, - isHorizontal = orientation == Orientation.Horizontal, - ) - } - } -} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt index 30c82f46f01d..5c6e1c89ad65 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt @@ -13,6 +13,7 @@ fun TransitionBuilder.goneToShadeTransition( ) { spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt()) + fractionRange(start = .58f) { fade(ShadeHeader.Elements.Clock) } fractionRange(start = .58f) { fade(ShadeHeader.Elements.CollapsedContentStart) } fractionRange(start = .58f) { fade(ShadeHeader.Elements.CollapsedContentEnd) } fractionRange(start = .58f) { fade(ShadeHeader.Elements.PrivacyChip) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt index 3c15da12b647..ffb6f3109015 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt @@ -18,10 +18,15 @@ fun TransitionBuilder.shadeToQuickSettingsTransition() { y = ShadeHeader.Dimensions.CollapsedHeight ) translate(ShadeHeader.Elements.CollapsedContentEnd, y = ShadeHeader.Dimensions.CollapsedHeight) - translate(ShadeHeader.Elements.ExpandedContent, y = (-ShadeHeader.Dimensions.ExpandedHeight)) + translate( + ShadeHeader.Elements.ExpandedContent, + y = -(ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight) + ) + translate(ShadeHeader.Elements.ShadeCarrierGroup, y = -ShadeHeader.Dimensions.CollapsedHeight) fractionRange(end = .14f) { fade(ShadeHeader.Elements.CollapsedContentStart) } fractionRange(end = .14f) { fade(ShadeHeader.Elements.CollapsedContentEnd) } fractionRange(start = .58f) { fade(ShadeHeader.Elements.ExpandedContent) } + fractionRange(start = .58f) { fade(ShadeHeader.Elements.ShadeCarrierGroup) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt index 00b494b7f994..d7911eac8a61 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt @@ -19,6 +19,7 @@ package com.android.systemui.shade.ui.composable import android.view.ContextThemeWrapper import android.view.ViewGroup +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -52,6 +53,7 @@ import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexScenePicker import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.ValueKey +import com.android.compose.animation.scene.animateElementFloatAsState import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.settingslib.Utils @@ -64,6 +66,7 @@ import com.android.systemui.res.R import com.android.systemui.scene.ui.composable.QuickSettings import com.android.systemui.scene.ui.composable.Shade as ShadeKey import com.android.systemui.shade.ui.composable.ShadeHeader.Dimensions.CollapsedHeight +import com.android.systemui.shade.ui.composable.ShadeHeader.Values.ClockScale import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager @@ -79,12 +82,18 @@ object ShadeHeader { val CollapsedContentStart = ElementKey("ShadeHeaderCollapsedContentStart") val CollapsedContentEnd = ElementKey("ShadeHeaderCollapsedContentEnd") val PrivacyChip = ElementKey("PrivacyChip", scenePicker = LowestZIndexScenePicker) + val Clock = ElementKey("ShadeHeaderClock", scenePicker = LowestZIndexScenePicker) + val ShadeCarrierGroup = ElementKey("ShadeCarrierGroup") } object Keys { val transitionProgress = ValueKey("ShadeHeaderTransitionProgress") } + object Values { + val ClockScale = ValueKey("ShadeHeaderClockScale") + } + object Dimensions { val CollapsedHeight = 48.dp val ExpandedHeight = 120.dp @@ -121,20 +130,18 @@ fun SceneScope.CollapsedShadeHeader( contents = listOf( { - Row(modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentStart)) { - AndroidView( - factory = { context -> - Clock( - ContextThemeWrapper(context, R.style.TextAppearance_QS_Status), - null - ) - }, + Row { + Clock( + scale = 1f, + viewModel = viewModel, modifier = Modifier.align(Alignment.CenterVertically), ) Spacer(modifier = Modifier.width(5.dp)) VariableDayDate( viewModel = viewModel, - modifier = Modifier.align(Alignment.CenterVertically), + modifier = + Modifier.element(ShadeHeader.Elements.CollapsedContentStart) + .align(Alignment.CenterVertically), ) } }, @@ -257,40 +264,29 @@ fun SceneScope.ExpandedShadeHeader( Column( verticalArrangement = Arrangement.Bottom, modifier = - Modifier.element(ShadeHeader.Elements.ExpandedContent) - .fillMaxWidth() + Modifier.fillMaxWidth() .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight) ) { - Row { - AndroidView( - factory = { context -> - Clock(ContextThemeWrapper(context, R.style.TextAppearance_QS_Status), null) - }, + Box(modifier = Modifier.fillMaxWidth()) { + Box { + Clock( + scale = 2.57f, + viewModel = viewModel, + modifier = Modifier.align(Alignment.CenterStart), + ) + } + Box( modifier = - Modifier.align(Alignment.CenterVertically) - // use graphicsLayer instead of Modifier.scale to anchor transform to - // the (start, top) corner - .graphicsLayer( - scaleX = 2.57f, - scaleY = 2.57f, - transformOrigin = - TransformOrigin( - when (LocalLayoutDirection.current) { - LayoutDirection.Ltr -> 0f - LayoutDirection.Rtl -> 1f - }, - 0.5f - ) - ), - ) - Spacer(modifier = Modifier.weight(1f)) - ShadeCarrierGroup( - viewModel = viewModel, - modifier = Modifier.align(Alignment.CenterVertically), - ) + Modifier.element(ShadeHeader.Elements.ShadeCarrierGroup).fillMaxWidth() + ) { + ShadeCarrierGroup( + viewModel = viewModel, + modifier = Modifier.align(Alignment.CenterEnd), + ) + } } Spacer(modifier = Modifier.width(5.dp)) - Row { + Row(modifier = Modifier.element(ShadeHeader.Elements.ExpandedContent)) { VariableDayDate( viewModel = viewModel, modifier = Modifier.widthIn(max = 90.dp).align(Alignment.CenterVertically), @@ -319,6 +315,41 @@ fun SceneScope.ExpandedShadeHeader( } @Composable +private fun SceneScope.Clock( + scale: Float, + viewModel: ShadeHeaderViewModel, + modifier: Modifier, +) { + val layoutDirection = LocalLayoutDirection.current + + Element(key = ShadeHeader.Elements.Clock, modifier = modifier) { + val animatedScale by animateElementFloatAsState(scale, ClockScale, canOverflow = false) + AndroidView( + factory = { context -> + Clock(ContextThemeWrapper(context, R.style.TextAppearance_QS_Status), null) + }, + modifier = + modifier + // use graphicsLayer instead of Modifier.scale to anchor transform + // to the (start, top) corner + .graphicsLayer { + scaleX = animatedScale + scaleY = animatedScale + transformOrigin = + TransformOrigin( + when (layoutDirection) { + LayoutDirection.Ltr -> 0f + LayoutDirection.Rtl -> 1f + }, + 0.5f + ) + } + .clickable { viewModel.onClockClicked() } + ) + } +} + +@Composable private fun BatteryIcon( createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, useExpandedFormat: Boolean, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index ff6e89548a75..2e0ce42ee713 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -28,6 +28,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -42,6 +43,7 @@ import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexScenePicker import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.animateSceneFloatAsState +import com.android.compose.modifiers.thenIf import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -163,6 +165,7 @@ private fun SceneScope.ShadeScene( val maxNotifScrimTop = remember { mutableStateOf(0f) } val tileSquishiness by animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness) + val isClickable by viewModel.isClickable.collectAsState() Box( modifier = @@ -178,8 +181,9 @@ private fun SceneScope.ShadeScene( Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = - Modifier.fillMaxWidth() - .clickable(onClick = { viewModel.onContentClicked() }) + Modifier.fillMaxWidth().thenIf(isClickable) { + Modifier.clickable(onClick = { viewModel.onContentClicked() }) + } ) { CollapsedShadeHeader( viewModel = viewModel.shadeHeaderViewModel, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt new file mode 100644 index 000000000000..453ff026a8a0 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/VolumeSlidersModule.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume + +import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents +import com.android.systemui.volume.panel.component.volume.ui.composable.VolumeSlidersComponent +import com.android.systemui.volume.panel.domain.AlwaysAvailableCriteria +import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria +import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface VolumeSlidersModule { + + @Binds + @IntoMap + @StringKey(VolumePanelComponents.VOLUME_SLIDERS) + fun bindVolumePanelUiComponent(component: VolumeSlidersComponent): VolumePanelUiComponent + + @Binds + @IntoMap + @StringKey(VolumePanelComponents.VOLUME_SLIDERS) + fun bindComponentAvailabilityCriteria( + criteria: AlwaysAvailableCriteria + ): ComponentAvailabilityCriteria +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt new file mode 100644 index 000000000000..ddc9252a5a4a --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.ui.composable + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.android.compose.PlatformSliderColors +import com.android.systemui.res.R +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel + +private const val EXPAND_DURATION_MILLIS = 500 +private const val COLLAPSE_DURATION_MILLIS = 300 + +/** Volume sliders laid out in a collapsable column */ +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun ColumnVolumeSliders( + viewModels: List<SliderViewModel>, + sliderColors: PlatformSliderColors, + isExpandable: Boolean, + modifier: Modifier = Modifier, +) { + require(viewModels.isNotEmpty()) + var isExpanded: Boolean by remember(isExpandable) { mutableStateOf(!isExpandable) } + val transition = updateTransition(isExpanded, label = "CollapsableSliders") + Column(modifier = modifier.verticalScroll(rememberScrollState())) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + val sliderViewModel: SliderViewModel = viewModels.first() + val sliderState by viewModels.first().slider.collectAsState() + VolumeSlider( + modifier = Modifier.weight(1f), + state = sliderState, + onValueChangeFinished = { sliderViewModel.onValueChangeFinished(sliderState, it) }, + sliderColors = sliderColors, + ) + + if (isExpandable) { + ExpandButton( + isExpanded = isExpanded, + onExpandedChanged = { isExpanded = it }, + sliderColors, + Modifier, + ) + } + } + transition.AnimatedVisibility( + visible = { it }, + enter = + expandVertically( + animationSpec = tween(durationMillis = EXPAND_DURATION_MILLIS), + expandFrom = Alignment.CenterVertically, + ), + exit = + shrinkVertically( + animationSpec = tween(durationMillis = COLLAPSE_DURATION_MILLIS), + shrinkTowards = Alignment.CenterVertically, + ), + ) { + Column(modifier = Modifier.fillMaxWidth()) { + for (index in 1..viewModels.lastIndex) { + val sliderViewModel: SliderViewModel = viewModels[index] + val sliderState by sliderViewModel.slider.collectAsState() + transition.AnimatedVisibility( + visible = { it }, + enter = enterTransition(index = index, totalCount = viewModels.size), + exit = exitTransition(index = index, totalCount = viewModels.size) + ) { + VolumeSlider( + modifier = Modifier.fillMaxWidth().padding(top = 16.dp), + state = sliderState, + onValueChangeFinished = { + sliderViewModel.onValueChangeFinished(sliderState, it) + }, + sliderColors = sliderColors, + ) + } + } + } + } + } +} + +@Composable +private fun ExpandButton( + isExpanded: Boolean, + onExpandedChanged: (Boolean) -> Unit, + sliderColors: PlatformSliderColors, + modifier: Modifier = Modifier, +) { + IconButton( + modifier = modifier.size(64.dp), + onClick = { onExpandedChanged(!isExpanded) }, + colors = + IconButtonDefaults.filledIconButtonColors( + containerColor = sliderColors.indicatorColor, + contentColor = sliderColors.iconColor + ), + ) { + Icon( + painter = + painterResource( + if (isExpanded) { + R.drawable.ic_filled_arrow_down + } else { + R.drawable.ic_filled_arrow_up + } + ), + contentDescription = null, + ) + } +} + +private fun enterTransition(index: Int, totalCount: Int): EnterTransition { + val enterDelay = ((totalCount - index + 1) * 10).coerceAtLeast(0) + val enterDuration = (EXPAND_DURATION_MILLIS - enterDelay).coerceAtLeast(100) + return slideInVertically( + initialOffsetY = { (it * 0.25).toInt() }, + animationSpec = tween(durationMillis = enterDuration, delayMillis = enterDelay), + ) + + scaleIn( + initialScale = 0.9f, + animationSpec = tween(durationMillis = enterDuration, delayMillis = enterDelay), + ) + + expandVertically( + initialHeight = { (it * 0.65).toInt() }, + animationSpec = tween(durationMillis = enterDuration, delayMillis = enterDelay), + clip = false, + expandFrom = Alignment.CenterVertically, + ) + + fadeIn( + animationSpec = tween(durationMillis = enterDuration, delayMillis = enterDelay), + ) +} + +private fun exitTransition(index: Int, totalCount: Int): ExitTransition { + val exitDuration = (COLLAPSE_DURATION_MILLIS - (totalCount - index + 1) * 10).coerceAtLeast(100) + return slideOutVertically( + targetOffsetY = { (it * 0.25).toInt() }, + animationSpec = tween(durationMillis = exitDuration), + ) + + scaleOut( + targetScale = 0.9f, + animationSpec = tween(durationMillis = exitDuration), + ) + + shrinkVertically( + targetHeight = { (it * 0.65).toInt() }, + animationSpec = tween(durationMillis = exitDuration), + clip = false, + shrinkTowards = Alignment.CenterVertically, + ) + + fadeOut(animationSpec = tween(durationMillis = exitDuration)) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt new file mode 100644 index 000000000000..910ee7285bdb --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.ui.composable + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.android.compose.PlatformSliderColors +import com.android.compose.grid.VerticalGrid +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel + +@Composable +fun GridVolumeSliders( + viewModels: List<SliderViewModel>, + sliderColors: PlatformSliderColors, + modifier: Modifier = Modifier, +) { + require(viewModels.isNotEmpty()) + VerticalGrid( + modifier = modifier, + columns = 2, + verticalSpacing = 16.dp, + horizontalSpacing = 24.dp, + ) { + for (sliderViewModel in viewModels) { + val sliderState = sliderViewModel.slider.collectAsState().value + VolumeSlider( + modifier = Modifier.fillMaxWidth(), + state = sliderState, + onValueChangeFinished = { sliderViewModel.onValueChangeFinished(sliderState, it) }, + sliderColors = sliderColors, + ) + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt new file mode 100644 index 000000000000..0d94bb06c06f --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.ui.composable + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import com.android.compose.PlatformSlider +import com.android.compose.PlatformSliderColors +import com.android.systemui.common.ui.compose.Icon +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderState + +@Composable +fun VolumeSlider( + state: SliderState, + onValueChangeFinished: (Float) -> Unit, + modifier: Modifier = Modifier, + sliderColors: PlatformSliderColors, +) { + var value by remember(state.value) { mutableFloatStateOf(state.value) } + PlatformSlider( + modifier = modifier, + value = value, + valueRange = state.valueRange, + onValueChange = { value = it }, + onValueChangeFinished = { onValueChangeFinished(value) }, + enabled = state.isEnabled, + icon = { isDragging -> + if (isDragging) { + Text(text = value.toInt().toString()) + } else { + state.icon?.let { Icon(icon = it) } + } + }, + colors = sliderColors, + label = { + Column(modifier = Modifier.animateContentSize()) { + Text(state.label, style = MaterialTheme.typography.titleMedium) + + state.disabledMessage?.let { message -> + AnimatedVisibility( + !state.isEnabled, + enter = expandVertically { it }, + exit = shrinkVertically { it }, + ) { + Text(text = message, style = MaterialTheme.typography.bodySmall) + } + } + } + } + ) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlidersComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlidersComponent.kt new file mode 100644 index 000000000000..1ca18deeaac2 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlidersComponent.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.ui.composable + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.android.compose.PlatformSliderDefaults +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel +import com.android.systemui.volume.panel.component.volume.ui.viewmodel.AudioVolumeComponentViewModel +import com.android.systemui.volume.panel.ui.composable.ComposeVolumePanelUiComponent +import com.android.systemui.volume.panel.ui.composable.VolumePanelComposeScope +import com.android.systemui.volume.panel.ui.composable.isPortrait +import javax.inject.Inject + +class VolumeSlidersComponent +@Inject +constructor( + private val viewModel: AudioVolumeComponentViewModel, +) : ComposeVolumePanelUiComponent { + + @Composable + override fun VolumePanelComposeScope.Content(modifier: Modifier) { + val sliderViewModels: List<SliderViewModel> by viewModel.sliderViewModels.collectAsState() + if (sliderViewModels.isEmpty()) { + return + } + if (isLargeScreen) { + GridVolumeSliders( + viewModels = sliderViewModels, + sliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(), + modifier = modifier.fillMaxWidth(), + ) + } else { + ColumnVolumeSliders( + viewModels = sliderViewModels, + sliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(), + isExpandable = isPortrait, + modifier = modifier.fillMaxWidth(), + ) + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/HorizontalVolumePanelContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/HorizontalVolumePanelContent.kt index 98ef0674e8a1..a838a99524a3 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/HorizontalVolumePanelContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/HorizontalVolumePanelContent.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -51,20 +50,21 @@ fun VolumePanelComposeScope.HorizontalVolumePanelContent( verticalArrangement = Arrangement.spacedBy(space = spacing, alignment = Alignment.Top) ) { for (component in layout.headerComponents) { - AnimatedVisibility(component.isVisible) { - with(component.component as ComposeVolumePanelUiComponent) { - Content(Modifier.weight(1f)) - } + AnimatedVisibility(visible = component.isVisible) { + with(component.component as ComposeVolumePanelUiComponent) { Content(Modifier) } } } Row( - modifier = Modifier.fillMaxWidth().wrapContentHeight(), + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(spacing), ) { for (component in layout.footerComponents) { - AnimatedVisibility(component.isVisible) { + AnimatedVisibility( + visible = component.isVisible, + modifier = Modifier.weight(1f), + ) { with(component.component as ComposeVolumePanelUiComponent) { - Content(Modifier.weight(1f)) + Content(Modifier) } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt index 22851286354c..4d073798c70c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt @@ -17,7 +17,6 @@ package com.android.systemui.volume.panel.ui.composable import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.animateContentSize import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -34,14 +33,12 @@ fun VolumePanelComposeScope.VerticalVolumePanelContent( modifier: Modifier = Modifier, ) { Column( - modifier = modifier.animateContentSize(), + modifier = modifier, verticalArrangement = Arrangement.spacedBy(20.dp), ) { for (component in layout.headerComponents) { AnimatedVisibility(component.isVisible) { - with(component.component as ComposeVolumePanelUiComponent) { - Content(Modifier.weight(1f)) - } + with(component.component as ComposeVolumePanelUiComponent) { Content(Modifier) } } } for (component in layout.contentComponents) { @@ -55,9 +52,12 @@ fun VolumePanelComposeScope.VerticalVolumePanelContent( horizontalArrangement = Arrangement.spacedBy(if (isLargeScreen) 28.dp else 20.dp), ) { for (component in layout.footerComponents) { - AnimatedVisibility(component.isVisible) { + AnimatedVisibility( + visible = component.isVisible, + modifier = Modifier.weight(1f), + ) { with(component.component as ComposeVolumePanelUiComponent) { - Content(Modifier.weight(1f)) + Content(Modifier) } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelComposeScope.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelComposeScope.kt index 8df8d2e81b51..af6909102cf3 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelComposeScope.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelComposeScope.kt @@ -29,7 +29,7 @@ class VolumePanelComposeScope(private val state: VolumePanelState) { /** Is true when Volume Panel is using large-screen layout and false the otherwise. */ val isLargeScreen: Boolean - get() = state.isWideScreen + get() = state.isLargeScreen } val VolumePanelComposeScope.isPortrait: Boolean diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt index 8a1e6a8b74f4..8a9ebc918be6 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt @@ -16,7 +16,6 @@ package com.android.systemui.volume.panel.ui.composable -import android.content.res.Configuration import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement @@ -111,15 +110,24 @@ private fun VolumePanelComposeScope.Components( layout: ComponentsLayout, modifier: Modifier = Modifier ) { - var columnModifier = modifier.widthIn(max = 800.dp) - if (!isLargeScreen && orientation != Configuration.ORIENTATION_PORTRAIT) { - columnModifier = columnModifier.heightIn(max = 332.dp) - } - Column(modifier = columnModifier, verticalArrangement = Arrangement.spacedBy(padding)) { - if (orientation == Configuration.ORIENTATION_PORTRAIT || isLargeScreen) { - VerticalVolumePanelContent(layout) + val arrangement = + if (isLargeScreen) { + Arrangement.spacedBy(20.dp) + } else { + if (isPortrait) Arrangement.spacedBy(padding) else Arrangement.spacedBy(4.dp) + } + Column( + modifier = modifier.widthIn(max = 800.dp), + verticalArrangement = arrangement, + ) { + val contentModifier = Modifier + if (isPortrait || isLargeScreen) { + VerticalVolumePanelContent(modifier = contentModifier, layout = layout) } else { - HorizontalVolumePanelContent(layout) + HorizontalVolumePanelContent( + modifier = contentModifier.heightIn(max = 212.dp), + layout = layout + ) } BottomBar(layout = layout, modifier = Modifier) } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt index 2e781e69bb4a..c7186da6b961 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt @@ -39,7 +39,6 @@ import androidx.compose.ui.layout.Placeable import androidx.compose.ui.node.DrawModifierNode import androidx.compose.ui.node.ModifierNodeElement import androidx.compose.ui.platform.testTag -import androidx.compose.ui.semantics.testTag import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.round @@ -204,6 +203,17 @@ internal class ElementNode( measurable: Measurable, constraints: Constraints, ): MeasureResult { + val overscrollScene = layoutImpl.state.currentOverscrollSpec?.scene + if (overscrollScene != null && overscrollScene != scene.key) { + // There is an overscroll in progress on another scene + // By measuring composable elements, Compose can cache relevant information. + // This reduces the need for re-measure when users return from an overscroll animation. + val placeable = measurable.measure(constraints) + return layout(placeable.width, placeable.height) { + // We don't want to draw it, no need to place the element. + } + } + val placeable = measure(layoutImpl, scene, element, sceneState, measurable, constraints) return layout(placeable.width, placeable.height) { place(layoutImpl, scene, element, sceneState, placeable, placementScope = this) @@ -253,11 +263,13 @@ private fun shouldDrawElement( ): Boolean { val transition = layoutImpl.state.currentTransition - // Always draw the element if there is no ongoing transition or if the element is not shared. + // Always draw the element if there is no ongoing transition or if the element is not shared or + // if the current scene is the one that is currently over scrolling with [OverscrollSpec]. if ( transition == null || transition.fromScene !in element.sceneStates || - transition.toScene !in element.sceneStates + transition.toScene !in element.sceneStates || + layoutImpl.state.currentOverscrollSpec?.scene == scene.key ) { return true } @@ -286,12 +298,14 @@ internal fun shouldDrawOrComposeSharedElement( val fromScene = transition.fromScene val toScene = transition.toScene - return scenePicker.sceneDuringTransition( - element = element, - transition = transition, - fromSceneZIndex = layoutImpl.scenes.getValue(fromScene).zIndex, - toSceneZIndex = layoutImpl.scenes.getValue(toScene).zIndex, - ) == scene + val chosenByPicker = + scenePicker.sceneDuringTransition( + element = element, + transition = transition, + fromSceneZIndex = layoutImpl.scenes.getValue(fromScene).zIndex, + toSceneZIndex = layoutImpl.scenes.getValue(toScene).zIndex, + ) == scene + return chosenByPicker || layoutImpl.state.currentOverscrollSpec?.scene == scene } private fun isSharedElementEnabled( @@ -549,6 +563,40 @@ private inline fun <T> computeValue( return idleValue } + if (transition is TransitionState.HasOverscrollProperties) { + val overscroll = layoutImpl.state.currentOverscrollSpec + if (overscroll?.scene == scene.key) { + val elementSpec = overscroll.transformationSpec.transformations(element.key, scene.key) + val propertySpec = transformation(elementSpec) ?: return currentValue() + val overscrollState = checkNotNull(if (scene.key == toScene) toState else fromState) + val targetValue = + propertySpec.transform( + layoutImpl, + scene, + element, + overscrollState, + transition, + idleValue, + ) + + // Make sure we don't read progress if values are the same and we don't need to + // interpolate, so we don't invalidate the phase where this is read. + if (targetValue == idleValue) { + return targetValue + } + + // TODO(b/290184746): Make sure that we don't overflow transformations associated to a + // range. + val directionSign = if (transition.isUpOrLeft) -1 else 1 + val overscrollProgress = transition.progress.let { if (it > 1f) it - 1f else it } + val progress = directionSign * overscrollProgress + val rangeProgress = propertySpec.range?.progress(progress) ?: progress + + // Interpolate between the value at rest and the over scrolled value. + return lerp(idleValue, targetValue, rangeProgress) + } + } + // The element is shared: interpolate between the value in fromScene and the value in toScene. // TODO(b/290184746): Support non linear shared paths as well as a way to make sure that shared // elements follow the finger direction. diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt index 76e7c95f274a..187d82a9e626 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt @@ -27,7 +27,6 @@ import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.round @@ -56,14 +55,17 @@ internal class SceneGestureHandler( if (isDrivingTransition || force) { layoutState.startTransition(newTransition, newTransition.key) - // Initialize SwipeTransition.swipeSpec. Note that this must be called right after - // layoutState.startTransition() is called, because it computes the - // layoutState.transformationSpec(). + // Initialize SwipeTransition.transformationSpec and .swipeSpec. Note that this must be + // called right after layoutState.startTransition() is called, because it computes the + // current layoutState.transformationSpec(). + val transformationSpec = layoutState.transformationSpec + newTransition.transformationSpec = transformationSpec newTransition.swipeSpec = - layoutState.transformationSpec.swipeSpec ?: layoutState.transitions.defaultSwipeSpec + transformationSpec.swipeSpec ?: layoutState.transitions.defaultSwipeSpec } else { - // We were not driving the transition and we don't force the update, so the spec won't - // be used and it doesn't matter which one we set here. + // We were not driving the transition and we don't force the update, so the specs won't + // be used and it doesn't matter which ones we set here. + newTransition.transformationSpec = TransformationSpec.Empty newTransition.swipeSpec = SceneTransitions.DefaultSwipeSpec } @@ -285,16 +287,21 @@ internal class SceneGestureHandler( ): Pair<Scene, Float> { val toScene = swipeTransition._toScene val fromScene = swipeTransition._fromScene - val absoluteDistance = swipeTransition.distance.absoluteValue + val distance = swipeTransition.distance() - // If the swipe was not committed, don't do anything. - if (swipeTransition._currentScene != toScene) { + // If the swipe was not committed or if the swipe distance is not computed yet, don't do + // anything. + if ( + swipeTransition._currentScene != toScene || + distance == SwipeTransition.DistanceUnspecified + ) { return fromScene to 0f } // If the offset is past the distance then let's change fromScene so that the user can swipe // to the next screen or go back to the previous one. val offset = swipeTransition.dragOffset + val absoluteDistance = distance.absoluteValue return if (offset <= -absoluteDistance && swipes!!.upOrLeftResult?.toScene == toScene.key) { toScene to absoluteDistance } else if ( @@ -347,16 +354,17 @@ internal class SceneGestureHandler( // Compute the destination scene (and therefore offset) to settle in. val offset = swipeTransition.dragOffset - val distance = swipeTransition.distance + val distance = swipeTransition.distance() var targetScene: Scene var targetOffset: Float if ( - shouldCommitSwipe( - offset, - distance, - velocity, - wasCommitted = swipeTransition._currentScene == toScene, - ) + distance != SwipeTransition.DistanceUnspecified && + shouldCommitSwipe( + offset, + distance, + velocity, + wasCommitted = swipeTransition._currentScene == toScene, + ) ) { targetScene = toScene targetOffset = distance @@ -372,7 +380,15 @@ internal class SceneGestureHandler( // We wanted to change to a new scene but we are not allowed to, so we animate back // to the current scene. targetScene = swipeTransition._currentScene - targetOffset = if (targetScene == fromScene) 0f else distance + targetOffset = + if (targetScene == fromScene) { + 0f + } else { + check(distance != SwipeTransition.DistanceUnspecified) { + "distance is equal to ${SwipeTransition.DistanceUnspecified}" + } + distance + } } animateTo(targetScene = targetScene, targetOffset = targetOffset) @@ -459,22 +475,20 @@ private fun SwipeTransition( ): SwipeTransition { val upOrLeftResult = swipes.upOrLeftResult val downOrRightResult = swipes.downOrRightResult - val userActionDistance = result.distance ?: DefaultSwipeDistance - val absoluteDistance = - with(userActionDistance) { - layoutImpl.density.absoluteDistance(fromScene.targetSize, orientation) + val isUpOrLeft = + when (result) { + upOrLeftResult -> true + downOrRightResult -> false + else -> error("Unknown result $result ($upOrLeftResult $downOrRightResult)") } return SwipeTransition( key = result.transitionKey, _fromScene = fromScene, _toScene = layoutImpl.scene(result.toScene), - distance = - when (result) { - upOrLeftResult -> -absoluteDistance - downOrRightResult -> absoluteDistance - else -> error("Unknown result $result ($upOrLeftResult $downOrRightResult)") - }, + userActionDistanceScope = layoutImpl.userActionDistanceScope, + orientation = orientation, + isUpOrLeft = isUpOrLeft, ) } @@ -482,19 +496,28 @@ private class SwipeTransition( val key: TransitionKey?, val _fromScene: Scene, val _toScene: Scene, - /** - * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is above - * or to the left of [toScene] - */ - val distance: Float, -) : TransitionState.Transition(_fromScene.key, _toScene.key) { + private val userActionDistanceScope: UserActionDistanceScope, + override val orientation: Orientation, + override val isUpOrLeft: Boolean, +) : + TransitionState.Transition(_fromScene.key, _toScene.key), + TransitionState.HasOverscrollProperties { var _currentScene by mutableStateOf(_fromScene) override val currentScene: SceneKey get() = _currentScene.key override val progress: Float get() { + // Important: If we are going to return early because distance is equal to 0, we should + // still make sure we read the offset before returning so that the calling code still + // subscribes to the offset value. val offset = if (isAnimatingOffset) offsetAnimatable.value else dragOffset + + val distance = distance() + if (distance == DistanceUnspecified) { + return 0f + } + return offset / distance } @@ -518,9 +541,50 @@ private class SwipeTransition( /** Job to check that there is at most one offset animation in progress. */ private var offsetAnimationJob: Job? = null + /** + * The [TransformationSpecImpl] associated to this transition. + * + * Note: This is lateinit because this [SwipeTransition] is needed by + * [BaseSceneTransitionLayoutState] to compute the [TransitionSpec], and it will be set right + * after [BaseSceneTransitionLayoutState.startTransition] is called with this transition. + */ + lateinit var transformationSpec: TransformationSpecImpl + /** The spec to use when animating this transition to either [fromScene] or [toScene]. */ lateinit var swipeSpec: SpringSpec<Float> + private var lastDistance = DistanceUnspecified + + /** + * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is above + * or to the left of [toScene]. + * + * Note that this distance can be equal to [DistanceUnspecified] during the first frame of a + * transition when the distance depends on the size or position of an element that is composed + * in the scene we are going to. + */ + fun distance(): Float { + if (lastDistance != DistanceUnspecified) { + return lastDistance + } + + val absoluteDistance = + with(transformationSpec.distance ?: DefaultSwipeDistance) { + userActionDistanceScope.absoluteDistance( + _fromScene.targetSize, + orientation, + ) + } + + if (absoluteDistance <= 0f) { + return DistanceUnspecified + } + + val distance = if (isUpOrLeft) -absoluteDistance else absoluteDistance + lastDistance = distance + return distance + } + /** Ends any previous [offsetAnimationJob] and runs the new [job]. */ private fun startOffsetAnimation(job: () -> Job) { cancelOffsetAnimation() @@ -563,6 +627,7 @@ private class SwipeTransition( } isAnimatingOffset = true + val animationSpec = transformationSpec offsetAnimatable.animateTo( targetValue = targetOffset, animationSpec = swipeSpec, @@ -571,10 +636,14 @@ private class SwipeTransition( finishOffsetAnimation() } + + companion object { + const val DistanceUnspecified = 0f + } } private object DefaultSwipeDistance : UserActionDistance { - override fun Density.absoluteDistance( + override fun UserActionDistanceScope.absoluteDistance( fromSceneSize: IntSize, orientation: Orientation, ): Float { @@ -722,14 +791,21 @@ internal class SceneNestedScrollHandler( ) fun hasNextScene(amount: Float): Boolean { - val fromScene = layoutImpl.scene(layoutState.transitionState.currentScene) + val transitionState = layoutState.transitionState + val scene = transitionState.currentScene + val fromScene = layoutImpl.scene(scene) val nextScene = when { amount < 0f -> fromScene.userActions[actionUpOrLeft] amount > 0f -> fromScene.userActions[actionDownOrRight] else -> null } - return nextScene != null + if (nextScene != null) return true + + if (transitionState !is TransitionState.Idle) return false + + val overscrollSpec = layoutImpl.state.transitions.overscrollSpec(scene, orientation) + return overscrollSpec != null } val source = this diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt index e1f8a0959f6f..1e3842a1de68 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density @@ -394,36 +395,52 @@ class UserActionResult( /** The scene we should be transitioning to during the [UserAction]. */ val toScene: SceneKey, - /** - * The distance the action takes to animate from 0% to 100%. - * - * If `null`, a default distance will be used that depends on the [UserAction] performed. - */ - val distance: UserActionDistance? = null, - /** The key of the transition that should be used. */ val transitionKey: TransitionKey? = null, -) { - constructor( - toScene: SceneKey, - distance: Dp, - transitionKey: TransitionKey? = null, - ) : this(toScene, FixedDistance(distance), transitionKey) -} +) interface UserActionDistance { /** * Return the **absolute** distance of the user action given the size of the scene we are * animating from and the [orientation]. + * + * Note: This function will be called for each drag event until it returns a value > 0f. This + * for instance allows you to return 0f or a negative value until the first layout pass of a + * scene, so that you can use the size and position of elements in the scene we are + * transitioning to when computing this absolute distance. */ - fun Density.absoluteDistance(fromSceneSize: IntSize, orientation: Orientation): Float + fun UserActionDistanceScope.absoluteDistance( + fromSceneSize: IntSize, + orientation: Orientation + ): Float +} + +interface UserActionDistanceScope : Density { + /** + * Return the *target* size of [this] element in the given [scene], i.e. the size of the element + * when idle, or `null` if the element is not composed and measured in that scene (yet). + */ + fun ElementKey.targetSize(scene: SceneKey): IntSize? + + /** + * Return the *target* offset of [this] element in the given [scene], i.e. the size of the + * element when idle, or `null` if the element is not composed and placed in that scene (yet). + */ + fun ElementKey.targetOffset(scene: SceneKey): Offset? + + /** + * Return the *target* size of [this] scene, i.e. the size of the scene when idle, or `null` if + * the scene was never composed. + */ + fun SceneKey.targetSize(): IntSize? } /** The user action has a fixed [absoluteDistance]. */ -private class FixedDistance(private val distance: Dp) : UserActionDistance { - override fun Density.absoluteDistance(fromSceneSize: IntSize, orientation: Orientation): Float { - return distance.toPx() - } +class FixedDistance(private val distance: Dp) : UserActionDistance { + override fun UserActionDistanceScope.absoluteDistance( + fromSceneSize: IntSize, + orientation: Orientation, + ): Float = distance.toPx() } /** diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt index 08399ff03f63..3093d477a24c 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt @@ -25,8 +25,13 @@ import androidx.compose.runtime.key import androidx.compose.runtime.snapshots.SnapshotStateMap import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ApproachLayoutModifierNode +import androidx.compose.ui.layout.ApproachMeasureScope import androidx.compose.ui.layout.LookaheadScope -import androidx.compose.ui.layout.intermediateLayout +import androidx.compose.ui.layout.Measurable +import androidx.compose.ui.layout.MeasureResult +import androidx.compose.ui.node.ModifierNodeElement +import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntSize import androidx.compose.ui.util.fastForEach @@ -96,9 +101,18 @@ internal class SceneTransitionLayoutImpl( ?: mutableMapOf<ValueKey, MutableMap<ElementKey?, SnapshotStateMap<SceneKey, *>>>() .also { _sharedValues = it } + // TODO(b/317958526): Lazily allocate scene gesture handlers the first time they are needed. private val horizontalGestureHandler: SceneGestureHandler private val verticalGestureHandler: SceneGestureHandler + private var _userActionDistanceScope: UserActionDistanceScope? = null + internal val userActionDistanceScope: UserActionDistanceScope + get() = + _userActionDistanceScope + ?: UserActionDistanceScopeImpl(layoutImpl = this).also { + _userActionDistanceScope = it + } + init { updateScenes(builder) @@ -172,7 +186,6 @@ internal class SceneTransitionLayoutImpl( } @Composable - @OptIn(ExperimentalComposeUiApi::class) internal fun Content(modifier: Modifier) { Box( modifier @@ -181,37 +194,7 @@ internal class SceneTransitionLayoutImpl( // swipes. .swipeToScene(horizontalGestureHandler) .swipeToScene(verticalGestureHandler) - // Animate the size of this layout. - .intermediateLayout { measurable, constraints -> - // Measure content normally. - val placeable = measurable.measure(constraints) - - val width: Int - val height: Int - val transition = state.currentTransition - if (transition == null) { - width = placeable.width - height = placeable.height - } else { - // Interpolate the size. - val fromSize = scene(transition.fromScene).targetSize - val toSize = scene(transition.toScene).targetSize - - // Optimization: make sure we don't read state.progress if fromSize == - // toSize to avoid running this code every frame when the layout size does - // not change. - if (fromSize == toSize) { - width = fromSize.width - height = fromSize.height - } else { - val size = lerp(fromSize, toSize, transition.progress) - width = size.width.coerceAtLeast(0) - height = size.height.coerceAtLeast(0) - } - } - - layout(width, height) { placeable.place(0, 0) } - } + .then(LayoutElement(layoutImpl = this)) ) { LookaheadScope { val scenesToCompose = @@ -254,3 +237,54 @@ internal class SceneTransitionLayoutImpl( scenes.values.forEach { it.targetSize = size } } } + +private data class LayoutElement(private val layoutImpl: SceneTransitionLayoutImpl) : + ModifierNodeElement<LayoutNode>() { + override fun create(): LayoutNode = LayoutNode(layoutImpl) + + override fun update(node: LayoutNode) { + node.layoutImpl = layoutImpl + } +} + +private class LayoutNode(var layoutImpl: SceneTransitionLayoutImpl) : + Modifier.Node(), ApproachLayoutModifierNode { + override fun isMeasurementApproachComplete(lookaheadSize: IntSize): Boolean { + return layoutImpl.state.currentTransition == null + } + + @ExperimentalComposeUiApi + override fun ApproachMeasureScope.approachMeasure( + measurable: Measurable, + constraints: Constraints, + ): MeasureResult { + // Measure content normally. + val placeable = measurable.measure(constraints) + + val width: Int + val height: Int + val transition = layoutImpl.state.currentTransition + if (transition == null) { + width = placeable.width + height = placeable.height + } else { + // Interpolate the size. + val fromSize = layoutImpl.scene(transition.fromScene).targetSize + val toSize = layoutImpl.scene(transition.toScene).targetSize + + // Optimization: make sure we don't read state.progress if fromSize == + // toSize to avoid running this code every frame when the layout size does + // not change. + if (fromSize == toSize) { + width = fromSize.width + height = fromSize.height + } else { + val size = lerp(fromSize, toSize, transition.progress) + width = size.width.coerceAtLeast(0) + height = size.height.coerceAtLeast(0) + } + } + + return layout(width, height) { placeable.place(0, 0) } + } +} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt index 662f33f3e88b..0fa19bb33818 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt @@ -16,6 +16,7 @@ package com.android.compose.animation.scene +import androidx.compose.foundation.gestures.Orientation import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.SideEffect @@ -221,6 +222,23 @@ sealed interface TransitionState { isTransitioning(from = other, to = scene) } } + + interface HasOverscrollProperties { + /** + * The position of the [TransitionState.Transition.toScene]. + * + * Used to understand the direction of the overscroll. + */ + val isUpOrLeft: Boolean + + /** + * The relative orientation between [TransitionState.Transition.fromScene] and + * [TransitionState.Transition.toScene]. + * + * Used to understand the orientation of the overscroll. + */ + val orientation: Orientation + } } internal abstract class BaseSceneTransitionLayoutState( @@ -237,6 +255,25 @@ internal abstract class BaseSceneTransitionLayoutState( */ internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty + private var fromOverscrollSpec: OverscrollSpecImpl? = null + private var toOverscrollSpec: OverscrollSpecImpl? = null + + /** + * @return the overscroll [OverscrollSpecImpl] if it is defined for the current + * [transitionState] and we are currently over scrolling. + */ + internal val currentOverscrollSpec: OverscrollSpecImpl? + get() { + val transition = currentTransition ?: return null + if (transition !is TransitionState.HasOverscrollProperties) return null + val progress = transition.progress + return when { + progress < 0f -> fromOverscrollSpec + progress > 1f -> toOverscrollSpec + else -> null + } + } + private val activeTransitionLinks = mutableMapOf<StateLink, LinkedTransition>() /** Whether we can transition to the given [scene]. */ @@ -266,10 +303,13 @@ internal abstract class BaseSceneTransitionLayoutState( transitionKey: TransitionKey?, ) { // Compute the [TransformationSpec] when the transition starts. + val fromScene = transition.fromScene + val toScene = transition.toScene + val orientation = (transition as? TransitionState.HasOverscrollProperties)?.orientation transformationSpec = - transitions - .transitionSpec(transition.fromScene, transition.toScene, key = transitionKey) - .transformationSpec() + transitions.transitionSpec(fromScene, toScene, key = transitionKey).transformationSpec() + fromOverscrollSpec = orientation?.let { transitions.overscrollSpec(fromScene, it) } + toOverscrollSpec = orientation?.let { transitions.overscrollSpec(toScene, it) } cancelActiveTransitionLinks() setupTransitionLinks(transition) transitionState = transition diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt index b8f9359463de..2dd41cd329a2 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt @@ -21,6 +21,7 @@ import androidx.compose.animation.core.Spring import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.snap import androidx.compose.animation.core.spring +import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.util.fastForEach @@ -41,18 +42,22 @@ class SceneTransitions internal constructor( internal val defaultSwipeSpec: SpringSpec<Float>, internal val transitionSpecs: List<TransitionSpecImpl>, + internal val overscrollSpecs: List<OverscrollSpecImpl>, ) { - private val cache = + private val transitionCache = mutableMapOf< SceneKey, MutableMap<SceneKey, MutableMap<TransitionKey?, TransitionSpecImpl>> >() + private val overscrollCache = + mutableMapOf<SceneKey, MutableMap<Orientation, OverscrollSpecImpl?>>() + internal fun transitionSpec( from: SceneKey, to: SceneKey, key: TransitionKey?, ): TransitionSpecImpl { - return cache + return transitionCache .getOrPut(from) { mutableMapOf() } .getOrPut(to) { mutableMapOf() } .getOrPut(key) { findSpec(from, to, key) } @@ -105,6 +110,28 @@ internal constructor( private fun defaultTransition(from: SceneKey, to: SceneKey) = TransitionSpecImpl(key = null, from, to, TransformationSpec.EmptyProvider) + internal fun overscrollSpec(scene: SceneKey, orientation: Orientation): OverscrollSpecImpl? = + overscrollCache + .getOrPut(scene) { mutableMapOf() } + .getOrPut(orientation) { overscroll(scene, orientation) { it.scene == scene } } + + private fun overscroll( + scene: SceneKey, + orientation: Orientation, + filter: (OverscrollSpecImpl) -> Boolean, + ): OverscrollSpecImpl? { + var match: OverscrollSpecImpl? = null + overscrollSpecs.fastForEach { spec -> + if (spec.orientation == orientation && filter(spec)) { + if (match != null) { + error("Found multiple transition specs for transition $scene") + } + match = spec + } + } + return match + } + companion object { internal val DefaultSwipeSpec = spring( @@ -112,7 +139,12 @@ internal constructor( visibilityThreshold = OffsetVisibilityThreshold, ) - val Empty = SceneTransitions(DefaultSwipeSpec, transitionSpecs = emptyList()) + val Empty = + SceneTransitions( + defaultSwipeSpec = DefaultSwipeSpec, + transitionSpecs = emptyList(), + overscrollSpecs = emptyList(), + ) } } @@ -139,7 +171,7 @@ interface TransitionSpec { */ fun reversed(): TransitionSpec - /* + /** * The [TransformationSpec] associated to this [TransitionSpec]. * * Note that this is called once every a transition associated to this [TransitionSpec] is @@ -163,6 +195,14 @@ interface TransformationSpec { */ val swipeSpec: SpringSpec<Float>? + /** + * The distance it takes for this transition to animate from 0% to 100% when it is driven by a + * [UserAction]. + * + * If `null`, a default distance will be used that depends on the [UserAction] performed. + */ + val distance: UserActionDistance? + /** The list of [Transformation] applied to elements during this transition. */ val transformations: List<Transformation> @@ -171,6 +211,7 @@ interface TransformationSpec { TransformationSpecImpl( progressSpec = snap(), swipeSpec = null, + distance = null, transformations = emptyList(), ) internal val EmptyProvider = { Empty } @@ -193,6 +234,7 @@ internal class TransitionSpecImpl( TransformationSpecImpl( progressSpec = reverse.progressSpec, swipeSpec = reverse.swipeSpec, + distance = reverse.distance, transformations = reverse.transformations.map { it.reversed() } ) } @@ -202,6 +244,24 @@ internal class TransitionSpecImpl( override fun transformationSpec(): TransformationSpecImpl = this.transformationSpec.invoke() } +/** The definition of the overscroll behavior of the [scene]. */ +interface OverscrollSpec { + /** The scene we are over scrolling. */ + val scene: SceneKey + + /** The orientation of this [OverscrollSpec]. */ + val orientation: Orientation + + /** The [TransformationSpec] associated to this [OverscrollSpec]. */ + val transformationSpec: TransformationSpec +} + +internal class OverscrollSpecImpl( + override val scene: SceneKey, + override val orientation: Orientation, + override val transformationSpec: TransformationSpecImpl, +) : OverscrollSpec + /** * An implementation of [TransformationSpec] that allows the quick retrieval of an element * [ElementTransformations]. @@ -209,6 +269,7 @@ internal class TransitionSpecImpl( internal class TransformationSpecImpl( override val progressSpec: AnimationSpec<Float>, override val swipeSpec: SpringSpec<Float>?, + override val distance: UserActionDistance?, override val transformations: List<Transformation>, ) : TransformationSpec { private val cache = mutableMapOf<ElementKey, MutableMap<SceneKey, ElementTransformations>>() diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt index d93911d2de42..bc52a28279dc 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt @@ -18,6 +18,7 @@ package com.android.compose.animation.scene import androidx.compose.animation.core.AnimationSpec import androidx.compose.animation.core.SpringSpec +import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -72,23 +73,30 @@ interface SceneTransitionsBuilder { key: TransitionKey? = null, builder: TransitionBuilder.() -> Unit = {}, ): TransitionSpec -} -@TransitionDsl -interface TransitionBuilder : PropertyTransformationBuilder { /** - * The [AnimationSpec] used to animate the associated transition progress from `0` to `1` when - * the transition is triggered (i.e. it is not gesture-based). + * Define the animation to be played when the [scene] is overscrolled in the given + * [orientation]. + * + * The overscroll animation always starts from a progress of 0f, and reaches 1f when moving the + * [distance] down/right, -1f when moving in the opposite direction. */ - var spec: AnimationSpec<Float> + fun overscroll( + scene: SceneKey, + orientation: Orientation, + builder: OverscrollBuilder.() -> Unit = {}, + ): OverscrollSpec +} +@TransitionDsl +interface OverscrollBuilder : PropertyTransformationBuilder { /** - * The [SpringSpec] used to animate the associated transition progress when the transition was - * started by a swipe and is now animating back to a scene because the user lifted their finger. + * The distance it takes for this transition to animate from 0% to 100% when it is driven by a + * [UserAction]. * - * If `null`, then the [SceneTransitionsBuilder.defaultSwipeSpec] will be used. + * If `null`, a default distance will be used that depends on the [UserAction] performed. */ - var swipeSpec: SpringSpec<Float>? + var distance: UserActionDistance? /** * Define a progress-based range for the transformations inside [builder]. @@ -109,6 +117,23 @@ interface TransitionBuilder : PropertyTransformationBuilder { end: Float? = null, builder: PropertyTransformationBuilder.() -> Unit, ) +} + +@TransitionDsl +interface TransitionBuilder : OverscrollBuilder, PropertyTransformationBuilder { + /** + * The [AnimationSpec] used to animate the associated transition progress from `0` to `1` when + * the transition is triggered (i.e. it is not gesture-based). + */ + var spec: AnimationSpec<Float> + + /** + * The [SpringSpec] used to animate the associated transition progress when the transition was + * started by a swipe and is now animating back to a scene because the user lifted their finger. + * + * If `null`, then the [SceneTransitionsBuilder.defaultSwipeSpec] will be used. + */ + var swipeSpec: SpringSpec<Float>? /** * Define a timestamp-based range for the transformations inside [builder]. diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt index 9b16d46bfcc8..65e8ea5cc341 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt @@ -21,7 +21,9 @@ import androidx.compose.animation.core.DurationBasedAnimationSpec import androidx.compose.animation.core.Spring import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.VectorConverter +import androidx.compose.animation.core.snap import androidx.compose.animation.core.spring +import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.Dp import com.android.compose.animation.scene.transformation.AnchoredSize @@ -41,13 +43,18 @@ internal fun transitionsImpl( builder: SceneTransitionsBuilder.() -> Unit, ): SceneTransitions { val impl = SceneTransitionsBuilderImpl().apply(builder) - return SceneTransitions(impl.defaultSwipeSpec, impl.transitionSpecs) + return SceneTransitions( + impl.defaultSwipeSpec, + impl.transitionSpecs, + impl.transitionOverscrollSpecs + ) } private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder { override var defaultSwipeSpec: SpringSpec<Float> = SceneTransitions.DefaultSwipeSpec val transitionSpecs = mutableListOf<TransitionSpecImpl>() + val transitionOverscrollSpecs = mutableListOf<OverscrollSpecImpl>() override fun to( to: SceneKey, @@ -66,6 +73,25 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder { return transition(from = from, to = to, key = key, builder) } + override fun overscroll( + scene: SceneKey, + orientation: Orientation, + builder: OverscrollBuilder.() -> Unit + ): OverscrollSpec { + fun transformationSpec(): TransformationSpecImpl { + val impl = OverscrollBuilderImpl().apply(builder) + return TransformationSpecImpl( + progressSpec = snap(), + swipeSpec = null, + distance = impl.distance, + transformations = impl.transformations, + ) + } + val spec = OverscrollSpecImpl(scene, orientation, transformationSpec()) + transitionOverscrollSpecs.add(spec) + return spec + } + private fun transition( from: SceneKey?, to: SceneKey?, @@ -77,6 +103,7 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder { return TransformationSpecImpl( progressSpec = impl.spec, swipeSpec = impl.swipeSpec, + distance = impl.distance, transformations = impl.transformations, ) } @@ -87,27 +114,11 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder { } } -internal class TransitionBuilderImpl : TransitionBuilder { +internal open class OverscrollBuilderImpl : OverscrollBuilder { val transformations = mutableListOf<Transformation>() - override var spec: AnimationSpec<Float> = spring(stiffness = Spring.StiffnessLow) - override var swipeSpec: SpringSpec<Float>? = null - private var range: TransformationRange? = null - private var reversed = false - private val durationMillis: Int by lazy { - val spec = spec - if (spec !is DurationBasedAnimationSpec) { - error("timestampRange {} can only be used with a DurationBasedAnimationSpec") - } - - spec.vectorize(Float.VectorConverter).durationMillis - } - - override fun reversed(builder: TransitionBuilder.() -> Unit) { - reversed = true - builder() - reversed = false - } + protected var reversed = false + override var distance: UserActionDistance? = null override fun fractionRange( start: Float?, @@ -119,28 +130,6 @@ internal class TransitionBuilderImpl : TransitionBuilder { range = null } - override fun sharedElement(matcher: ElementMatcher, enabled: Boolean) { - transformations.add(SharedElementTransformation(matcher, enabled)) - } - - override fun timestampRange( - startMillis: Int?, - endMillis: Int?, - builder: PropertyTransformationBuilder.() -> Unit - ) { - if (startMillis != null && (startMillis < 0 || startMillis > durationMillis)) { - error("invalid start value: startMillis=$startMillis durationMillis=$durationMillis") - } - - if (endMillis != null && (endMillis < 0 || endMillis > durationMillis)) { - error("invalid end value: endMillis=$startMillis durationMillis=$durationMillis") - } - - val start = startMillis?.let { it.toFloat() / durationMillis } - val end = endMillis?.let { it.toFloat() / durationMillis } - fractionRange(start, end, builder) - } - private fun transformation(transformation: PropertyTransformation<*>) { val transformation = if (range != null) { @@ -195,3 +184,45 @@ internal class TransitionBuilderImpl : TransitionBuilder { transformation(AnchoredSize(matcher, anchor, anchorWidth, anchorHeight)) } } + +internal class TransitionBuilderImpl : OverscrollBuilderImpl(), TransitionBuilder { + override var spec: AnimationSpec<Float> = spring(stiffness = Spring.StiffnessLow) + override var swipeSpec: SpringSpec<Float>? = null + override var distance: UserActionDistance? = null + private val durationMillis: Int by lazy { + val spec = spec + if (spec !is DurationBasedAnimationSpec) { + error("timestampRange {} can only be used with a DurationBasedAnimationSpec") + } + + spec.vectorize(Float.VectorConverter).durationMillis + } + + override fun reversed(builder: TransitionBuilder.() -> Unit) { + reversed = true + builder() + reversed = false + } + + override fun sharedElement(matcher: ElementMatcher, enabled: Boolean) { + transformations.add(SharedElementTransformation(matcher, enabled)) + } + + override fun timestampRange( + startMillis: Int?, + endMillis: Int?, + builder: PropertyTransformationBuilder.() -> Unit + ) { + if (startMillis != null && (startMillis < 0 || startMillis > durationMillis)) { + error("invalid start value: startMillis=$startMillis durationMillis=$durationMillis") + } + + if (endMillis != null && (endMillis < 0 || endMillis > durationMillis)) { + error("invalid end value: endMillis=$startMillis durationMillis=$durationMillis") + } + + val start = startMillis?.let { it.toFloat() / durationMillis } + val end = endMillis?.let { it.toFloat() / durationMillis } + fractionRange(start, end, builder) + } +} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt new file mode 100644 index 000000000000..228d19f09cff --- /dev/null +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.compose.animation.scene + +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.unit.IntSize + +internal class UserActionDistanceScopeImpl( + private val layoutImpl: SceneTransitionLayoutImpl, +) : UserActionDistanceScope { + override val density: Float + get() = layoutImpl.density.density + + override val fontScale: Float + get() = layoutImpl.density.fontScale + + override fun ElementKey.targetSize(scene: SceneKey): IntSize? { + return layoutImpl.elements[this]?.sceneStates?.get(scene)?.targetSize.takeIf { + it != Element.SizeUnspecified + } + } + + override fun ElementKey.targetOffset(scene: SceneKey): Offset? { + return layoutImpl.elements[this]?.sceneStates?.get(scene)?.targetOffset.takeIf { + it != Offset.Unspecified + } + } + + override fun SceneKey.targetSize(): IntSize? { + return layoutImpl.scenes[this]?.targetSize.takeIf { it != IntSize.Zero } + } +} diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt index 33be1dc83dc8..059a10e23207 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt @@ -18,9 +18,13 @@ package com.android.compose.animation.scene import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.rememberScrollableState +import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.size @@ -34,8 +38,14 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.layout.intermediateLayout +import androidx.compose.ui.platform.LocalViewConfiguration +import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -528,4 +538,157 @@ class ElementTest { after { assertThat(fooCompositions).isEqualTo(1) } } } + + @Test + fun elementTransitionDuringOverscroll() { + // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is + // detected as a drag event. + var touchSlop = 0f + val overscrollTranslateY = 10.dp + val layoutWidth = 200.dp + val layoutHeight = 400.dp + + val state = + MutableSceneTransitionLayoutState( + initialScene = TestScenes.SceneA, + transitions = + transitions { + overscroll(TestScenes.SceneB, Orientation.Vertical) { + translate(TestElements.Foo, y = overscrollTranslateY) + } + } + ) + as MutableSceneTransitionLayoutStateImpl + + rule.setContent { + touchSlop = LocalViewConfiguration.current.touchSlop + SceneTransitionLayout( + state = state, + modifier = Modifier.size(layoutWidth, layoutHeight) + ) { + scene( + key = TestScenes.SceneA, + userActions = mapOf(Swipe.Down to TestScenes.SceneB) + ) { + Spacer(Modifier.fillMaxSize()) + } + scene(TestScenes.SceneB) { + Spacer(Modifier.element(TestElements.Foo).fillMaxSize()) + } + } + } + + assertThat(state.currentTransition).isNull() + assertThat(state.currentOverscrollSpec).isNull() + + // Swipe by half of verticalSwipeDistance. + rule.onRoot().performTouchInput { + val middleTop = Offset((layoutWidth / 2).toPx(), 0f) + down(middleTop) + // Scroll 50% + moveBy(Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f), delayMillis = 1_000) + } + + val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true) + fooElement.assertTopPositionInRootIsEqualTo(0.dp) + val transition = state.currentTransition + assertThat(transition).isNotNull() + assertThat(transition!!.progress).isEqualTo(0.5f) + + rule.onRoot().performTouchInput { + // Scroll another 100% + moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000) + } + + // Scroll 150% (Scene B overscroll by 50%) + assertThat(transition.progress).isEqualTo(1.5f) + assertThat(state.currentOverscrollSpec).isNotNull() + fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f) + + rule.onRoot().performTouchInput { + // Scroll another 100% + moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000) + } + + // Scroll 250% (Scene B overscroll by 150%) + assertThat(transition.progress).isEqualTo(2.5f) + assertThat(state.currentOverscrollSpec).isNotNull() + fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f) + } + + @Test + fun elementTransitionDuringNestedScrollOverscroll() { + // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is + // detected as a drag event. + var touchSlop = 0f + val overscrollTranslateY = 10.dp + val layoutWidth = 200.dp + val layoutHeight = 400.dp + + val state = + MutableSceneTransitionLayoutState( + initialScene = TestScenes.SceneB, + transitions = + transitions { + overscroll(TestScenes.SceneB, Orientation.Vertical) { + translate(TestElements.Foo, y = overscrollTranslateY) + } + } + ) + as MutableSceneTransitionLayoutStateImpl + + rule.setContent { + touchSlop = LocalViewConfiguration.current.touchSlop + SceneTransitionLayout( + state = state, + modifier = Modifier.size(layoutWidth, layoutHeight) + ) { + scene(TestScenes.SceneA) { Spacer(Modifier.fillMaxSize()) } + scene(TestScenes.SceneB, userActions = mapOf(Swipe.Up to TestScenes.SceneA)) { + Box( + Modifier + // Unconsumed scroll gesture will be intercepted by STL + .verticalNestedScrollToScene() + // A scrollable that does not consume the scroll gesture + .scrollable( + rememberScrollableState(consumeScrollDelta = { 0f }), + Orientation.Vertical + ) + .fillMaxSize() + ) { + Spacer(Modifier.element(TestElements.Foo).fillMaxSize()) + } + } + } + } + + assertThat(state.currentTransition).isNull() + assertThat(state.currentOverscrollSpec).isNull() + val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true) + fooElement.assertTopPositionInRootIsEqualTo(0.dp) + + // Swipe by half of verticalSwipeDistance. + rule.onRoot().performTouchInput { + val middleTop = Offset((layoutWidth / 2).toPx(), 0f) + down(middleTop) + // Scroll 50% + moveBy(Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f), delayMillis = 1_000) + } + + val transition = state.currentTransition + assertThat(state.currentOverscrollSpec).isNotNull() + assertThat(transition).isNotNull() + assertThat(transition!!.progress).isEqualTo(-0.5f) + fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f) + + rule.onRoot().performTouchInput { + // Scroll another 100% + moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000) + } + + // Scroll 150% (Scene B overscroll by 50%) + assertThat(transition.progress).isEqualTo(-1.5f) + assertThat(state.currentOverscrollSpec).isNotNull() + fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt index fe53d5b45420..d28ac6ad546e 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt @@ -52,7 +52,7 @@ class SceneGestureHandlerTest { private val testScope: MonotonicClockTestScope, ) { var canChangeScene: (SceneKey) -> Boolean = { true } - private val layoutState = + val layoutState = MutableSceneTransitionLayoutStateImpl( SceneA, EmptyTestTransitions, @@ -932,4 +932,28 @@ class SceneGestureHandlerTest { advanceUntilIdle() assertIdle(SceneB) } + + @Test + fun scrollFromIdleWithNoTargetScene_shouldUseOverscrollSpecIfAvailable() = runGestureTest { + layoutState.transitions = transitions { + overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) } + } + // Start at scene C. + navigateToSceneC() + + val scene = layoutState.transitionState.currentScene + // We should have overscroll spec for scene C + assertThat(layoutState.transitions.overscrollSpec(scene, Orientation.Vertical)).isNotNull() + assertThat(layoutState.currentOverscrollSpec).isNull() + + val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways) + nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f)) + + // We scrolled down, under scene C there is nothing, so we can use the overscroll spec + assertThat(layoutState.currentOverscrollSpec).isNotNull() + assertThat(layoutState.currentOverscrollSpec?.scene).isEqualTo(SceneC) + val transition = layoutState.currentTransition + assertThat(transition).isNotNull() + assertThat(transition!!.progress).isEqualTo(-0.1f) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt index f81a7f2908e8..3cbcd73a0adb 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt @@ -16,6 +16,8 @@ package com.android.compose.animation.scene +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.compose.animation.scene.TestScenes.SceneA @@ -389,4 +391,118 @@ class SceneTransitionLayoutStateTest { assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isFalse() } + + private fun startOverscrollableTransistionFromAtoB( + progress: () -> Float, + sceneTransitions: SceneTransitions, + ): MutableSceneTransitionLayoutStateImpl { + val state = + MutableSceneTransitionLayoutStateImpl( + SceneA, + sceneTransitions, + ) + state.startTransition( + object : + TransitionState.Transition(SceneA, SceneB), + TransitionState.HasOverscrollProperties { + override val currentScene: SceneKey = SceneA + override val progress: Float + get() = progress() + + override val isInitiatedByUserInput: Boolean = false + override val isUserInputOngoing: Boolean = false + override val isUpOrLeft: Boolean = false + override val orientation: Orientation = Orientation.Vertical + }, + transitionKey = null + ) + assertThat(state.isTransitioning()).isTrue() + return state + } + + @Test + fun overscrollDsl_definedForToScene() = runMonotonicClockTest { + val progress = mutableStateOf(0f) + val state = + startOverscrollableTransistionFromAtoB( + progress = { progress.value }, + sceneTransitions = + transitions { + overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) } + } + ) + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneA is NOT defined + progress.value = -0.1f + assertThat(state.currentOverscrollSpec).isNull() + + // scroll from SceneA to SceneB + progress.value = 0.5f + assertThat(state.currentOverscrollSpec).isNull() + + progress.value = 1f + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneB is defined + progress.value = 1.1f + assertThat(state.currentOverscrollSpec).isNotNull() + assertThat(state.currentOverscrollSpec?.scene).isEqualTo(SceneB) + } + + @Test + fun overscrollDsl_definedForFromScene() = runMonotonicClockTest { + val progress = mutableStateOf(0f) + val state = + startOverscrollableTransistionFromAtoB( + progress = { progress.value }, + sceneTransitions = + transitions { + overscroll(SceneA, Orientation.Vertical) { fade(TestElements.Foo) } + } + ) + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneA is defined + progress.value = -0.1f + assertThat(state.currentOverscrollSpec).isNotNull() + assertThat(state.currentOverscrollSpec?.scene).isEqualTo(SceneA) + + // scroll from SceneA to SceneB + progress.value = 0.5f + assertThat(state.currentOverscrollSpec).isNull() + + progress.value = 1f + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneB is NOT defined + progress.value = 1.1f + assertThat(state.currentOverscrollSpec).isNull() + } + + @Test + fun overscrollDsl_notDefinedScenes() = runMonotonicClockTest { + val progress = mutableStateOf(0f) + val state = + startOverscrollableTransistionFromAtoB( + progress = { progress.value }, + sceneTransitions = transitions {} + ) + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneA is NOT defined + progress.value = -0.1f + assertThat(state.currentOverscrollSpec).isNull() + + // scroll from SceneA to SceneB + progress.value = 0.5f + assertThat(state.currentOverscrollSpec).isNull() + + progress.value = 1f + assertThat(state.currentOverscrollSpec).isNull() + + // overscroll for SceneB is NOT defined + progress.value = 1.1f + assertThat(state.currentOverscrollSpec).isNull() + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt index 543ed0482430..99372a5d084b 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt @@ -16,9 +16,11 @@ package com.android.compose.animation.scene +import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -33,6 +35,7 @@ import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeWithVelocity import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat @@ -61,8 +64,10 @@ class SwipeToSceneTest { @get:Rule val rule = createComposeRule() - private fun layoutState(initialScene: SceneKey = TestScenes.SceneA) = - MutableSceneTransitionLayoutState(initialScene, EmptyTestTransitions) + private fun layoutState( + initialScene: SceneKey = TestScenes.SceneA, + transitions: SceneTransitions = EmptyTestTransitions, + ) = MutableSceneTransitionLayoutState(initialScene, transitions) /** The content under test. */ @Composable @@ -370,8 +375,16 @@ class SwipeToSceneTest { // detected as a drag event. var touchSlop = 0f - val layoutState = layoutState() val verticalSwipeDistance = 50.dp + val layoutState = + layoutState( + transitions = + transitions { + from(TestScenes.SceneA, to = TestScenes.SceneB) { + distance = FixedDistance(verticalSwipeDistance) + } + } + ) assertThat(verticalSwipeDistance).isNotEqualTo(LayoutHeight) rule.setContent { @@ -383,14 +396,7 @@ class SwipeToSceneTest { ) { scene( TestScenes.SceneA, - userActions = - mapOf( - Swipe.Down to - UserActionResult( - toScene = TestScenes.SceneB, - distance = verticalSwipeDistance, - ) - ), + userActions = mapOf(Swipe.Down to TestScenes.SceneB), ) { Spacer(Modifier.fillMaxSize()) } @@ -548,4 +554,64 @@ class SwipeToSceneTest { assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB)).isTrue() assertThat(state.transformationSpec.transformations).hasSize(2) } + + @Test + fun dynamicSwipeDistance() { + val swipeDistance = + object : UserActionDistance { + override fun UserActionDistanceScope.absoluteDistance( + fromSceneSize: IntSize, + orientation: Orientation, + ): Float { + // Foo is going to have a vertical offset of 50dp. Let's make the swipe distance + // the difference between the bottom of the scene and the bottom of the element, + // so that we use the offset and size of the element as well as the size of the + // scene. + val fooSize = TestElements.Foo.targetSize(TestScenes.SceneB) ?: return 0f + val fooOffset = TestElements.Foo.targetOffset(TestScenes.SceneB) ?: return 0f + val sceneSize = TestScenes.SceneB.targetSize() ?: return 0f + return sceneSize.height - fooOffset.y - fooSize.height + } + } + + val state = + MutableSceneTransitionLayoutState( + TestScenes.SceneA, + transitions { + from(TestScenes.SceneA, to = TestScenes.SceneB) { distance = swipeDistance } + } + ) + + val layoutSize = 200.dp + val fooYOffset = 50.dp + val fooSize = 25.dp + + var touchSlop = 0f + rule.setContent { + touchSlop = LocalViewConfiguration.current.touchSlop + + SceneTransitionLayout(state, Modifier.size(layoutSize)) { + scene(TestScenes.SceneA, userActions = mapOf(Swipe.Up to TestScenes.SceneB)) { + Box(Modifier.fillMaxSize()) + } + scene(TestScenes.SceneB) { + Box(Modifier.fillMaxSize()) { + Box(Modifier.offset(y = fooYOffset).element(TestElements.Foo).size(fooSize)) + } + } + } + } + + // Swipe up by half the expected distance to get to 50% progress. + val expectedDistance = layoutSize - fooYOffset - fooSize + rule.onRoot().performTouchInput { + val middle = (layoutSize / 2).toPx() + down(Offset(middle, middle)) + moveBy(Offset(0f, -touchSlop - (expectedDistance / 2f).toPx()), delayMillis = 1_000) + } + + rule.waitForIdle() + assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB)).isTrue() + assertThat(state.currentTransition!!.progress).isWithin(0.01f).of(0.5f) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt index 1beafcc2cbb2..c9c3eccdedfc 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt @@ -20,9 +20,11 @@ import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.TweenSpec import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween +import androidx.compose.foundation.gestures.Orientation import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.compose.animation.scene.transformation.Transformation import com.android.compose.animation.scene.transformation.TransformationRange +import com.android.compose.animation.scene.transformation.Translate import com.google.common.truth.Correspondence import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -223,6 +225,17 @@ class TransitionDslTest { .isSameInstanceAs(specFromAToC) } + @Test + fun overscrollSpec() { + val transitions = transitions { + overscroll(TestScenes.SceneA, Orientation.Vertical) { translate(TestElements.Bar) } + } + + val overscrollSpec = transitions.overscrollSpecs.single() + val transformation = overscrollSpec.transformationSpec.transformations.single() + assertThat(transformation).isInstanceOf(Translate::class.java) + } + companion object { private val TRANSFORMATION_RANGE = Correspondence.transforming<Transformation, TransformationRange?>( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/data/repository/AssistRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/data/repository/AssistRepositoryTest.kt new file mode 100644 index 000000000000..80077a21f985 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/data/repository/AssistRepositoryTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.assist.data.repository + +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.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class AssistRepositoryTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val underTest = kosmos.assistRepository + + @Test + fun invocationType() = + testScope.runTest { + val invocationType by collectLastValue(underTest.latestInvocationType) + underTest.setLatestInvocationType(2) + runCurrent() + + assertThat(invocationType).isEqualTo(2) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/domain/interactor/AssistInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/domain/interactor/AssistInteractorTest.kt new file mode 100644 index 000000000000..c12f1aca350a --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/assist/domain/interactor/AssistInteractorTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.assist.domain.interactor + +import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.Flags +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +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.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +@SmallTest +class AssistInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val underTest = kosmos.assistInteractor + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CONTEXTUAL_TIPS, Flags.FLAG_ENABLE_CONTEXTUAL_TIP_FOR_POWER_OFF) + fun onAssistantStarted() = + testScope.runTest { + val invocationType by collectLastValue(underTest.latestInvocationType) + underTest.onAssistantStarted(3) + runCurrent() + + assertThat(invocationType).isEqualTo(3) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index 259f3498d4c3..503463171ae7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -44,12 +44,18 @@ import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayView import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.LockscreenShadeTransitionController +import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.SystemUIDialogManager import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController @@ -58,6 +64,10 @@ import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.user.domain.interactor.SelectedUserInteractor 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.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule import org.junit.Test @@ -68,6 +78,7 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.mock +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit @@ -120,6 +131,9 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Mock private lateinit var shadeInteractor: ShadeInteractor @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams> @Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor + private lateinit var powerRepository: FakePowerRepository + private lateinit var powerInteractor: PowerInteractor + private lateinit var testScope: TestScope private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true } private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams() @@ -127,6 +141,15 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Before fun setup() { + testScope = TestScope(StandardTestDispatcher()) + powerRepository = FakePowerRepository() + powerInteractor = + PowerInteractor( + powerRepository, + mock(FalsingCollector::class.java), + mock(ScreenOffAnimationController::class.java), + statusBarStateController, + ) whenever(inflater.inflate(R.layout.udfps_view, null, false)).thenReturn(udfpsView) whenever(inflater.inflate(R.layout.udfps_bp_view, null)) .thenReturn(mock(UdfpsBpView::class.java)) @@ -178,6 +201,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { { defaultUdfpsTouchOverlayViewModel }, shadeInteractor, udfpsOverlayInteractor, + powerInteractor, + testScope, ) block() } @@ -277,6 +302,66 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { } } + @Test + fun showUdfpsOverlay_awake() = + testScope.runTest { + withReason(REASON_AUTH_KEYGUARD) { + mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + controllerOverlay.show(udfpsController, overlayParams) + runCurrent() + verify(windowManager).addView(any(), any()) + } + } + + @Test + fun showUdfpsOverlay_whileGoingToSleep() = + testScope.runTest { + withReason(REASON_AUTH_KEYGUARD) { + mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE) + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + controllerOverlay.show(udfpsController, overlayParams) + runCurrent() + verify(windowManager, never()).addView(any(), any()) + + // we hide to end the job that listens for the finishedGoingToSleep signal + controllerOverlay.hide() + } + } + + @Test + fun showUdfpsOverlay_afterFinishedGoingToSleep() = + testScope.runTest { + withReason(REASON_AUTH_KEYGUARD) { + mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE) + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + controllerOverlay.show(udfpsController, overlayParams) + runCurrent() + verify(windowManager, never()).addView(any(), any()) + + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + runCurrent() + verify(windowManager) + .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture()) + } + } + private fun showUdfpsOverlay() { val didShow = controllerOverlay.show(udfpsController, overlayParams) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 529403a710b5..561cdbbf66ce 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -86,6 +86,7 @@ import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayView import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel; import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; +import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; @@ -94,10 +95,15 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.power.data.repository.FakePowerRepository; +import com.android.systemui.power.domain.interactor.PowerInteractor; +import com.android.systemui.power.shared.model.WakeSleepReason; +import com.android.systemui.power.shared.model.WakefulnessState; import com.android.systemui.res.R; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.VibratorHelper; +import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.SystemUIDialogManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; @@ -125,6 +131,8 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; +import kotlinx.coroutines.CoroutineScope; + @SmallTest @RunWith(AndroidJUnit4.class) @RunWithLooper(setAsMainLooper = true) @@ -238,6 +246,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private ScreenLifecycle.Observer mScreenObserver; private FingerprintSensorPropertiesInternal mOpticalProps; private FingerprintSensorPropertiesInternal mUltrasonicProps; + private PowerInteractor mPowerInteractor; + private FakePowerRepository mPowerRepository; @Mock private InputManager mInputManager; @Mock @@ -253,6 +263,19 @@ public class UdfpsControllerTest extends SysuiTestCase { @Before public void setUp() { + mPowerRepository = new FakePowerRepository(); + mPowerInteractor = new PowerInteractor( + mPowerRepository, + mock(FalsingCollector.class), + mock(ScreenOffAnimationController.class), + mStatusBarStateController + ); + mPowerRepository.updateWakefulness( + WakefulnessState.AWAKE, + WakeSleepReason.POWER_BUTTON, + WakeSleepReason.OTHER, + /* powerButtonLaunchGestureTriggered */ false + ); mContext.getOrCreateTestableResources() .addOverride(com.android.internal.R.bool.config_ignoreUdfpsVote, false); @@ -346,7 +369,9 @@ public class UdfpsControllerTest extends SysuiTestCase { mKeyguardTransitionInteractor, mDeviceEntryUdfpsTouchOverlayViewModel, mDefaultUdfpsTouchOverlayViewModel, - mUdfpsOverlayInteractor + mUdfpsOverlayInteractor, + mPowerInteractor, + mock(CoroutineScope.class) ); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index a8fe16b12e1b..92396e0bcdef 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -20,6 +20,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dock.DockManager @@ -33,6 +34,7 @@ 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.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent @@ -50,7 +52,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { private lateinit var underTest: CommunalSceneStartable @Before - fun setUp() = + fun setUp() { with(kosmos) { underTest = CommunalSceneStartable( @@ -61,7 +63,15 @@ class CommunalSceneStartableTest : SysuiTestCase() { bgScope = applicationCoroutineScope, ) .apply { start() } + + // Make communal available so that communalInteractor.desiredScene accurately reflects + // scene changes instead of just returning Blank. + with(kosmos.testScope) { + launch { setCommunalAvailable(true) } + testScheduler.runCurrent() + } } + } @Test fun keyguardGoesAway_forceBlankScene() = @@ -83,25 +93,6 @@ class CommunalSceneStartableTest : SysuiTestCase() { } @Test - fun deviceDreaming_forceBlankScene() = - with(kosmos) { - testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) - - communalInteractor.onSceneChanged(CommunalSceneKey.Communal) - assertThat(scene).isEqualTo(CommunalSceneKey.Communal) - - fakeKeyguardTransitionRepository.sendTransitionSteps( - from = KeyguardState.GLANCEABLE_HUB, - to = KeyguardState.DREAMING, - testScope = this - ) - - assertThat(scene).isEqualTo(CommunalSceneKey.Blank) - } - } - - @Test fun deviceDocked_forceCommunalScene() = with(kosmos) { testScope.runTest { @@ -115,13 +106,6 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope = this ) assertThat(scene).isEqualTo(CommunalSceneKey.Communal) - - fakeKeyguardTransitionRepository.sendTransitionSteps( - from = KeyguardState.GLANCEABLE_HUB, - to = KeyguardState.DREAMING, - testScope = this - ) - assertThat(scene).isEqualTo(CommunalSceneKey.Blank) } } @@ -249,4 +233,10 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeDockManager.setDockEvent(DockManager.STATE_DOCKED) runCurrent() } + + private suspend fun TestScope.enableCommunal() = + with(kosmos) { + setCommunalAvailable(true) + runCurrent() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt index 5b20ae5131b2..06b3806cb382 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt @@ -25,7 +25,6 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags -import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.flowOf @@ -57,46 +56,6 @@ class CommunalRepositoryImplTest : SysuiTestCase() { } @Test - fun isCommunalShowing_sceneContainerDisabled_onCommunalScene_true() = - testScope.runTest { - underTest.setDesiredScene(CommunalSceneKey.Communal) - - val isCommunalHubShowing by collectLastValue(underTest.isCommunalHubShowing) - assertThat(isCommunalHubShowing).isTrue() - } - - @Test - fun isCommunalShowing_sceneContainerDisabled_onBlankScene_false() = - testScope.runTest { - underTest.setDesiredScene(CommunalSceneKey.Blank) - - val isCommunalHubShowing by collectLastValue(underTest.isCommunalHubShowing) - assertThat(isCommunalHubShowing).isFalse() - } - - @Test - fun isCommunalShowing_sceneContainerEnabled_onCommunalScene_true() = - testScope.runTest { - underTest = createRepositoryImpl(true) - - sceneContainerRepository.changeScene(SceneKey.Communal) - - val isCommunalHubShowing by collectLastValue(underTest.isCommunalHubShowing) - assertThat(isCommunalHubShowing).isTrue() - } - - @Test - fun isCommunalShowing_sceneContainerEnabled_onLockscreenScene_false() = - testScope.runTest { - underTest = createRepositoryImpl(true) - - sceneContainerRepository.changeScene(SceneKey.Lockscreen) - - val isCommunalHubShowing by collectLastValue(underTest.isCommunalHubShowing) - assertThat(isCommunalHubShowing).isFalse() - } - - @Test fun transitionState_idleByDefault() = testScope.runTest { val transitionState by collectLastValue(underTest.transitionState) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index 53af4a0fb454..cd296524c17c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -18,7 +18,9 @@ package com.android.systemui.communal.domain.interactor import android.app.smartspace.SmartspaceTarget +import android.appwidget.AppWidgetProviderInfo import android.content.pm.UserInfo +import android.os.UserHandle import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED import android.widget.RemoteViews import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -47,6 +49,12 @@ import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags +import com.android.systemui.scene.shared.model.SceneKey +import com.android.systemui.settings.FakeUserTracker +import com.android.systemui.settings.fakeUserTracker import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos @@ -91,6 +99,8 @@ class CommunalInteractorTest : SysuiTestCase() { private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var communalPrefsRepository: FakeCommunalPrefsRepository private lateinit var editWidgetsActivityStarter: EditWidgetsActivityStarter + private lateinit var sceneInteractor: SceneInteractor + private lateinit var userTracker: FakeUserTracker private lateinit var underTest: CommunalInteractor @@ -107,6 +117,8 @@ class CommunalInteractorTest : SysuiTestCase() { keyguardRepository = kosmos.fakeKeyguardRepository editWidgetsActivityStarter = kosmos.editWidgetsActivityStarter communalPrefsRepository = kosmos.fakeCommunalPrefsRepository + sceneInteractor = kosmos.sceneInteractor + userTracker = kosmos.fakeUserTracker whenever(mainUser.isMain).thenReturn(true) whenever(secondaryUser.isMain).thenReturn(false) @@ -201,25 +213,19 @@ class CommunalInteractorTest : SysuiTestCase() { keyguardRepository.setKeyguardOccluded(false) tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - // Widgets are available. - val widgets = - listOf( - CommunalWidgetContentModel( - appWidgetId = 0, - priority = 30, - providerInfo = mock(), - ), - CommunalWidgetContentModel( - appWidgetId = 1, - priority = 20, - providerInfo = mock(), - ), - CommunalWidgetContentModel( - appWidgetId = 2, - priority = 10, - providerInfo = mock(), - ), - ) + val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + runCurrent() + + // Widgets available. + val widget1 = createWidgetForUser(1, USER_INFO_WORK.id) + val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id) + val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id) + val widgets = listOf(widget1, widget2, widget3) widgetRepository.setCommunalWidgets(widgets) val widgetContent by collectLastValue(underTest.widgetContent) @@ -449,6 +455,9 @@ class CommunalInteractorTest : SysuiTestCase() { @Test fun listensToSceneChange() = testScope.runTest { + kosmos.setCommunalAvailable(true) + runCurrent() + var desiredScene = collectLastValue(underTest.desiredScene) runCurrent() assertThat(desiredScene()).isEqualTo(CommunalSceneKey.Blank) @@ -473,6 +482,30 @@ class CommunalInteractorTest : SysuiTestCase() { } @Test + fun desiredScene_communalNotAvailable_returnsBlank() = + testScope.runTest { + kosmos.setCommunalAvailable(true) + runCurrent() + + val desiredScene by collectLastValue(underTest.desiredScene) + + underTest.onSceneChanged(CommunalSceneKey.Communal) + assertThat(desiredScene).isEqualTo(CommunalSceneKey.Communal) + + kosmos.setCommunalAvailable(false) + runCurrent() + + // Scene returns blank when communal is not available. + assertThat(desiredScene).isEqualTo(CommunalSceneKey.Blank) + + kosmos.setCommunalAvailable(true) + runCurrent() + + // After re-enabling, scene goes back to Communal. + assertThat(desiredScene).isEqualTo(CommunalSceneKey.Communal) + } + + @Test fun transitionProgress_onTargetScene_fullProgress() = testScope.runTest { val targetScene = CommunalSceneKey.Blank @@ -600,6 +633,9 @@ class CommunalInteractorTest : SysuiTestCase() { @Test fun isCommunalShowing() = testScope.runTest { + kosmos.setCommunalAvailable(true) + runCurrent() + var isCommunalShowing = collectLastValue(underTest.isCommunalShowing) runCurrent() assertThat(isCommunalShowing()).isEqualTo(false) @@ -612,6 +648,59 @@ class CommunalInteractorTest : SysuiTestCase() { } @Test + fun isCommunalShowing_whenSceneContainerDisabled() = + testScope.runTest { + kosmos.setCommunalAvailable(true) + runCurrent() + + // Verify default is false + val isCommunalShowing by collectLastValue(underTest.isCommunalShowing) + runCurrent() + assertThat(isCommunalShowing).isFalse() + + // Verify scene changes with the flag doesn't have any impact + sceneInteractor.changeScene(SceneKey.Communal, loggingReason = "") + runCurrent() + assertThat(isCommunalShowing).isFalse() + + // Verify scene changes (without the flag) to communal sets the value to true + underTest.onSceneChanged(CommunalSceneKey.Communal) + runCurrent() + assertThat(isCommunalShowing).isTrue() + + // Verify scene changes (without the flag) to blank sets the value back to false + underTest.onSceneChanged(CommunalSceneKey.Blank) + runCurrent() + assertThat(isCommunalShowing).isFalse() + } + + @Test + fun isCommunalShowing_whenSceneContainerEnabled() = + testScope.runTest { + kosmos.fakeSceneContainerFlags.enabled = true + + // Verify default is false + val isCommunalShowing by collectLastValue(underTest.isCommunalShowing) + runCurrent() + assertThat(isCommunalShowing).isFalse() + + // Verify scene changes without the flag doesn't have any impact + underTest.onSceneChanged(CommunalSceneKey.Communal) + runCurrent() + assertThat(isCommunalShowing).isFalse() + + // Verify scene changes (with the flag) to communal sets the value to true + sceneInteractor.changeScene(SceneKey.Communal, loggingReason = "") + runCurrent() + assertThat(isCommunalShowing).isTrue() + + // Verify scene changes (with the flag) to lockscreen sets the value to false + sceneInteractor.changeScene(SceneKey.Lockscreen, loggingReason = "") + runCurrent() + assertThat(isCommunalShowing).isFalse() + } + + @Test fun isIdleOnCommunal() = testScope.runTest { val transitionState = @@ -710,6 +799,38 @@ class CommunalInteractorTest : SysuiTestCase() { verify(editWidgetsActivityStarter).startActivity(widgetKey) } + @Test + fun filterWidgets_whenUserProfileRemoved() = + testScope.runTest { + // Keyguard showing, and tutorial completed. + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) + + // Only main user exists. + val userInfos = listOf(MAIN_USER_INFO) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + runCurrent() + + val widgetContent by collectLastValue(underTest.widgetContent) + // Given three widgets, and one of them is associated with pre-existing work profile. + val widget1 = createWidgetForUser(1, USER_INFO_WORK.id) + val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id) + val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id) + val widgets = listOf(widget1, widget2, widget3) + widgetRepository.setCommunalWidgets(widgets) + + // One widget is filtered out and the remaining two link to main user id. + assertThat(checkNotNull(widgetContent).size).isEqualTo(2) + widgetContent!!.forEachIndexed { _, model -> + assertThat(model.providerInfo.profile?.identifier).isEqualTo(MAIN_USER_INFO.id) + } + } + private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget { val timer = mock(SmartspaceTarget::class.java) whenever(timer.smartspaceTargetId).thenReturn(id) @@ -718,4 +839,17 @@ class CommunalInteractorTest : SysuiTestCase() { whenever(timer.creationTimeMillis).thenReturn(timestamp) return timer } + + private fun createWidgetForUser(appWidgetId: Int, userId: Int): CommunalWidgetContentModel = + mock<CommunalWidgetContentModel> { + whenever(this.appWidgetId).thenReturn(appWidgetId) + val providerInfo = mock<AppWidgetProviderInfo>() + whenever(providerInfo.profile).thenReturn(UserHandle(userId)) + whenever(this.providerInfo).thenReturn(providerInfo) + } + + private companion object { + val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt index ceb7fac1046f..8b785927ba5e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt @@ -16,7 +16,6 @@ package com.android.systemui.communal.domain.interactor -import android.content.pm.UserInfo import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_NOT_STARTED import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_STARTED @@ -24,10 +23,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.SysuiTestCase -import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository -import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository +import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic @@ -38,13 +36,11 @@ import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.data.repository.fakeUserRepository import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi 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 CommunalTutorialInteractorTest : SysuiTestCase() { @@ -54,7 +50,6 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { private lateinit var underTest: CommunalTutorialInteractor private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var communalTutorialRepository: FakeCommunalTutorialRepository - private lateinit var communalRepository: FakeCommunalRepository private lateinit var communalInteractor: CommunalInteractor private lateinit var userRepository: FakeUserRepository @@ -62,11 +57,9 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun setUp() { keyguardRepository = kosmos.fakeKeyguardRepository communalTutorialRepository = kosmos.fakeCommunalTutorialRepository - communalRepository = kosmos.fakeCommunalRepository communalInteractor = kosmos.communalInteractor userRepository = kosmos.fakeUserRepository - userRepository.setUserInfos(listOf(MAIN_USER_INFO)) kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true) mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB) @@ -77,7 +70,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialUnavailable_whenKeyguardNotVisible() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) - setCommunalAvailable(true) + kosmos.setCommunalAvailable(true) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) keyguardRepository.setKeyguardShowing(false) assertThat(isTutorialAvailable).isFalse() @@ -87,10 +80,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialUnavailable_whenTutorialIsCompleted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) - setCommunalAvailable(true) - keyguardRepository.setKeyguardShowing(true) - keyguardRepository.setKeyguardOccluded(false) - communalRepository.setIsCommunalHubShowing(false) + goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) assertThat(isTutorialAvailable).isFalse() } @@ -99,7 +89,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialUnavailable_whenCommunalNotAvailable() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) - setCommunalAvailable(false) + kosmos.setCommunalAvailable(false) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) keyguardRepository.setKeyguardShowing(true) assertThat(isTutorialAvailable).isFalse() @@ -109,10 +99,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialAvailable_whenTutorialNotStarted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) - setCommunalAvailable(true) - keyguardRepository.setKeyguardShowing(true) - keyguardRepository.setKeyguardOccluded(false) - communalRepository.setIsCommunalHubShowing(false) + kosmos.setCommunalAvailable(true) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) assertThat(isTutorialAvailable).isTrue() } @@ -121,10 +108,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialAvailable_whenTutorialIsStarted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) - setCommunalAvailable(true) - keyguardRepository.setKeyguardShowing(true) - keyguardRepository.setKeyguardOccluded(false) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED) assertThat(isTutorialAvailable).isTrue() } @@ -134,10 +118,9 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED) } @@ -147,10 +130,10 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) + communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED) } @@ -160,10 +143,9 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } @@ -173,10 +155,10 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) + kosmos.setCommunalAvailable(true) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) - communalRepository.setIsCommunalHubShowing(false) + communalInteractor.onSceneChanged(CommunalSceneKey.Blank) assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_NOT_STARTED) } @@ -186,11 +168,10 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED) - communalRepository.setIsCommunalHubShowing(false) + communalInteractor.onSceneChanged(CommunalSceneKey.Blank) assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } @@ -200,26 +181,16 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { testScope.runTest { val tutorialSettingState by collectLastValue(communalTutorialRepository.tutorialSettingState) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) - communalRepository.setIsCommunalHubShowing(true) + goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - communalRepository.setIsCommunalHubShowing(false) + communalInteractor.onSceneChanged(CommunalSceneKey.Blank) assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } - private suspend fun setCommunalAvailable(available: Boolean) { - if (available) { - keyguardRepository.setIsEncryptedOrLockdown(false) - userRepository.setSelectedUserInfo(MAIN_USER_INFO) - keyguardRepository.setKeyguardShowing(true) - } else { - keyguardRepository.setIsEncryptedOrLockdown(true) - } - } - - private companion object { - val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + private suspend fun goToCommunal() { + kosmos.setCommunalAvailable(true) + communalInteractor.onSceneChanged(CommunalSceneKey.Communal) } } 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 352bacc56ca5..5ee88cb92fa0 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,9 @@ package com.android.systemui.communal.view.viewmodel import android.app.smartspace.SmartspaceTarget +import android.appwidget.AppWidgetProviderInfo +import android.content.pm.UserInfo +import android.os.UserHandle import android.provider.Settings import android.widget.RemoteViews import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -39,6 +42,7 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.media.controls.ui.view.MediaHost +import com.android.systemui.settings.fakeUserTracker import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos @@ -59,6 +63,7 @@ import org.mockito.MockitoAnnotations class CommunalEditModeViewModelTest : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost @Mock private lateinit var uiEventLogger: UiEventLogger + @Mock private lateinit var providerInfo: AppWidgetProviderInfo private val kosmos = testKosmos() private val testScope = kosmos.testScope @@ -78,6 +83,11 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { widgetRepository = kosmos.fakeCommunalWidgetRepository smartspaceRepository = kosmos.fakeSmartspaceRepository mediaRepository = kosmos.fakeCommunalMediaRepository + kosmos.fakeUserTracker.set( + userInfos = listOf(MAIN_USER_INFO), + selectedUserIndex = 0, + ) + whenever(providerInfo.profile).thenReturn(UserHandle(MAIN_USER_INFO.id)) underTest = CommunalEditModeViewModel( @@ -100,12 +110,12 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { CommunalWidgetContentModel( appWidgetId = 0, priority = 30, - providerInfo = mock(), + providerInfo = providerInfo, ), CommunalWidgetContentModel( appWidgetId = 1, priority = 20, - providerInfo = mock(), + providerInfo = providerInfo, ), ) widgetRepository.setCommunalWidgets(widgets) @@ -156,12 +166,12 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { CommunalWidgetContentModel( appWidgetId = 0, priority = 30, - providerInfo = mock(), + providerInfo = providerInfo, ), CommunalWidgetContentModel( appWidgetId = 1, priority = 20, - providerInfo = mock(), + providerInfo = providerInfo, ), ) widgetRepository.setCommunalWidgets(widgets) @@ -205,4 +215,8 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { underTest.onReorderWidgetCancel() verify(uiEventLogger).log(CommunalUiEvent.COMMUNAL_HUB_REORDER_WIDGET_CANCEL) } + + private companion object { + val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + } } 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 cc322d085acd..1e523dd2a9cc 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,7 +17,9 @@ package com.android.systemui.communal.view.viewmodel import android.app.smartspace.SmartspaceTarget +import android.appwidget.AppWidgetProviderInfo import android.content.pm.UserInfo +import android.os.UserHandle import android.provider.Settings import android.widget.RemoteViews import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -45,13 +47,13 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.view.MediaHost +import com.android.systemui.settings.fakeUserTracker import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.data.repository.fakeUserRepository -import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -71,6 +73,7 @@ import org.mockito.MockitoAnnotations class CommunalViewModelTest : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost @Mock private lateinit var user: UserInfo + @Mock private lateinit var providerInfo: AppWidgetProviderInfo private val kosmos = testKosmos() private val testScope = kosmos.testScope @@ -98,6 +101,12 @@ class CommunalViewModelTest : SysuiTestCase() { kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true) mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB) + kosmos.fakeUserTracker.set( + userInfos = listOf(MAIN_USER_INFO), + selectedUserIndex = 0, + ) + whenever(providerInfo.profile).thenReturn(UserHandle(MAIN_USER_INFO.id)) + underTest = CommunalViewModel( testScope, @@ -147,12 +156,12 @@ class CommunalViewModelTest : SysuiTestCase() { CommunalWidgetContentModel( appWidgetId = 0, priority = 30, - providerInfo = mock(), + providerInfo = providerInfo, ), CommunalWidgetContentModel( appWidgetId = 1, priority = 20, - providerInfo = mock(), + providerInfo = providerInfo, ), ) widgetRepository.setCommunalWidgets(widgets) @@ -225,4 +234,8 @@ class CommunalViewModelTest : SysuiTestCase() { userRepository.setUserInfos(listOf(user)) userRepository.setSelectedUserInfo(user) } + + private companion object { + val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartableTest.kt index 8488843905f7..2c9d72c423bc 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartableTest.kt @@ -16,7 +16,9 @@ package com.android.systemui.communal.widgets +import android.appwidget.AppWidgetProviderInfo import android.content.pm.UserInfo +import android.os.UserHandle import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_COMMUNAL_HUB @@ -32,6 +34,7 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope +import com.android.systemui.settings.fakeUserTracker import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.mock @@ -65,7 +68,7 @@ class CommunalAppWidgetHostStartableTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO)) + kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO, USER_INFO_WORK)) kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true) mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB) @@ -76,6 +79,7 @@ class CommunalAppWidgetHostStartableTest : SysuiTestCase() { CommunalAppWidgetHostStartable( appWidgetHost, kosmos.communalInteractor, + kosmos.fakeUserTracker, kosmos.applicationCoroutineScope, kosmos.testDispatcher, ) @@ -170,6 +174,46 @@ class CommunalAppWidgetHostStartableTest : SysuiTestCase() { } } + @Test + fun removeWidgetsForDeletedProfile_whenCommunalIsAvailable() = + with(kosmos) { + testScope.runTest { + // Communal is available and work profile is configured. + setCommunalAvailable(true) + kosmos.fakeUserTracker.set( + userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK), + selectedUserIndex = 0, + ) + val widget1 = createWidgetForUser(1, USER_INFO_WORK.id) + val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id) + val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id) + val widgets = listOf(widget1, widget2, widget3) + fakeCommunalWidgetRepository.setCommunalWidgets(widgets) + + underTest.start() + runCurrent() + + val communalWidgets by + collectLastValue(fakeCommunalWidgetRepository.communalWidgets) + assertThat(communalWidgets).containsExactly(widget1, widget2, widget3) + + // Unlock the device and remove work profile. + fakeKeyguardRepository.setKeyguardShowing(false) + kosmos.fakeUserTracker.set( + userInfos = listOf(MAIN_USER_INFO), + selectedUserIndex = 0, + ) + runCurrent() + + // Communal becomes available. + fakeKeyguardRepository.setKeyguardShowing(true) + runCurrent() + + // Widget created for work profile is removed. + assertThat(communalWidgets).containsExactly(widget2, widget3) + } + } + private suspend fun setCommunalAvailable(available: Boolean) = with(kosmos) { fakeKeyguardRepository.setIsEncryptedOrLockdown(false) @@ -179,7 +223,16 @@ class CommunalAppWidgetHostStartableTest : SysuiTestCase() { fakeSettings.putIntForUser(GLANCEABLE_HUB_ENABLED, settingsValue, MAIN_USER_INFO.id) } + private fun createWidgetForUser(appWidgetId: Int, userId: Int): CommunalWidgetContentModel = + mock<CommunalWidgetContentModel> { + whenever(this.appWidgetId).thenReturn(appWidgetId) + val providerInfo = mock<AppWidgetProviderInfo>() + whenever(providerInfo.profile).thenReturn(UserHandle(userId)) + whenever(this.providerInfo).thenReturn(providerInfo) + } + private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt index a6715dfcec24..c670506d9f04 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt @@ -11,7 +11,6 @@ import com.android.systemui.complication.ComplicationHostViewController import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.BlurUtils -import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever @@ -46,7 +45,6 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { @Mock private lateinit var hostViewController: ComplicationHostViewController @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController @Mock private lateinit var stateController: DreamOverlayStateController - @Mock private lateinit var configController: ConfigurationController @Mock private lateinit var transitionViewModel: DreamOverlayViewModel private val logBuffer = FakeLogBuffer.Factory.create() private lateinit var controller: DreamOverlayAnimationsController @@ -62,7 +60,6 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { stateController, DREAM_BLUR_RADIUS, transitionViewModel, - configController, DREAM_IN_BLUR_ANIMATION_DURATION, DREAM_IN_COMPLICATIONS_ANIMATION_DURATION, DREAM_IN_TRANSLATION_Y_DISTANCE, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt index 558e7e6564ae..3a28471b5f9a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt @@ -33,6 +33,7 @@ import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticati import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runCurrent @@ -215,6 +216,39 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() { } @Test + fun onFingerprintFailed_failedAuthenticationStatusWithOtherStatuses() = + testScope.runTest { + val failStatus by + collectLastValue( + underTest.authenticationStatus.filterIsInstance< + FailFingerprintAuthenticationStatus + >() + ) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricAcquired( + BiometricSourceType.FINGERPRINT, + /* acquireInfo */ 0, + ) + updateMonitorCallback.value.onBiometricAuthFailed( + BiometricSourceType.FINGERPRINT, + ) + updateMonitorCallback.value.onBiometricHelp( + /* msgId */ 7, + /* errString */ "Not recognized.", + BiometricSourceType.FINGERPRINT, + ) + updateMonitorCallback.value.onBiometricError( + /* msgId */ 7, + /* errString */ "Too many attempts.", + BiometricSourceType.FINGERPRINT, + ) + + assertThat(failStatus).isNotNull() + } + + @Test fun onFingerprintError_errorAuthenticationStatus() = testScope.runTest { val authenticationStatus by collectLastValue(underTest.authenticationStatus) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt index 199ffa6b87bd..3f6e2291fd1f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt @@ -19,15 +19,15 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository 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.coroutines.collectValues -import com.android.systemui.keyguard.data.repository.biometricSettingsRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.TransitionState @@ -63,7 +63,7 @@ class AlternateBouncerToAodTransitionViewModelTest : SysuiTestCase() { } @Test - fun deviceEntryParentViewAppear() = + fun deviceEntryParentViewAppear_udfpsEnrolledAndEnabled() = testScope.runTest { fingerprintPropertyRepository.setProperties( sensorId = 0, @@ -90,6 +90,33 @@ class AlternateBouncerToAodTransitionViewModelTest : SysuiTestCase() { } @Test + fun deviceEntryParentViewDisappear_udfpsNotEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.setProperties( + sensorId = 0, + strength = SensorStrength.STRONG, + sensorType = FingerprintSensorType.UDFPS_OPTICAL, + sensorLocations = emptyMap(), + ) + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + @Test fun deviceEntryBackgroundViewDisappear() = testScope.runTest { val values by collectValues(underTest.deviceEntryBackgroundViewAlpha) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelTest.kt new file mode 100644 index 000000000000..f8a6fc795b42 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +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.collectValues +import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class AlternateBouncerToDozingTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository + private lateinit var underTest: AlternateBouncerToDozingTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + biometricSettingsRepository = kosmos.biometricSettingsRepository + underTest = kosmos.alternateBouncerToDozingTransitionViewModel + } + + @Test + fun deviceEntryParentViewAppear_udfpsEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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) } + } + + @Test + fun deviceEntryParentViewDisappear_udfpsNotEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + @Test + fun deviceEntryBackgroundViewDisappear() = + testScope.runTest { + val values by collectValues(underTest.deviceEntryBackgroundViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.DOZING, + value = value, + transitionState = state, + ownerName = "AlternateBouncerToDozingTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelTest.kt new file mode 100644 index 000000000000..7e937db842ff --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectValues +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class DozingToGoneTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var underTest: DozingToGoneTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + underTest = kosmos.dozingToGoneTransitionViewModel + } + + @Test + fun deviceEntryParentViewDisappear() = + testScope.runTest { + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.DOZING, + to = KeyguardState.GONE, + value = value, + transitionState = state, + ownerName = "DozingToGoneTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt new file mode 100644 index 000000000000..bf71bec9e1f6 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectValues +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class DozingToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var underTest: DozingToPrimaryBouncerTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + underTest = kosmos.dozingToPrimaryBouncerTransitionViewModel + } + + @Test + fun deviceEntryParentViewDisappear() = + testScope.runTest { + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.DOZING, + to = KeyguardState.PRIMARY_BOUNCER, + value = value, + transitionState = state, + ownerName = "DozingToPrimaryBouncerTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt index 4defe8a08d3d..aba21c946e46 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt @@ -19,12 +19,14 @@ package com.android.systemui.keyguard.ui.viewmodel 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.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.res.R import com.android.systemui.testKosmos import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat @@ -38,6 +40,7 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope + val configurationRepository by lazy { kosmos.fakeConfigurationRepository } val underTest by lazy { kosmos.dreamingToGlanceableHubTransitionViewModel } @Test @@ -66,7 +69,12 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() { @Test fun dreamOverlayTranslationX() = testScope.runTest { - val values by collectValues(underTest.dreamOverlayTranslationX(100)) + configurationRepository.setDimensionPixelSize( + R.dimen.dreaming_to_hub_transition_dream_overlay_translation_x, + -100 + ) + + val values by collectValues(underTest.dreamOverlayTranslationX) assertThat(values).isEmpty() kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt new file mode 100644 index 000000000000..11890c74a418 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +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.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.res.R +import com.android.systemui.testKosmos +import com.google.common.collect.Range +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class GlanceableHubToDreamingTransitionViewModelTest : SysuiTestCase() { + val kosmos = testKosmos() + val testScope = kosmos.testScope + + val configurationRepository by lazy { kosmos.fakeConfigurationRepository } + val underTest by lazy { kosmos.glanceableHubToDreamingTransitionViewModel } + + @Test + fun dreamOverlayAlpha() = + testScope.runTest { + val values by collectValues(underTest.dreamOverlayAlpha) + assertThat(values).isEmpty() + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + // Should start running here... + step(0.1f), + step(0.5f), + // Up to here... + step(1f), + ), + testScope, + ) + + assertThat(values).hasSize(2) + values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) } + } + + @Test + fun dreamOverlayTranslationX() = + testScope.runTest { + configurationRepository.setDimensionPixelSize( + R.dimen.hub_to_dreaming_transition_dream_overlay_translation_x, + 100 + ) + + val values by collectValues(underTest.dreamOverlayTranslationX) + assertThat(values).isEmpty() + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0.3f), + step(0.6f), + ), + testScope, + ) + + assertThat(values).hasSize(3) + values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) } + } + + private fun step( + value: Float, + state: TransitionState = TransitionState.RUNNING + ): TransitionStep { + return TransitionStep( + from = KeyguardState.GLANCEABLE_HUB, + to = KeyguardState.DREAMING, + value = value, + transitionState = state, + ownerName = GlanceableHubToDreamingTransitionViewModelTest::class.java.simpleName + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelTest.kt new file mode 100644 index 000000000000..59a6ce75e912 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelTest.kt @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +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.fakeFingerprintPropertyRepository +import com.android.systemui.coroutines.collectValues +import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class GoneToDozingTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var underTest: GoneToDozingTransitionViewModel + + @Before + fun setUp() { + fingerprintPropertyRepository = kosmos.fakeFingerprintPropertyRepository + biometricSettingsRepository = kosmos.fakeBiometricSettingsRepository + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + underTest = kosmos.goneToDozingTransitionViewModel + } + + @Test + fun deviceEntryParentViewAppear_udfpsEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) + + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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) } + } + + @Test + fun deviceEntryParentViewDisappear_noUdfpsEnrolled_noUpdates() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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).isNull() } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.DOZING, + value = value, + transitionState = state, + ownerName = "GoneToDozingTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt new file mode 100644 index 000000000000..28f5eba28763 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +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.collectValues +import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class LockscreenToDozingTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository + private lateinit var underTest: LockscreenToDozingTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + biometricSettingsRepository = kosmos.biometricSettingsRepository + underTest = kosmos.lockscreenToDozingTransitionViewModel + } + + @Test + fun deviceEntryParentViewAppear_udfpsEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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) } + } + + @Test + fun deviceEntryParentViewDisappear_udfpsNotEnrolled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + @Test + fun deviceEntryBackgroundViewDisappear() = + testScope.runTest { + val values by collectValues(underTest.deviceEntryBackgroundViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.DOZING, + value = value, + transitionState = state, + ownerName = "LockscreenToDozingTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt new file mode 100644 index 000000000000..28473b204ce3 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +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.collectValues +import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +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.TransitionState.RUNNING +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.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class PrimaryBouncerToDozingTransitionViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository + private lateinit var underTest: PrimaryBouncerToDozingTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + biometricSettingsRepository = kosmos.biometricSettingsRepository + underTest = kosmos.primaryBouncerToDozingTransitionViewModel + } + + @Test + fun deviceEntryParentViewAppear_udfpsEnrolledAndEnabled() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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) } + } + + @Test + fun deviceEntryParentView_udfpsNotEnrolledAndEnabled_noUpdates() = + testScope.runTest { + fingerprintPropertyRepository.supportsUdfps() + biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + val values by collectValues(underTest.deviceEntryParentViewAlpha) + + 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).isNull() } + } + + @Test + fun deviceEntryBackgroundViewDisappear() = + testScope.runTest { + val values by collectValues(underTest.deviceEntryBackgroundViewAlpha) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + step(0f, TransitionState.STARTED), + step(0f), + step(0.1f), + step(0.2f), + step(0.3f), + step(1f), + ), + testScope, + ) + + values.forEach { assertThat(it).isEqualTo(0f) } + } + + private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.PRIMARY_BOUNCER, + to = KeyguardState.DOZING, + value = value, + transitionState = state, + ownerName = "PrimaryBouncerToDozingTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt index ff8a9bd019fb..39851b6f21a7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt @@ -8,6 +8,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.FakeBroadcastDispatcher import com.android.systemui.coroutines.collectLastValue import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger +import com.android.systemui.statusbar.policy.FakeDeviceProvisionedController import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher @@ -28,6 +29,7 @@ class QSSettingsRestoredBroadcastRepositoryTest : SysuiTestCase() { private val testScope = TestScope(dispatcher) @Mock private lateinit var pipelineLogger: QSPipelineLogger + private val deviceProvisionedController = FakeDeviceProvisionedController() private lateinit var underTest: QSSettingsRestoredBroadcastRepository @@ -38,6 +40,7 @@ class QSSettingsRestoredBroadcastRepositoryTest : SysuiTestCase() { underTest = QSSettingsRestoredBroadcastRepository( fakeBroadcastDispatcher, + deviceProvisionedController, pipelineLogger, testScope.backgroundScope, dispatcher, @@ -176,6 +179,100 @@ class QSSettingsRestoredBroadcastRepositoryTest : SysuiTestCase() { } } + @Test + fun restoreAfterUserSetup_singleTilesRestoredBroadcast() = + testScope.runTest { + runCurrent() + val restoreData by collectLastValue(underTest.restoreData) + val user = 0 + + val tilesIntent = + createRestoreIntent( + RestoreType.TILES, + CURRENT_TILES, + RESTORED_TILES, + ) + + sendIntentForUser(tilesIntent, user) + + deviceProvisionedController.setUserSetup(user) + + with(restoreData!!) { + assertThat(restoredTiles).isEqualTo(RESTORED_TILES.toTilesList()) + assertThat(restoredAutoAddedTiles).isEmpty() + assertThat(userId).isEqualTo(user) + } + } + + @Test + fun restoreAfterUserSetup_singleAutoAddRestoredBroadcast_noRestore() = + testScope.runTest { + runCurrent() + val restoreData by collectLastValue(underTest.restoreData) + val user = 0 + + val autoAddIntent = + createRestoreIntent( + RestoreType.AUTOADD, + CURRENT_AUTO_ADDED_TILES, + RESTORED_AUTO_ADDED_TILES, + ) + + sendIntentForUser(autoAddIntent, user) + + deviceProvisionedController.setUserSetup(user) + + assertThat(restoreData).isNull() + } + + @Test + fun restoreAfterUserSetup_otherUserFinishedSetup_noRestore() = + testScope.runTest { + runCurrent() + val restoreData by collectLastValue(underTest.restoreData) + val user = 0 + + val tilesIntent = + createRestoreIntent( + RestoreType.TILES, + CURRENT_TILES, + RESTORED_TILES, + ) + + sendIntentForUser(tilesIntent, user) + + deviceProvisionedController.setUserSetup(user + 1) + + assertThat(restoreData).isNull() + } + + @Test + fun restoreAfterUserSetup_otherUserFinishedSetup_thenCorrectUser_restored() = + testScope.runTest { + runCurrent() + val restoreData by collectLastValue(underTest.restoreData) + val user = 0 + + val tilesIntent = + createRestoreIntent( + RestoreType.TILES, + CURRENT_TILES, + RESTORED_TILES, + ) + + sendIntentForUser(tilesIntent, user) + + deviceProvisionedController.setUserSetup(user + 1) + runCurrent() + deviceProvisionedController.setUserSetup(user) + + with(restoreData!!) { + assertThat(restoredTiles).isEqualTo(RESTORED_TILES.toTilesList()) + assertThat(restoredAutoAddedTiles).isEmpty() + assertThat(userId).isEqualTo(user) + } + } + private fun sendIntentForUser(intent: Intent, userId: Int) { fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( context, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index 82862e021b4c..1eb9adb8c004 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.UserAction import com.android.systemui.scene.shared.model.UserActionResult import com.android.systemui.shade.domain.interactor.privacyChipInteractor +import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository @@ -97,6 +98,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { mobileIconsInteractor = mobileIconsInteractor, mobileIconsViewModel = mobileIconsViewModel, privacyChipInteractor = kosmos.privacyChipInteractor, + clockInteractor = kosmos.shadeHeaderClockInteractor, broadcastDispatcher = fakeBroadcastDispatcher, ) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index af2835126261..4e72843922e1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -66,6 +66,7 @@ import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.shade.domain.interactor.privacyChipInteractor +import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor @@ -143,6 +144,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { SceneContainerViewModel( sceneInteractor = sceneInteractor, falsingInteractor = kosmos.falsingInteractor, + powerInteractor = kosmos.powerInteractor, ) .apply { setTransitionState(transitionState) } } @@ -234,6 +236,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { mobileIconsInteractor = mobileIconsInteractor, mobileIconsViewModel = mobileIconsViewModel, privacyChipInteractor = kosmos.privacyChipInteractor, + clockInteractor = kosmos.shadeHeaderClockInteractor, broadcastDispatcher = fakeBroadcastDispatcher, ) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt index 4b9ebdc295c6..dd3eb6845789 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt @@ -22,7 +22,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.kosmos.testScope -import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.sceneContainerConfig import com.android.systemui.scene.sceneKeys @@ -276,12 +275,4 @@ class SceneInteractorTest : SysuiTestCase() { underTest.setVisible(true, "reason") assertThat(isVisible).isTrue() } - - @Test - fun userInput() = - testScope.runTest { - assertThat(kosmos.fakePowerRepository.userTouchRegistered).isFalse() - underTest.onUserInput() - assertThat(kosmos.fakePowerRepository.userTouchRegistered).isTrue() - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index 39a5319946ef..ffbdafe338e7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt @@ -25,6 +25,8 @@ import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.classifier.fakeFalsingManager import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope +import com.android.systemui.power.data.repository.fakePowerRepository +import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.sceneContainerConfig import com.android.systemui.scene.sceneKeys @@ -32,6 +34,7 @@ import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -61,6 +64,7 @@ class SceneContainerViewModelTest : SysuiTestCase() { SceneContainerViewModel( sceneInteractor = interactor, falsingInteractor = kosmos.falsingInteractor, + powerInteractor = kosmos.powerInteractor, ) } @@ -187,4 +191,12 @@ class SceneContainerViewModelTest : SysuiTestCase() { .isTrue() } } + + @Test + fun userInput() = + testScope.runTest { + assertThat(kosmos.fakePowerRepository.userTouchRegistered).isFalse() + underTest.onMotionEvent(mock()) + assertThat(kosmos.fakePowerRepository.userTouchRegistered).isTrue() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryTest.kt new file mode 100644 index 000000000000..d7b77e613c2d --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryTest.kt @@ -0,0 +1,58 @@ +/* + * 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.data.repository + +import android.app.AlarmManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.testScope +import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback +import com.android.systemui.statusbar.policy.nextAlarmController +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.withArgCaptor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@SmallTest +@RunWith(AndroidJUnit4::class) +class ShadeHeaderClockRepositoryTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val nextAlarmController = kosmos.nextAlarmController + + val underTest = kosmos.shadeHeaderClockRepository + + @Test + fun nextAlarmIntent_updates() = + testScope.runTest { + assertThat(underTest.nextAlarmIntent).isNull() + + val callback = + withArgCaptor<NextAlarmChangeCallback> { + verify(nextAlarmController).addCallback(capture()) + } + + callback.onNextAlarmChanged(AlarmManager.AlarmClockInfo(1L, mock())) + assertThat(underTest.nextAlarmIntent).isNotNull() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt new file mode 100644 index 000000000000..84fc93008f49 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt @@ -0,0 +1,80 @@ +/* + * 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 android.app.AlarmManager +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.kosmos.testScope +import com.android.systemui.plugins.activityStarter +import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback +import com.android.systemui.statusbar.policy.nextAlarmController +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argThat +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.withArgCaptor +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatcher +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@SmallTest +@RunWith(AndroidJUnit4::class) +class ShadeHeaderClockInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val activityStarter = kosmos.activityStarter + private val nextAlarmController = kosmos.nextAlarmController + + val underTest = kosmos.shadeHeaderClockInteractor + + @Test + fun launchClockActivity_default() = + testScope.runTest { + underTest.launchClockActivity() + verify(activityStarter) + .postStartActivityDismissingKeyguard( + argThat(IntentMatcherAction(AlarmClock.ACTION_SHOW_ALARMS)), + any() + ) + } + + @Test + fun launchClockActivity_nextAlarmIntent() = + testScope.runTest { + val callback = + withArgCaptor<NextAlarmChangeCallback> { + verify(nextAlarmController).addCallback(capture()) + } + callback.onNextAlarmChanged(AlarmManager.AlarmClockInfo(1L, mock())) + + underTest.launchClockActivity() + verify(activityStarter).postStartActivityDismissingKeyguard(any()) + } +} + +private class IntentMatcherAction(private val action: String) : ArgumentMatcher<Intent> { + override fun matches(argument: Intent?): Boolean { + return argument?.action == action + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt index 1ef307617c4e..062741df01cf 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt @@ -1,5 +1,7 @@ package com.android.systemui.shade.ui.viewmodel +import android.content.Intent +import android.provider.AlarmClock import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest @@ -8,7 +10,9 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.kosmos.testScope +import com.android.systemui.plugins.activityStarter import com.android.systemui.shade.domain.interactor.privacyChipInteractor +import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel @@ -18,12 +22,16 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsVi import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.argThat import com.android.systemui.util.mockito.mock 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.ArgumentMatcher +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest @@ -64,6 +72,7 @@ class ShadeHeaderViewModelTest : SysuiTestCase() { mobileIconsInteractor = mobileIconsInteractor, mobileIconsViewModel = mobileIconsViewModel, privacyChipInteractor = kosmos.privacyChipInteractor, + clockInteractor = kosmos.shadeHeaderClockInteractor, broadcastDispatcher = fakeBroadcastDispatcher, ) } @@ -81,6 +90,19 @@ class ShadeHeaderViewModelTest : SysuiTestCase() { assertThat(mobileSubIds).isEqualTo(listOf(1, 2)) } + @Test + fun onClockClicked_launchesClock() = + testScope.runTest { + val activityStarter = kosmos.activityStarter + underTest.onClockClicked() + + verify(activityStarter) + .postStartActivityDismissingKeyguard( + argThat(IntentMatcherAction(AlarmClock.ACTION_SHOW_ALARMS)), + anyInt(), + ) + } + companion object { private val SUB_1 = SubscriptionModel( @@ -98,3 +120,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() { ) } } + +private class IntentMatcherAction(private val action: String) : ArgumentMatcher<Intent> { + override fun matches(argument: Intent?): Boolean { + return argument?.action == action + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index 33c2d4ef7b3b..d655ade5cf2c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt @@ -32,6 +32,7 @@ import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.domain.interactor.privacyChipInteractor +import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor @@ -100,6 +101,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() { mobileIconsInteractor = mobileIconsInteractor, mobileIconsViewModel = mobileIconsViewModel, privacyChipInteractor = kosmos.privacyChipInteractor, + clockInteractor = kosmos.shadeHeaderClockInteractor, broadcastDispatcher = fakeBroadcastDispatcher, ) @@ -167,6 +169,32 @@ class ShadeSceneViewModelTest : SysuiTestCase() { } @Test + fun isClickable_deviceUnlocked_false() = + testScope.runTest { + val isClickable by collectLastValue(underTest.isClickable) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin + ) + kosmos.fakeDeviceEntryRepository.setUnlocked(true) + runCurrent() + + assertThat(isClickable).isFalse() + } + + @Test + fun isClickable_deviceLockedSecurely_true() = + testScope.runTest { + val isClickable by collectLastValue(underTest.isClickable) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin + ) + kosmos.fakeDeviceEntryRepository.setUnlocked(false) + runCurrent() + + assertThat(isClickable).isTrue() + } + + @Test fun onContentClicked_deviceUnlocked_switchesToGone() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt new file mode 100644 index 000000000000..e188f5bfc1c8 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.domain.interactor + +import android.app.NotificationManager +import android.media.AudioManager +import android.provider.Settings.Global +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.settingslib.statusbar.notification.data.model.ZenMode +import com.android.settingslib.statusbar.notification.data.repository.updateNotificationPolicy +import com.android.settingslib.statusbar.notification.domain.interactor.NotificationsSoundPolicyInteractor +import com.android.settingslib.volume.shared.model.AudioStream +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Expect +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class NotificationsSoundPolicyInteractorTest : SysuiTestCase() { + + @JvmField @Rule val expect = Expect.create() + + private val kosmos = testKosmos() + + private lateinit var underTest: NotificationsSoundPolicyInteractor + + @Before + fun setup() { + with(kosmos) { + underTest = NotificationsSoundPolicyInteractor(notificationsSoundPolicyRepository) + } + } + + @Test + fun onlyAlarmsCategory_areAlarmsAllowed_isTrue() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode(ZenMode(Global.ZEN_MODE_OFF)) + val expectedByCategory = + NotificationManager.Policy.ALL_PRIORITY_CATEGORIES.associateWith { + it == NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS + } + expectedByCategory.forEach { entry -> + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = entry.key + ) + + val areAlarmsAllowed by collectLastValue(underTest.areAlarmsAllowed) + runCurrent() + + expect.that(areAlarmsAllowed).isEqualTo(entry.value) + } + } + } + } + + @Test + fun onlyMediaCategory_areAlarmsAllowed_isTrue() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode(ZenMode(Global.ZEN_MODE_OFF)) + val expectedByCategory = + NotificationManager.Policy.ALL_PRIORITY_CATEGORIES.associateWith { + it == NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA + } + expectedByCategory.forEach { entry -> + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = entry.key + ) + + val isMediaAllowed by collectLastValue(underTest.isMediaAllowed) + runCurrent() + + expect.that(isMediaAllowed).isEqualTo(entry.value) + } + } + } + } + + @Test + fun atLeastOneCategoryAllowed_isRingerAllowed_isTrue() { + with(kosmos) { + testScope.runTest { + for (category in NotificationManager.Policy.ALL_PRIORITY_CATEGORIES) { + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = category, + state = NotificationManager.Policy.STATE_UNSET, + ) + + val isRingerAllowed by collectLastValue(underTest.isRingerAllowed) + runCurrent() + + expect.that(isRingerAllowed).isTrue() + } + } + } + } + + @Test + fun allCategoriesAllowed_isRingerAllowed_isTrue() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = + NotificationManager.Policy.ALL_PRIORITY_CATEGORIES.reduce { acc, value -> + acc or value + }, + state = NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED, + ) + + val isRingerAllowed by collectLastValue(underTest.isRingerAllowed) + runCurrent() + + assertThat(isRingerAllowed).isTrue() + } + } + } + + @Test + fun noCategoriesAndBlocked_isRingerAllowed_isFalse() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = 0, + state = NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED, + ) + + val isRingerAllowed by collectLastValue(underTest.isRingerAllowed) + runCurrent() + + assertThat(isRingerAllowed).isFalse() + } + } + } + + @Test + fun zenModeNoInterruptions_allStreams_muted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateNotificationPolicy() + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Global.ZEN_MODE_NO_INTERRUPTIONS) + ) + + for (stream in AudioStream.supportedStreamTypes) { + val isZenMuted by collectLastValue(underTest.isZenMuted(AudioStream(stream))) + runCurrent() + + expect.that(isZenMuted).isTrue() + } + } + } + } + + @Test + fun zenModeOff_allStreams_notMuted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateNotificationPolicy() + notificationsSoundPolicyRepository.updateZenMode(ZenMode(Global.ZEN_MODE_OFF)) + + for (stream in AudioStream.supportedStreamTypes) { + val isZenMuted by collectLastValue(underTest.isZenMuted(AudioStream(stream))) + runCurrent() + + expect.that(isZenMuted).isFalse() + } + } + } + } + + @Test + fun zenModeAlarms_ringAndNotifications_muted() { + with(kosmos) { + val expectedToBeMuted = + setOf(AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION) + testScope.runTest { + notificationsSoundPolicyRepository.updateNotificationPolicy() + notificationsSoundPolicyRepository.updateZenMode(ZenMode(Global.ZEN_MODE_ALARMS)) + + for (stream in AudioStream.supportedStreamTypes) { + val isZenMuted by collectLastValue(underTest.isZenMuted(AudioStream(stream))) + runCurrent() + + expect.that(isZenMuted).isEqualTo(stream in expectedToBeMuted) + } + } + } + } + + @Test + fun alarms_allowed_notMuted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + ) + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS + ) + + val isZenMuted by + collectLastValue(underTest.isZenMuted(AudioStream(AudioManager.STREAM_ALARM))) + runCurrent() + + expect.that(isZenMuted).isFalse() + } + } + } + + @Test + fun media_allowed_notMuted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + ) + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA + ) + + val isZenMuted by + collectLastValue(underTest.isZenMuted(AudioStream(AudioManager.STREAM_MUSIC))) + runCurrent() + + expect.that(isZenMuted).isFalse() + } + } + } + + @Test + fun ringer_allowed_notificationsNotMuted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + ) + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = + NotificationManager.Policy.ALL_PRIORITY_CATEGORIES.reduce { acc, value -> + acc or value + }, + state = NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED, + ) + + val isZenMuted by + collectLastValue( + underTest.isZenMuted(AudioStream(AudioManager.STREAM_NOTIFICATION)) + ) + runCurrent() + + expect.that(isZenMuted).isFalse() + } + } + } + + @Test + fun ringer_allowed_ringNotMuted() { + with(kosmos) { + testScope.runTest { + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + ) + notificationsSoundPolicyRepository.updateNotificationPolicy( + priorityCategories = + NotificationManager.Policy.ALL_PRIORITY_CATEGORIES.reduce { acc, value -> + acc or value + }, + state = NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED, + ) + + val isZenMuted by + collectLastValue(underTest.isZenMuted(AudioStream(AudioManager.STREAM_RING))) + runCurrent() + + expect.that(isZenMuted).isFalse() + } + } + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt new file mode 100644 index 000000000000..a2f3ccb8c416 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.domain.interactor + +import android.media.AudioManager +import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.settingslib.statusbar.notification.data.model.ZenMode +import com.android.settingslib.statusbar.notification.data.repository.updateNotificationPolicy +import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor +import com.android.settingslib.volume.shared.model.AudioStream +import com.android.settingslib.volume.shared.model.RingerMode +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyInteractor +import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyRepository +import com.android.systemui.testKosmos +import com.android.systemui.volume.audioRepository +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +@SmallTest +class AudioVolumeInteractorTest : SysuiTestCase() { + + private val kosmos = testKosmos() + + private lateinit var underTest: AudioVolumeInteractor + + @Before + fun setup() { + with(kosmos) { + underTest = AudioVolumeInteractor(audioRepository, notificationsSoundPolicyInteractor) + + audioRepository.setRingerMode(RingerMode(AudioManager.RINGER_MODE_NORMAL)) + + notificationsSoundPolicyRepository.updateNotificationPolicy() + notificationsSoundPolicyRepository.updateZenMode(ZenMode(Settings.Global.ZEN_MODE_OFF)) + } + } + + @Test + fun setMuted_mutesStream() { + with(kosmos) { + testScope.runTest { + val model by collectLastValue(underTest.getAudioStream(audioStream)) + + underTest.setMuted(audioStream, false) + runCurrent() + assertThat(model!!.isMuted).isFalse() + + underTest.setMuted(audioStream, true) + runCurrent() + assertThat(model!!.isMuted).isTrue() + } + } + } + + @Test + fun setVolume_changesVolume() { + with(kosmos) { + testScope.runTest { + val model by collectLastValue(underTest.getAudioStream(audioStream)) + + underTest.setVolume(audioStream, 10) + runCurrent() + assertThat(model!!.volume).isEqualTo(10) + + underTest.setVolume(audioStream, 20) + runCurrent() + assertThat(model!!.volume).isEqualTo(20) + } + } + } + + @Test + fun ringMuted_notificationVolume_cantChange() { + with(kosmos) { + testScope.runTest { + val canChangeVolume by + collectLastValue( + underTest.canChangeVolume(AudioStream(AudioManager.STREAM_NOTIFICATION)) + ) + + underTest.setMuted(AudioStream(AudioManager.STREAM_RING), true) + runCurrent() + + assertThat(canChangeVolume).isFalse() + } + } + } + + @Test + fun streamIsMuted_getStream_volumeZero() { + with(kosmos) { + testScope.runTest { + val model by collectLastValue(underTest.getAudioStream(audioStream)) + + underTest.setMuted(audioStream, true) + runCurrent() + + assertThat(model!!.volume).isEqualTo(0) + } + } + } + + @Test + fun streamIsZenMuted_getStream_lastAudibleVolume() { + with(kosmos) { + testScope.runTest { + audioRepository.setLastAudibleVolume(audioStream, 30) + notificationsSoundPolicyRepository.updateZenMode( + ZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) + ) + + val model by collectLastValue(underTest.getAudioStream(audioStream)) + runCurrent() + + assertThat(model!!.volume).isEqualTo(30) + } + } + } + + @Test + fun ringerModeVibrateAndMuted_getNotificationStream_volumeIsZero() { + with(kosmos) { + testScope.runTest { + audioRepository.setRingerMode(RingerMode(AudioManager.RINGER_MODE_VIBRATE)) + underTest.setMuted(AudioStream(AudioManager.STREAM_NOTIFICATION), true) + + val model by + collectLastValue( + underTest.getAudioStream(AudioStream(AudioManager.STREAM_NOTIFICATION)) + ) + runCurrent() + + assertThat(model!!.volume).isEqualTo(0) + } + } + } + + @Test + fun ringerModeVibrate_getRingerStream_volumeIsZero() { + with(kosmos) { + testScope.runTest { + audioRepository.setRingerMode(RingerMode(AudioManager.RINGER_MODE_VIBRATE)) + + val model by + collectLastValue( + underTest.getAudioStream(AudioStream(AudioManager.STREAM_RING)) + ) + runCurrent() + + assertThat(model!!.volume).isEqualTo(0) + } + } + } + + private companion object { + val audioStream = AudioStream(AudioManager.STREAM_SYSTEM) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt new file mode 100644 index 000000000000..a1e4fcafd3a4 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.domain.interactor + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class VolumeSliderInteractorTest : SysuiTestCase() { + + private val underTest = VolumeSliderInteractor() + + @Test + fun translateValueToVolume() { + assertThat(underTest.translateValueToVolume(30f, volumeRange)).isEqualTo(3) + } + + @Test + fun processVolumeToValue_muted_zero() { + assertThat(underTest.processVolumeToValue(3, volumeRange, null, true)).isEqualTo(0) + } + + @Test + fun processVolumeToValue_currentValue_currentValue() { + assertThat(underTest.processVolumeToValue(3, volumeRange, 30f, false)).isEqualTo(30f) + } + + @Test + fun processVolumeToValue_currentValueDiffersVolume_returnsTranslatedVolume() { + assertThat(underTest.processVolumeToValue(1, volumeRange, 60f, false)).isEqualTo(10f) + } + + @Test + fun processVolumeToValue_currentValueDiffersNotEnoughVolume_returnsTranslatedVolume() { + assertThat(underTest.processVolumeToValue(1, volumeRange, 12f, false)).isEqualTo(12f) + } + + private companion object { + val volumeRange = 0..10 + } +} diff --git a/packages/SystemUI/res/drawable/ic_call.xml b/packages/SystemUI/res/drawable/ic_call.xml new file mode 100644 index 000000000000..859506ad5e7c --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_call.xml @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="960" + android:viewportHeight="960" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M798,840Q673,840 551,785.5Q429,731 329,631Q229,531 174.5,409Q120,287 120,162Q120,144 132,132Q144,120 162,120L324,120Q338,120 349,129.5Q360,139 362,152L388,292Q390,308 387,319Q384,330 376,338L279,436Q299,473 326.5,507.5Q354,542 387,574Q418,605 452,631.5Q486,658 524,680L618,586Q627,577 641.5,572.5Q656,568 670,570L808,598Q822,602 831,612.5Q840,623 840,636L840,798Q840,816 828,828Q816,840 798,840ZM241,360L307,294Q307,294 307,294Q307,294 307,294L290,200Q290,200 290,200Q290,200 290,200L201,200Q201,200 201,200Q201,200 201,200Q206,241 215,281Q224,321 241,360ZM599,718Q638,735 678.5,745Q719,755 760,758Q760,758 760,758Q760,758 760,758L760,670Q760,670 760,670Q760,670 760,670L666,651Q666,651 666,651Q666,651 666,651L599,718ZM241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360ZM599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_filled_arrow_down.xml b/packages/SystemUI/res/drawable/ic_filled_arrow_down.xml new file mode 100644 index 000000000000..c85965fd0e58 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_filled_arrow_down.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="24" + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> + <path + android:pathData="M7 10l5 5 5 -5z" + android:fillColor="#FF000000"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_filled_arrow_up.xml b/packages/SystemUI/res/drawable/ic_filled_arrow_up.xml new file mode 100644 index 000000000000..8ee7e1330531 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_filled_arrow_up.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="24" + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> + <path + android:pathData="M7 14l5-5 5 5z" + android:fillColor="#FF000000"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_music_note_off.xml b/packages/SystemUI/res/drawable/ic_music_note_off.xml new file mode 100644 index 000000000000..d583576911dd --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_music_note_off.xml @@ -0,0 +1,25 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="#FF000000" + android:pathData="M792,904L56,168L112,112L848,848L792,904ZM560,446L480,366L480,120L720,120L720,280L560,280L560,446ZM400,840Q334,840 287,793Q240,746 240,680Q240,614 287,567Q334,520 400,520Q423,520 442.5,525.5Q462,531 480,542L480,480L560,560L560,680Q560,746 513,793Q466,840 400,840Z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_volume_off.xml b/packages/SystemUI/res/drawable/ic_volume_off.xml new file mode 100644 index 000000000000..209f684436ee --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volume_off.xml @@ -0,0 +1,27 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="960" + android:viewportHeight="960" + android:tint="?attr/colorControlNormal" + android:autoMirrored="true"> + <path + android:fillColor="@android:color/white" + android:pathData="M792,904L671,783Q646,799 618,810.5Q590,822 560,829L560,747Q574,742 587.5,737Q601,732 613,725L480,592L480,800L280,600L120,600L120,360L248,360L56,168L112,112L848,848L792,904ZM784,672L726,614Q743,583 751.5,549Q760,515 760,479Q760,385 705,311Q650,237 560,211L560,129Q684,157 762,254.5Q840,352 840,479Q840,532 825.5,581Q811,630 784,672ZM650,538L560,448L560,318Q607,340 633.5,384Q660,428 660,480Q660,495 657.5,509.5Q655,524 650,538ZM480,368L376,264L480,160L480,368ZM400,606L400,512L328,440L328,440L200,440L200,520L314,520L400,606ZM364,476L364,476L364,476L364,476L364,476L364,476L364,476L364,476Z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml index 37964158a4aa..2616e8ae25e8 100644 --- a/packages/SystemUI/res/layout/screen_share_dialog.xml +++ b/packages/SystemUI/res/layout/screen_share_dialog.xml @@ -67,12 +67,12 @@ android:gravity="start"/> <!-- Buttons --> - <LinearLayout + <com.android.internal.widget.ButtonBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="@dimen/screenrecord_buttons_margin_top"> - <TextView + <Button android:id="@android:id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -83,13 +83,13 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> - <TextView + <Button android:id="@android:id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:text="@string/screenrecord_continue" style="@style/Widget.Dialog.Button" /> - </LinearLayout> + </com.android.internal.widget.ButtonBarLayout> </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index d05a1fcfaaf4..4002517b2cd4 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gestoor"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ontkoppel"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveer"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Skakel dit môre outomaties weer aan"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Kenmerke soos Kitsdeel, Kry My Toestel en toestelligging gebruik Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batterykrag"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Oudio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Kopstuk"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Hierdie toestel word deur jou ouer bestuur. Jou ouer kan inligting sien en bestuur soos die programme wat jy gebruik, jou ligging en jou skermtyd."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ontsluit gehou deur TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Diefstalbeskerming\nToestel gesluit; te veel pogings om te ontsluit"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Klankinstellings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Gee outomaties mediaopskrifte"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiveer"</string> <string name="sound_settings" msgid="8874581353127418308">"Klank en vibrasie"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellings"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Intydse Onderskrifte"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume is verlaag na ’n veiliger vlak"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Oorfoonvolume was langer as wat aanbeveel word hoog"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Oorfoonvolume het die veilige limiet vir hierdie week oorskry"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibreer"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volumekontroles"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Oproepe en kennisgewings sal lui (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> speel tans op"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Oudio sal speel op"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Stelsel-UI-ontvanger"</string> <string name="status_bar" msgid="4357390266055077437">"Statusbalk"</string> <string name="demo_mode" msgid="263484519766901593">"Stelsel-UI-demonstrasiemodus"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 6ee6c996e70b..ebc20027209f 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ተቀምጧል"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ግንኙነትን አቋርጥ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ያግብሩ"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ነገ እንደገና በራስ-ሰር አስጀምር"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"እንደ ፈጣን ማጋራት፣ የእኔን መሣሪያ አግኝ እና የመሣሪያ አካባቢ ያሉ ባህሪያት ብሉቱዝን ይጠቀማሉ"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ባትሪ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ኦዲዮ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ማዳመጫ"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ይህ መሣሪያ በእርስዎ ወላጅ የሚተዳደር ነው። ወላጅዎ የሚጠቀሙባቸውን መተግበሪያዎች፣ አካባቢዎን እና የማያ ገፅ ጊዜዎን የመሳሰሉ መረጃዎችን ማየት እና ማስተዳደር ይችላል።"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"በ TrustAgent እንደተከፈተ ቀርቷል"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"የስርቆት መከላከያ\nመሳሪያ ተቆልፏል፣ በጣም ብዙ የመክፈት ሙከራዎች"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>። <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"የድምፅ ቅንብሮች"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ራስሰር የሥዕል መግለጫ ጽሑፍን ሚዲያ"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ንዘር"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s የድምፅ መቆጣጠሪያዎች"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ጥሪዎች እና ማሳወቂያዎች (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>) ላይ ይደውላሉ"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> እየተጫወተ ያለው በ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ኦዲዮ ይጫወታል በ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"የስርዓት በይነገጽ መቃኛ"</string> <string name="status_bar" msgid="4357390266055077437">"የሁኔታ አሞሌ"</string> <string name="demo_mode" msgid="263484519766901593">"የስርዓት ተጠቃሚ በይነገጽ ማሳያ ሁነታ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index fdad1cfe9b38..ec72578f9fc3 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"إلغاء الربط"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"تفعيل"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"تفعيل البلوتوث تلقائيًا مرة أخرى غدًا"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"يُستخدَم البلوتوث في ميزات مثل Quick Share و\"العثور على جهازي\" والموقع الجغرافي للجهاز"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"صوت"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"سماعة الرأس"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"يتولّى أحد الوالدين إدارة هذا الجهاز. يمكن للوالدين عرض وإدارة معلوماتك، مثلاً التطبيقات التي تستخدمها وموقعك الجغرافي ووقت النظر إلى الشاشة."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"شبكة افتراضية خاصة"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"فتح القفل باستمرار بواسطة TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"تم قفل الجهاز\nلحمايته من السرقة بسبب إجراء العديد من محاولات إلغاء القفل."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"إعدادات الصوت"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"شرح تلقائي للوسائط"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"اهتزاز"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s عنصر للتحكم في مستوى الصوت"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"سيصدر الهاتف رنينًا عند تلقي المكالمات والإشعارات (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)."</string> + <string name="media_output_label_title" msgid="872824698593182505">"تشغيل <xliff:g id="LABEL">%s</xliff:g> على"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"سيتم تشغيل الصوت على"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"أداة ضبط واجهة مستخدم النظام"</string> <string name="status_bar" msgid="4357390266055077437">"شريط الحالة"</string> <string name="demo_mode" msgid="263484519766901593">"وضع تجريبي لواجهة مستخدم النظام"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 34141ebde3df..f66650b41451 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ছেভ কৰা হৈছে"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"সংযোগ বিচ্ছিন্ন কৰক"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"সক্ৰিয় কৰক"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"কাইলৈ পুনৰ স্বয়ংক্ৰিয়ভাৱে অন কৰক"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Find My Device আৰু ডিভাইচৰ অৱস্থানৰ দৰে সুবিধাই ব্লুটুথ ব্যৱহাৰ কৰে"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিঅ’"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডছেট"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে। আপোনাৰ অভিভাৱকে আপুনি ব্যৱহাৰ কৰা এপ্, আপোনাৰ অৱস্থান আৰু আপুনি ডিভাইচত অতিবাহিত কৰা সময়ৰ দৰে তথ্য চাব আৰু পৰিচালনা কৰিব পাৰে।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"ভিপিএন"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgentএ আনলক কৰি ৰাখিছে"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"চুৰিৰ পৰা সুৰক্ষা\nডিভাইচ লক আছে, বহুবাৰ আনলকৰ চেষ্টা কৰা হৈছে"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ধ্বনিৰ ছেটিং"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"স্বয়ংক্ৰিয় কেপশ্বন মিডিয়া"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"কম্পন কৰক"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ধ্বনি নিয়ন্ত্ৰণসমূহ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"কল আৰু জাননীবোৰ ইমান ভলিউমত বাজিব (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"ইয়াত <xliff:g id="LABEL">%s</xliff:g> প্লে’ হৈ আছে"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"অডিঅ’ ইয়াত প্লে’ হ’ব"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"স্থিতি দণ্ড"</string> <string name="demo_mode" msgid="263484519766901593">"ছিষ্টেমৰ UI প্ৰদৰ্শন ম\'ড"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 46dcc95db646..70484414a4cb 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Yadda saxlandı"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"əlaqəni kəsin"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivləşdirin"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Sabah avtomatik aktiv edin"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Cəld Paylaşım, Cihazın Tapılması və cihaz məkanı kimi funksiyalar Bluetooth istifadə edir"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batareya"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Qulaqlıq"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu cihaz valideyniniz tərəfindən idarə olunur. Valideyniniz işlətdiyiniz tətbiqlər, məkanınız və ekran vaxtınız kimi bilgiləri görə və idarə edə bilər."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN (Virtual Şəxsi Şəbəkələr)"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ilə açıq saxlayın"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Oğurluqdan qoruma\nCihaz kilidləndi. Çoxlu kilidaçma cəhdi"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Səs ayarları"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Avtomatik başlıq mediası"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrasiya"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s səs nəzarətləri"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Çağrı və bildirişlər zəng çalacaq (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> tətbiqində oxudulur"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio oxudulacaq"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status paneli"</string> <string name="demo_mode" msgid="263484519766901593">"Sistem interfeysi: demorejim"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 8e49279b4af6..a598d8f3733b 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja roditelj. Roditelj može da vidi informacije, kao što su aplikacije koje koristiš, tvoju lokaciju i vreme ispred ekrana, i da upravlja njima."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Pouzdani agent sprečava zaključavanje"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Zaštita od krađe\nZaklj. uređaj, previše pokušaja otključavanja"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Podešavanja zvuka"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatski titl za medije"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibracija"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Kontrole za jačinu zvuka za %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Melodija zvona za pozive i obaveštenja je uključena (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> se pušta na"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk se pušta na"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Tjuner za korisnički interfejs sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Statusna traka"</string> <string name="demo_mode" msgid="263484519766901593">"Režim demonstracije za korisnički interfejs sistema"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index c4a1a66a2351..2b137fb63258 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Гэта прылада знаходзіцца пад кантролем бацькоў. Бацькі могуць праглядаць і кантраляваць тваю інфармацыю, напрыклад пра праграмы, якія ты выкарыстоўваеш, даныя пра тваё месцазнаходжанне і час карыстання прыладай."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Разблакіравана з дапамогай TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Абарона ад крадзяжу\nПрылада заблакіравана з-за няўдалых спроб"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Налады гуку"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Аўтаматычныя субцітры"</string> @@ -539,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"адключыць"</string> <string name="sound_settings" msgid="8874581353127418308">"Гук і вібрацыя"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налады"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Аўтаматычныя субцітры"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Гучнасць паніжана да больш бяспечнага ўзроўню"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Гучнасць у навушніках была вялікай больш часу, чым рэкамендавана"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гучнасць у навушніках перавысіла ліміт бяспечнага праслухоўвання на гэтым тыдні"</string> @@ -584,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вібрыраваць"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Рэгулятар гучнасці %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Для выклікаў і апавяшчэнняў уключаны гук (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> прайграецца тут:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аўдыявыхад:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Наладка сістэмнага інтэрфейсу карыстальніка"</string> <string name="status_bar" msgid="4357390266055077437">"Панэль стану"</string> <string name="demo_mode" msgid="263484519766901593">"Рэжым дэманстрацыі сістэмнага інтэрфейсу карыстальніка"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index b75a7dfd5972..aa3da9caa6f9 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Запазено"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекратяване на връзката"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активиране"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматично включване отново утре"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Bluetooth се използва от различни функции, като например „Бързо споделяне“, „Намиране на устройството ми“ и местоположението на устройството"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалки"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Това устройство се управлява от родителя ви. Той може да вижда и управлява информация, като например приложенията, които използвате, местоположението ви и времето на ползване."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Поддържа се отключено от надежден агент"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Защита от кражба\nУ-вото е закл., твърде много опити за откл."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Настройки за звука"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Медия с автоматични надписи"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"деактивиране"</string> <string name="sound_settings" msgid="8874581353127418308">"Звук и вибриране"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Настройки"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Надписи на живо"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Силата на звука е намалена до по-безопасно ниво"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Нивото на силата на звука на слушалките е било високо по-дълго, отколкото е препоръчително"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Нивото на силата на звука на слушалките е надвишило безопасния лимит за тази седмица"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибриране"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Контроли за силата на звука – %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"При обаждания и известия устройството ще звъни (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Възпроизвеждане на <xliff:g id="LABEL">%s</xliff:g> на"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиото ще се възпроизвежда на"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Тунер на системния потребителски интерфейс"</string> <string name="status_bar" msgid="4357390266055077437">"Лента на състоянието"</string> <string name="demo_mode" msgid="263484519766901593">"Демонстрационен режим на системния ПИ"</string> @@ -1235,7 +1235,7 @@ <string name="assistant_attention_content_description" msgid="4166330881435263596">"Установено е присъствие на потребител"</string> <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартно приложение за бележки от настройките"</string> <string name="install_app" msgid="5066668100199613936">"Инсталиране на приложението"</string> - <string name="dismissible_keyguard_swipe" msgid="8377597870094949432">"Прекарайте пръст нагоре, за да продължите"</string> + <string name="dismissible_keyguard_swipe" msgid="8377597870094949432">"Плъзнете нагоре, за да продължите"</string> <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Да се дублира ли на външния екран?"</string> <string name="connected_display_dialog_dual_display_stop_warning" msgid="4174707498892447947">"Съдържанието на вътрешния ви дисплей ще бъде дублирано. Предният ви дисплей ще бъде изключен."</string> <string name="mirror_display" msgid="2515262008898122928">"Дублиране на дисплея"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 54cf758c5613..12e24c0a3bd3 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"সেভ করা আছে"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ডিসকানেক্ট করুন"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"চালু করুন"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"আগামীকাল অটোমেটিক আবার চালু হবে"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"দ্রুত শেয়ার, Find My Device ও ডিভাইসের লোকেশন ব্লুটুথ ব্যবহার করে"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিও"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডসেট"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"আপনার অভিভাবক এই ডিভাইস ম্যানেজ করেন। আপনার অভিভাবক আপনার ব্যবহার করা অ্যাপ, লোকেশন ও স্ক্রিন টাইমের মতো তথ্যগুলি দেখতে এবং ম্যানেজ করতে পারেন।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent দিয়ে আনলক করে রাখা হয়েছে"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"চুরি থেকে সুরক্ষা\nডিভাইস লক করা আছে, আনলক করার জন্য অনেকবার চেষ্টা করা হয়েছে"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"সাউন্ড সেটিংস"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"অটোমেটিক মিডিয়া ক্যাপশন দেখুন"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"বন্ধ হবে"</string> <string name="sound_settings" msgid="8874581353127418308">"সাউন্ড ও ভাইব্রেশন"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"সেটিংস"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"লাইভ ক্যাপশন"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ভলিউম কমিয়ে আরও নিরাপদ মাত্রায় নামানো হয়েছে"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"সাজেস্ট করা সময়ের চেয়ে অতিরিক্ত সময় ধরে হেডফোনের ভলিউম বেশি করা আছে"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"এই সপ্তাহে হেডফোনের ভলিউম নিরাপদ মাত্রা ছাড়িয়ে গেছে"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ভাইব্রেট করান"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ভলিউম নিয়ন্ত্রণ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"কল এবং বিজ্ঞপ্তির রিং হবে (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>-এ প্লে করা হচ্ছে"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"অডিও প্লে করা হবে"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"সিস্টেম UI টিউনার"</string> <string name="status_bar" msgid="4357390266055077437">"স্ট্যাটাস বার"</string> <string name="demo_mode" msgid="263484519766901593">"সিস্টেম UI ডেমো মোড"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 989daf970d7d..f79e2d915451 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekid veze"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski uključi ponovo sutra"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funkcije kao što su Quick Share, Pronađi moj uređaj i lokacija uređaja koriste Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvuk"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalice"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja tvoj roditelj. Roditelj može vidjeti i upravljati informacijama kao što su aplikacije koje koristiš, lokacija i vrijeme korištenja uređaja."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Pouzdani agent sprečava zaključavanje"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Zaštita od krađe\nUređaj je zaključan, previše pokušaja otključ."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Postavke zvuka"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatski titlovi za medije"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Kontrole glasnoće za %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Pozivi i obavještenja će zvoniti jačinom (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Reproduciranje: <xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk će se reprod. na:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Podešavač za korisnički interfejs sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Statusna traka"</string> <string name="demo_mode" msgid="263484519766901593">"Demo način rada Sistemskog UI-ja"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 6b0eabc50b69..583275f366b3 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"El teu pare o mare gestionen aquest dispositiu, i poden veure i gestionar informació com ara les aplicacions que utilitzes, la teva ubicació i el teu temps de connexió."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloquejat per TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protecció antirobatoris\nDispositiu bloquejat; massa intents"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configuració del so"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Subtitula el contingut multimèdia automàticament"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controls de volum %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Les trucades i les notificacions sonaran (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"S\'està reproduint <xliff:g id="LABEL">%s</xliff:g> a"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Es reproduirà a"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Personalitzador d\'interfície d\'usuari"</string> <string name="status_bar" msgid="4357390266055077437">"Barra d\'estat"</string> <string name="demo_mode" msgid="263484519766901593">"Mode de demostració de la IU del sistema"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 71c8a35fa08b..6cdb3d8af2a1 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Toto zařízení spravuje rodič. Rodič může zobrazit údaje, jako jsou používané aplikace, tvá poloha a čas strávený na zařízení."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Odemknutí udržováno funkcí TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Ochrana před odcizením\nZamknuto, moc pokusů o odemknutí"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Nastavení zvuku"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatické přepisy médií"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrovat"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Ovládací prvky hlasitosti %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Volání a oznámení budou vyzvánět (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Přehrávání <xliff:g id="LABEL">%s</xliff:g> na"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk se přehraje na"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Nástroj na ladění uživatelského rozhraní systému"</string> <string name="status_bar" msgid="4357390266055077437">"Stavový řádek"</string> <string name="demo_mode" msgid="263484519766901593">"Ukázkový režim uživatelského rozhraní systému"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index ab436790cc1b..79b01a84b3bb 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gemt"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"afbryd forbindelse"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivér"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivér automatisk igen i morgen"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funktioner som f.eks. Quick Share, Find min enhed og enhedslokation anvender Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din lokation og din skærmtid."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Holdes oplåst af TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Tyveribeskyttelse\nLåst enhed (for mange oplåsningsforsøg)"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Lydindstillinger"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Undertekster til medier"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string> <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Indstillinger"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Livetekstning"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Lydstyrken blev reduceret til et mere sikkert niveau"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Høretelefonernes lydstyrke har været høj i længere tid end anbefalet"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Høretelefonernes lydstyrke har overskredet sikkerhedsgrænsen for denne uge"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrer"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s lydstyrkeknapper"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Der afspilles lyd ved opkald og notifikationer (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Afspiller <xliff:g id="LABEL">%s</xliff:g> på"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Lyden afspilles på"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Statusbjælke"</string> <string name="demo_mode" msgid="263484519766901593">"Demotilstand for systemets brugerflade"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 3c4730038040..43f799bd1b68 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gespeichert"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Verknüpfung aufheben"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivieren"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Morgen automatisch wieder aktivieren"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Für Funktionen wie Quick Share, „Mein Gerät finden“ und den Gerätestandort wird Bluetooth verwendet"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dieses Gerät wird von deinen Eltern verwaltet. Sie können unter anderem Informationen über deine genutzten Apps, deinen Standort und deine Bildschirmzeit einsehen und verwalten."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Durch TrustAgent entsperrt"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Diebstahlschutz\nGerät gesperrt – zu viele Entsperrversuche"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Toneinstellungen"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Medien autom. untertiteln"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivieren"</string> <string name="sound_settings" msgid="8874581353127418308">"Ton & Vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Einstellungen"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Automatische Untertitel"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Auf verträglichere Lautstärke eingestellt"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörerlautstärke war länger als empfohlen hoch eingestellt"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Die Kopfhörerlautstärke hat für diese Woche das Sicherheitslimit überschritten"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"Vibrieren lassen"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Lautstärkeregler von %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Gerät klingelt bei Anrufen und Benachrichtigungen (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Wiedergabe von <xliff:g id="LABEL">%s</xliff:g> über"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audiowiedergabe über"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Statusleiste"</string> <string name="demo_mode" msgid="263484519766901593">"Demomodus der System-UI"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index a7a300f391e1..43ab777aa1de 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Αποθηκεύτηκε"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"αποσύνδεση"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ενεργοποίηση"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Αυτόματη ενεργοποίηση ξανά αύριο"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Λειτουργίες όπως το Quick Share, η Εύρεση συσκευής και η τοποθεσία της συσκευής χρησιμοποιούν Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ήχος"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ακουστικά"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου. Ο γονέας σου μπορεί να βλέπει και να διαχειρίζεται πληροφορίες όπως οι εφαρμογές που χρησιμοποιείς, η τοποθεσία σου και ο χρόνος χρήσης."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Διατήρηση ξεκλειδώματος με TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Προστασία από κλοπή\nΗ συσκ. κλειδ., πάρα πολλές προσπ. ξεκλ."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ρυθμίσεις ήχου"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Αυτόματοι υπότιτλοι στο μέσο"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"δόνηση"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s στοιχεία ελέγχου έντασης ήχου"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Θα υπάρχει ηχητική ειδοποίηση για κλήσεις και ειδοποιήσεις (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Αναπαραγωγή <xliff:g id="LABEL">%s</xliff:g> σε"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Ο ήχος θα παίξει σε"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Γραμμή κατάστασης"</string> <string name="demo_mode" msgid="263484519766901593">"Λειτουργία επίδειξης διεπαφής χρήστη συστήματος"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 40ad5af31440..9d2742a2b9fe 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Features like Quick Share, Find My Device and device location use Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nDevice locked, too many unlock attempts"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live Caption"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volume controls"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index a51225a1b26f..f77f66028397 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps you use, your location, and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nDevice locked, too many unlock attempts"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volume controls"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 40ad5af31440..9d2742a2b9fe 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Features like Quick Share, Find My Device and device location use Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nDevice locked, too many unlock attempts"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live Caption"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volume controls"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 40ad5af31440..9d2742a2b9fe 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Features like Quick Share, Find My Device and device location use Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nDevice locked, too many unlock attempts"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live Caption"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volume controls"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index d98ef62cad85..6f5c13362405 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps you use, your location, and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nDevice locked, too many unlock attempts"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volume controls"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index c3ade659938d..8c64a0767cfd 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tu padre o madre administra este dispositivo. Esa persona puede ver y administrar información, como las apps que usas, tu ubicación y el tiempo de uso."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent lo mantiene desbloqueado"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protección antirrobo\nDispositivo bloqueado; muchos intentos"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configuración de sonido"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Muestra subtítulos automáticos"</string> @@ -539,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inhabilitar"</string> <string name="sound_settings" msgid="8874581353127418308">"Sonido y vibración"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Subtitulado instantáneo"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Se bajó el volumen a un nivel seguro"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"El volumen de los auriculares se mantuvo elevado por más tiempo del recomendado"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Se excedió el límite seguro de volumen de los auriculares para esta semana"</string> @@ -584,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controles de volumen %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Sonarán las llamadas y notificaciones (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Reproduciendo <xliff:g id="LABEL">%s</xliff:g> en"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Se reproducirá en"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador de IU del sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string> <string name="demo_mode" msgid="263484519766901593">"Modo demostración de la IU del sistema"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 73dcea18ebc2..692bb26fb190 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tu padre o madre gestionan este dispositivo y pueden ver y controlar cierta información, como las aplicaciones que utilizas, tu ubicación y tu tiempo de pantalla."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado por TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protección antirrobo\nDispositivo bloqueado; demasiados intentos"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ajustes de sonido"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Subtitular automáticamente"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controles de volumen %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Las llamadas y las notificaciones sonarán (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Reproduciendo <xliff:g id="LABEL">%s</xliff:g> en"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Se reproducirá en"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Configurador de UI del sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string> <string name="demo_mode" msgid="263484519766901593">"Modo Demo de UI del sistema"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 0e1e690b2733..070f200f2d74 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvestatud"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkesta ühendus"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveeri"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Lülita automaatselt homme uuesti sisse"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funktsioonid, nagu Kiirjagamine, Leia mu seade ja seadme asukoht, kasutavad Bluetoothi"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> akut"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Heli"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Peakomplekt"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Seda seadet haldab sinu vanem. Sinu vanem näeb ja saab hallata teavet, näiteks kasutatavaid rakendusi, sinu asukohta ja ekraaniaega."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Avatuna hoiab TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Vargusvastane kaitse\nSeade lukus – liiga palju avamiskatseid"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Heliseaded"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automaatsed subtiitrid"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibreerimine"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Helitugevuse juhtnupud: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Kõnede ja märguannete puhul telefon heliseb (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Esitamine jätkub seadmes <xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Heli esitamine jätkub"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Süsteemi kasutajaliidese tuuner"</string> <string name="status_bar" msgid="4357390266055077437">"Olekuriba"</string> <string name="demo_mode" msgid="263484519766901593">"Süsteemi kasutajaliidese demorežiim"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index f6a4f395c055..36eac0ce42b9 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gordeta"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deskonektatu"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktibatu"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktibatu automatikoki berriro bihar"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Bilatu nire gailua, gailuaren kokapena eta beste eginbide batzuek Bluetootha darabilte"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audioa"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Entzungailua"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikusi eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPNa"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent bidez desblokeatuta"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Lapurreten aurkako babesa\nGailua blokeatuta dago, desblokeatzeko saiakera gehiegi"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Soinuaren ezarpenak"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Ezarri azpitituluak automatikoki"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desgaitu"</string> <string name="sound_settings" msgid="8874581353127418308">"Audioa eta dardara"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ezarpenak"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Istanteko azpitituluak"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Bolumena maila seguruago batera jaitsi da"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Entzungailuen bolumena gomendatutako denbora baino luzaroago egon da ozen"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Entzungailuen bolumenak aste honetarako muga segurua gainditu du"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"dardara"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s gailuaren bolumena kontrolatzeko aukerak"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Tonuak jo egingo du deiak eta jakinarazpenak jasotzean (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> hemen erreproduzitzen:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audioa erreproduzitzen jarraituko du"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sistemaren erabiltzaile-interfazearen konfiguratzailea"</string> <string name="status_bar" msgid="4357390266055077437">"Egoera-barra"</string> <string name="demo_mode" msgid="263484519766901593">"Sistemaren erabiltzaile-interfazearen demo modua"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 7a29b27ca705..b3a5e36327db 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ذخیرهشده"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"قطع اتصال"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کردن"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"فردا دوباره بهطور خودکار روشن شود"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ویژگیهایی مثل «همرسانی سریع»، «پیدا کردن دستگاهم»، و مکان دستگاه از بلوتوث استفاده میکنند"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"شارژ باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"صوت"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"هدست"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"این دستگاه را ولیتان مدیریت میکند. ولیتان میتواند اطلاعاتی مثل برنامههایی که استفاده میکنید، مکانتان، و مدت تماشای صفحهتان را ببیند و مدیریت کند."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"با TrustAgent قفل را باز نگهدارید"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"محافظت دربرابر سرقت\nدستگاه قفل شد، تعداد تلاشها قفلگشایی از حد مجاز بیشتر بود"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"تنظیمات صدا"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"رسانه زیرنویس خودکار"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"لرزش"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s کنترلهای میزان صدا"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"تماسها و اعلانها زنگ میخورند (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"درحال پخش <xliff:g id="LABEL">%s</xliff:g> در"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"صدا پخش میشود در"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"تنظیمکننده واسط کاربری سیستم"</string> <string name="status_bar" msgid="4357390266055077437">"نوار وضعیت"</string> <string name="demo_mode" msgid="263484519766901593">"حالت نمایشی واسط کاربری سیستم"</string> @@ -1234,7 +1235,7 @@ <string name="assistant_attention_content_description" msgid="4166330881435263596">"حضور کاربر شناسایی میشود"</string> <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"برنامه پیشفرض یادداشت را در «تنظیمات» تنظیم کنید"</string> <string name="install_app" msgid="5066668100199613936">"نصب برنامه"</string> - <string name="dismissible_keyguard_swipe" msgid="8377597870094949432">"برای ادامه دادن تند بهبالا بکشید"</string> + <string name="dismissible_keyguard_swipe" msgid="8377597870094949432">"برای ادامه دادن، تند بهبالا بکشید"</string> <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"روی نمایشگر خارجی قرینهسازی شود؟"</string> <string name="connected_display_dialog_dual_display_stop_warning" msgid="4174707498892447947">"نمایشگر داخلی شما قرینهسازی میشود. نمایشگر جلو خاموش میشود."</string> <string name="mirror_display" msgid="2515262008898122928">"قرینهسازی نمایشگر"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 8f85edfd309b..47e7f2d7dd2d 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Tallennettu"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkaise yhteys"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivoi"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Laita automaattisesti päälle taas huomenna"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Ominaisuudet (esim. Quick Share ja Paikanna laite) ja laitteen sijainti käyttävät Bluetoothia"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ääni"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Vanhempasi ylläpitää tätä laitetta. Vanhempasi voi nähdä ja ylläpitää tietoja, esim. käyttämiäsi sovelluksia, sijaintiasi ja käyttöaikaasi."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent pitää lukitusta avattuna"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Varkaussuoja\nLaite lukittu, liian monta avausyritystä"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ääniasetukset"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Tekstitä media automaatt."</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"poista käytöstä"</string> <string name="sound_settings" msgid="8874581353127418308">"Ääni ja värinä"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Asetukset"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Livetekstitys"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Äänenvoimakkuus laskettu turvalliselle tasolle"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Äänenvoimakkuus on ollut suuri suositeltua kauemmin"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Kuulokkeiden äänenvoimakkuus on ylittänyt tämän viikon turvarajan"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"värinä"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Äänenvoimakkuuden säädin: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Puhelut ja ilmoitukset soivat (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Toistetaan: <xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audiota toistetaan laitteella"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Tilapalkki"</string> <string name="demo_mode" msgid="263484519766901593">"Käyttöliittymän esittelytila"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index e95955589a22..1bb8147b9cdf 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Déconnecter"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"Activer"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Activer le Bluetooth automatiquement demain"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Les fonctionnalités comme le Partage rapide, Localiser mon appareil et la position de l\'appareil utilisent le Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Écouteurs"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par ton parent. Ton parent peut voir et gérer de l\'information, comme les applications que tu utilises, ta position et ton temps d\'utilisation des écrans."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"RPV"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Maintenu déverrouillé par TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protection c. le vol\nAppareil verrouillé, trop de tentatives"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Paramètres sonores"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sous-titrer automatiquement"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string> <string name="sound_settings" msgid="8874581353127418308">"Son et vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Paramètres"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Sous-titres instantanés"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume réduit à un niveau plus sécuritaire"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Le niveau du volume des écouteurs est resté élevé au-delà de la durée recommandée"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Le niveau du volume des écouteurs a dépassé la limite de sécurité pour cette semaine"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibration"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Commandes de volume de %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Les appels et les notifications seront annoncés par une sonnerie (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Lecture de <xliff:g id="LABEL">%s</xliff:g> sur"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Lecture audio sur"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Barre d\'état"</string> <string name="demo_mode" msgid="263484519766901593">"Mode Démo de l\'interface système"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index a04f6e8800ee..84160af98955 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -81,7 +81,7 @@ <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string> <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Impossible d\'enregistrer la capture d\'écran"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string> - <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"La prise de captures d\'écran est bloquée par votre administrateur informatique"</string> + <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"La capture d\'écran est bloquée par votre administrateur informatique"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifier"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifier la capture d\'écran"</string> <string name="screenshot_share_description" msgid="2861628935812656612">"Partager la capture d\'écran"</string> @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par tes parents. Ils peuvent voir et gérer certaines informations, telles que les applications que tu utilises, ta position et ton temps d\'utilisation de l\'appareil."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Maintenu déverrouillé par TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protection contre le vol\nAppareil verrouillé, trop de tentatives de déverrouillage"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Paramètres audio"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sous-titrer automatiquement"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"activer le vibreur"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Commandes de volume %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Les appels et les notifications sonneront (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Diffusion de <xliff:g id="LABEL">%s</xliff:g> sur"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"L\'audio se mettra en marche"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Barre d\'état"</string> <string name="demo_mode" msgid="263484519766901593">"Mode démo de l\'UI du système"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 2adb759cc555..b78199a149cf 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gardouse"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Volver activar automaticamente mañá"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"As funcións como Quick Share, Localizar o meu dispositivo ou a de localización do dispositivo utilizan o Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"O teu pai ou nai xestiona este dispositivo e pode ver e xestionar información como as aplicacións que usas, a túa localización e o tempo diante da pantalla."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado por un axente de confianza"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protección antirroubo\nDisp. bloq., demasiados intentos desb."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configuración do son"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Crear subtítulos automáticos"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactiva"</string> <string name="sound_settings" msgid="8874581353127418308">"Son e vibración"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Subtítulos instantáneos"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"O volume baixouse ata un nivel máis seguro"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Usaches os auriculares cun volume alto durante máis tempo do recomendado"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos auriculares superou o límite de seguranza desta semana"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controis de volume de %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"As chamadas e as notificacións soarán (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Reproducindo <xliff:g id="LABEL">%s</xliff:g> en"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio reproducido en"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Configurador da IU do sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string> <string name="demo_mode" msgid="263484519766901593">"Modo de demostración da IU do sistema"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index e61a5b52beb9..d84b1f553f8b 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"સાચવેલું"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ડિસ્કનેક્ટ કરો"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"સક્રિય કરો"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"આવતીકાલે ફરીથી ઑટોમૅટિક રીતે ચાલુ કરો"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ક્વિક શેર, Find My Device અને ડિવાઇસના લોકેશન જેવી સુવિધાઓ બ્લૂટૂથનો ઉપયોગ કરે છે"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> બૅટરી"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ઑડિયો"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"હૅડસેટ"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"આ ડિવાઇસ તમારા માતાપિતા દ્વારા મેનેજ કરવામાં આવે છે. તમે જેનો ઉપયોગ કરો છો તે ઍપ, તમારું સ્થાન અને તમારા સ્ક્રીન સમય જેવી માહિતીને તમારા માતાપિતા જોઈ અને મેનેજ કરી શકે છે."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent દ્વારા અનલૉક રાખેલું"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ચોરીથી સુરક્ષા\nડિવાઇસ અનલૉક કર્યું, અનલૉક કરવાના ઘણા પ્રયાસો"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"સાઉન્ડ સેટિંગ"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"મીડિયામાં કૅપ્શન ઑટોમૅટિક રીતે ઉમેરો"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"બંધ કરો"</string> <string name="sound_settings" msgid="8874581353127418308">"સાઉન્ડ અને વાઇબ્રેશન"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"સેટિંગ"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"લાઇવ કૅપ્શન"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"વૉલ્યૂમને વધુ સલામત લેવલ સુધી ઘટાડ્યું"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"હૅડફોનનું વૉલ્યૂમ સુઝાવ આપેલા સમય કરતાં વધારે સમય સુધી ઊંચા વૉલ્યૂમ પર રહ્યું છે"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"હૅડફોનનું વૉલ્યૂમ આ અઠવાડિયા માટેની સુરક્ષિત મર્યાદા કરતાં વધારે છે"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"વાઇબ્રેટ"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s વૉલ્યૂમ નિયંત્રણો"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"કૉલ અને નોટિફિકેશનની રિંગ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>) પર વાગશે"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> વગાડી રહ્યાં છીએ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ઑડિયો આની પર વાગશે"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"સિસ્ટમ UI ટ્યૂનર"</string> <string name="status_bar" msgid="4357390266055077437">"સ્ટેટસ બાર"</string> <string name="demo_mode" msgid="263484519766901593">"સિસ્ટમ UI ડેમો મોડ"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index cf029e0bc64d..8d1ac11b933f 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"कल फिर से अपने-आप चालू हो जाएगा"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"क्विक शेयर, Find My Device, और डिवाइस की जगह की जानकारी जैसी सुविधाएं ब्लूटूथ का इस्तेमाल करती हैं"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बैटरी"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ऑडियो"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं. अभिभावक आपके डिवाइस से जुड़ी जानकारी देख सकते हैं. साथ ही, इसे प्रबंधित कर सकते हैं. इनमें आपके इस्तेमाल किए गए ऐप्लिकेशन, जगह की जानकारी, और डिवाइस के इस्तेमाल में बिताए गए समय जैसी जानकारी शामिल है."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"वीपीएन"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent की वजह से अनलॉक रखा गया है"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"चोरी से सुरक्षा\nडिवाइस लॉक हो गया, अनलॉक की कई कोशिशें की गईं"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"साउंड सेटिंग"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ऑडियो-वीडियो से अपने-आप कैप्शन बनना"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करें"</string> <string name="sound_settings" msgid="8874581353127418308">"आवाज़ और वाइब्रेशन"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"लाइव कैप्शन"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट कर दिया गया है"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय से देर तक ज़्यादा रही"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"इस हफ़्ते के लिए हेडफ़ोन की आवाज़, सुझाई गई सीमा से ज़्यादा हो गई है"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"वाइब्रेशन की सुविधा चालू करें"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s की आवाज़ कम या ज़्यादा करने की सुविधा"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"कॉल और सूचनाएं आने पर घंटी बजेगी (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> को चलाया जा रहा है"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ऑडियो इसमें चलेगा"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर"</string> <string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string> <string name="demo_mode" msgid="263484519766901593">"सिस्टम यूज़र इंटरफ़ेस (यूआई) डेमो मोड"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 3dc70879f4a4..d4e460ddf9ca 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski ponovo uključi sutra"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Značajke kao što su brzo dijeljenje, Pronađi moj uređaj i lokacija uređaja upotrebljavaju Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalice"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja tvoj roditelj. Tvoj roditelj može vidjeti podatke kao što su aplikacije kojima se koristiš, lokaciju i vrijeme upotrebe te upravljati njima."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Otključano održava TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Zaštita od krađe\nUređaj zaključan, previše pokušaja otključavanja"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Postavke zvuka"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatski titlovi za medije"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Kontrole glasnoće – %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Telefon će zvoniti za pozive i obavijesti (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Reproducira se – <xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk će se reproducirati"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Ugađanje korisničkog sučelja sustava"</string> <string name="status_bar" msgid="4357390266055077437">"Traka statusa"</string> <string name="demo_mode" msgid="263484519766901593">"Demo način korisničkog sučelja sustava"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 9b37701f6d84..7c62c7a813e8 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Mentve"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"leválasztás"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiválás"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatikus visszakapcsolás holnap"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Az olyan funkciók, mint a Quick Share, a Készülékkereső és az eszköz helyadatai Bluetootht használnak"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Hang"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Az eszközt a szülőd felügyeli. A szülőd megtekintheti és kezelheti például a használt alkalmazásokra, a tartózkodási helyre és a képernyőidőre vonatkozó adatokat."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Feloldva tartva TrustAgent által"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Lopásgátlás\nTúl sok feloldási kísérlet, eszköz zárolva"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Hangbeállítások"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatikus feliratozás"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"rezgés"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s hangerőszabályzók"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"A hívásoknál és értesítéseknél csörög a telefon (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> lejátszása itt:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Hang lejátszása itt:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Kezelőfelület-hangoló"</string> <string name="status_bar" msgid="4357390266055077437">"Állapotsor"</string> <string name="demo_mode" msgid="263484519766901593">"A rendszer kezelőfelületének demómódja"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index db2b3ce6ca05..8427fc3b683f 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Պահված է"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"անջատել"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ակտիվացնել"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Վաղը նորից ավտոմատ միացնել"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Գործառույթները, ինչպիսիք են Quick Share-ը, «Գտնել իմ սարքը» գործառույթը և սարքի տեղորոշումը, օգտագործում են Bluetooth-ը"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Աուդիո"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ականջակալ"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Այս սարքը կառավարում է ձեր ծնողը։ Նա կարող է դիտել և փոփոխել որոշակի տեղեկություններ, օրինակ՝ հավելվածները, որոնք դուք օգտագործում եք, ձեր տեղադրությունը և սարքի օգտագործման ժամանակը։"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ապակողպվում է TrustAgent-ի միջոցով"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Գողությունից պաշտպանություն\nՍարքը կողպվել է, ապակողպման շատ փորձեր"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ձայնի կարգավորումներ"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Ավտոմատ ավելացնել ենթագրեր"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"անջատել"</string> <string name="sound_settings" msgid="8874581353127418308">"Ձայն և թրթռոց"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Կարգավորումներ"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Կենդանի ենթագրեր"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ձայնն իջեցվեց անվտանգ մակարդակի"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ձայնը բարձր է եղել առաջարկված ժամանակահատվածից ավելի երկար"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Ականջակալների ձայնի ուժգնությունը այս շաբաթ գերազանցել է անվտանգ մակարդակի շեմը"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"միացնել թրթռոցը"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Ձայնի ուժգնության կառավարներ` %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Զանգերի և ծանուցումների համար հեռախոսի ձայնը միացված է (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>. նվագարկվում է"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Աուդիոն կնվագարկվի"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Համակարգի ՕՄ-ի կարգավորիչ"</string> <string name="status_bar" msgid="4357390266055077437">"Կարգավիճակի գոտի"</string> <string name="demo_mode" msgid="263484519766901593">"Համակարգի միջերեսի ցուցադրական ռեժիմ"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 44f9bfc3705b..a2f05b95026f 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan koneksi"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Otomatis aktifkan lagi besok"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Fitur seperti Quick Share, Temukan Perangkat Saya, dan lokasi perangkat menggunakan Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Perangkat ini dikelola oleh orang tuamu. Orang tuamu bisa melihat dan mengelola berbagai informasi, seperti aplikasi yang kamu gunakan, lokasimu, dan lama pemakaian perangkat."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Tetap terbuka kuncinya oleh TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Perlindungan pencurian\nPerangkat dikunci, terlalu banyak upaya pembukaan kunci"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Setelan suara"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Otomatis beri teks di media"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"nonaktifkan"</string> <string name="sound_settings" msgid="8874581353127418308">"Suara & getaran"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setelan"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Teks Otomatis"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diturunkan ke level yang lebih aman"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volume headphone tinggi untuk waktu lebih lama dari yang direkomendasikan"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volume headphone telah melampaui batas aman untuk minggu ini"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"getar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s kontrol volume"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Panggilan telepon dan notifikasi akan berdering (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Memutar <xliff:g id="LABEL">%s</xliff:g> di"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio akan diputar di"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Penyetel Antarmuka Pengguna Sistem"</string> <string name="status_bar" msgid="4357390266055077437">"Bilah status"</string> <string name="demo_mode" msgid="263484519766901593">"Mode demo UI sistem"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 8cfe4e834304..9c9a29f513fc 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Vistað"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"aftengja"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"virkja"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Kveikja sjálfkrafa aftur á morgun"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Eiginleikar á borð við flýtideilingu, „Finna tækið mitt“ og staðsetningu tækis nota Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> rafhlöðuhleðsla"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Hljóð"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Höfuðtól"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Foreldri þitt stjórnar þessu tæki. Foreldri þitt getur séð og stjórnað upplýsingum eins og forritunum sem þú notar, staðsetningu þinni og skjátímanum."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Haldið opnu af TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Þjófavörn\nTækinu var læst vegna of margra tilrauna til að taka það úr lás"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Hljóðstillingar"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sjálfvirkir skjátextar"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"slökkva"</string> <string name="sound_settings" msgid="8874581353127418308">"Hljóð og titringur"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Stillingar"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Skjátextar í rauntíma"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hljóð lækkað í öruggari hljóðstyrk"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Hljóðstyrkur í heyrnartólum hefur verið hár í lengri tíma en mælt er með"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Hljóðstyrkur í heyrnartólum hefur náð öryggismörkum fyrir þessa viku"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"titringur"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s stýringar á hljóstyrk"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Símhringingar og tilkynningar heyrast (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Í spilun í <xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Hljóð heldur áfram að spilast"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Fínstillingar kerfisviðmóts"</string> <string name="status_bar" msgid="4357390266055077437">"Stöðustika"</string> <string name="demo_mode" msgid="263484519766901593">"Prufustilling kerfisviðmóts"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 268925f629ad..ec58af8fe1af 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnetti"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"attiva"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Riattiva automaticamente domani"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funzionalità come Quick Share, Trova il mio dispositivo e la posizione del dispositivo usano il Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auricolare"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Questo dispositivo è gestito da uno dei tuoi genitori, il quale può visualizzare e gestire informazioni come le app che usi, la tua posizione e il tuo tempo di utilizzo."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Sbloccato da TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protezione da furti\nDisp. bloccato, troppi tentat. di sblocco"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Impostazioni audio"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sottotitoli automatici"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrazione"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controlli del volume %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"La suoneria sarà attiva per chiamate e notifiche (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> in riproduzione su"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio riprodotto su:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Ottimizzatore UI di sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Barra di stato"</string> <string name="demo_mode" msgid="263484519766901593">"Modalità demo dell\'interfaccia utente di sistema"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 2b8e153402b9..c9a71c71867b 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"נשמר"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ניתוק"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"הפעלה"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"החיבור יופעל שוב אוטומטית מחר"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"תכונות כמו \'שיתוף מהיר\', \'איפה המכשיר שלי\' ומיקום המכשיר משתמשות בחיבור Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> סוללה"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"אודיו"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"אוזניות"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"מכשיר זה מנוהל על ידי ההורה שלך. להורה שלך יש אפשרות לצפות בפרטים כמו האפליקציות שבשימוש, המיקום וזמן המסך שלך, ולנהל אותם."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"הנעילה נמנעת על ידי סביבה מהימנה"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"הגנה מפני גניבה\nהמכשיר ננעל, יותר מדי ניסיונות לביטול הנעילה"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"הגדרות צליל"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"הוספת כתוביות באופן אוטומטי למדיה"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"השבתה"</string> <string name="sound_settings" msgid="8874581353127418308">"צליל ורטט"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"הגדרות"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"כתוביות מיידיות"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"עוצמת הקול הוחלשה לרמה בטוחה יותר"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"עוצמת הקול של האוזניות הייתה גבוהה במשך יותר זמן מהמומלץ"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"עוצמת הקול של האוזניות חרגה ממגבלת הבטיחות לשבוע הזה"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"רטט"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"בקרי עוצמת קול של %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"הטלפון יצלצל כשמתקבלות שיחות והתראות (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"הפעלה של <xliff:g id="LABEL">%s</xliff:g> במכשיר"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"האודיו יופעל במכשיר"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"שורת סטטוס"</string> <string name="demo_mode" msgid="263484519766901593">"מצב הדגמה בממשק המשתמש של המערכת"</string> @@ -792,7 +792,7 @@ <string name="right_keycode" msgid="2480715509844798438">"קוד מפתח ימני"</string> <string name="left_icon" msgid="5036278531966897006">"סמל שמאלי"</string> <string name="right_icon" msgid="1103955040645237425">"סמל ימני"</string> - <string name="drag_to_add_tiles" msgid="8933270127508303672">"יש ללחוץ ולגרור כדי להוסיף כרטיסי מידע"</string> + <string name="drag_to_add_tiles" msgid="8933270127508303672">"יש ללחוץ ולגרור כדי להוסיף לחצנים"</string> <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"יש ללחוץ ולגרור כדי לסדר מחדש את כרטיסי המידע"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"אפשר לגרור לכאן כדי להסיר"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"יש צורך ב-<xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> אריחים לפחות"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 5b42737d2ab5..dc33b0ddc15d 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"このデバイスは保護者によって管理されています。保護者は、あなたが使用するアプリ、あなたの現在地、デバイスの利用時間などの情報を確認したり、管理したりできます。"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"信頼エージェントがロック解除を管理"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"盗難防止\nデバイスをロック - ロック解除に繰り返し失敗"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"音声の設定"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"メディアの自動字幕起こし"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"バイブレーション"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s の音量調節"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"着信音と通知音が鳴ります(<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> を再生:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"音声の再生形式:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"システムUI調整ツール"</string> <string name="status_bar" msgid="4357390266055077437">"ステータスバー"</string> <string name="demo_mode" msgid="263484519766901593">"システム UI デモモード"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index fef2fe11016f..d78bc2072734 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"შენახული"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"კავშირის გაწყვეტა"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"გააქტიურება"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ხელახლა ავტომატურად ჩართვა ხვალ"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ფუნქციები, როგორებიცაა „სწრაფი გაზიარება“, „ჩემი მოწყობილობის პოვნა“ და „მოწყობილობის მდებარეობა“ იყენებენ Bluetooth-ს"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ბატარეა"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"აუდიო"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ყურსაცვამი"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ამ მოწყობილობას თქვენი მშობელი მართავს. თქვენი მშობელი ხედავს და მართავს ისეთ ინფორმაციას, როგორიც არის თქვენ მიერ გამოყენებული აპები, თქვენი მდებარეობა და თქვენ მიერ ეკრანთან გატარებული დრო."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"განბლოკილია TrustAgent-ის მიერ"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"მოპარვისაგან დაცვა\nდაიბლოკა განბლოკვის ბევრი მცდელობის გამო."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ხმის პარამეტრები"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"მედიის ავტომ. სუბტიტრირება"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ვიბრაცია"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s-ის ხმის მართვის საშუალებები"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ზარებისა და შეტყობინებების მიღებისას დაირეკება (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"უკრავს <xliff:g id="LABEL">%s</xliff:g>:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"აუდიო დაიკვრება"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"სისტემის UI ტუნერი"</string> <string name="status_bar" msgid="4357390266055077437">"სტატუსის ზოლი"</string> <string name="demo_mode" msgid="263484519766901593">"სისტემის UI-ს დემო-რეჟიმი"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index cf5a560870b6..407da0b9b8fa 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сақталды"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажырату"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"іске қосу"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ертең автоматты түрде қосылсын"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Find My Device сияқты функциялар мен құрылғы локациясы Bluetooth пайдаланады."</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батарея деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Aудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бұл құрылғыны ата-анаңыз басқарады. Ата-анаңыз сіз пайдаланатын қолданбалар, геодерегіңіз және пайдалану уақытыңыз сияқты ақпаратты көре және басқара алады."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent арқылы құлпы ашылды."</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Ұрлықтан қорғау\nҚұрылғы құлыпталған, құлыпты ашуға тым көп әрекет жасалды."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Дыбыс параметрлері"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматты субтитр қосу"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өшіру"</string> <string name="sound_settings" msgid="8874581353127418308">"Дыбыс және діріл"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live Caption"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Дыбыс қауіпсіз деңгейге түсірілді"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Құлақаспаптың жоғары дыбыс деңгейі ұсынылған уақыттан ұзақ қосылып тұрды."</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Құлақаспаптың дыбыс деңгейі осы аптадағы қауіпсіз шектен асып кетті."</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"дірілдету"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Дыбысты басқару элементтері: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Қоңыраулар мен хабарландырулар дыбысы қосулы (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ойнатылатын құрылғы:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио ойнатылатын құрылғы:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Жүйелік пайдаланушылық интерфейс тюнері"</string> <string name="status_bar" msgid="4357390266055077437">"Күйін көрсету жолағы"</string> <string name="demo_mode" msgid="263484519766901593">"Жүйе интерфейсінің демо режимі"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 480a0e5d2d8d..eaca65732975 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"បានរក្សាទុក"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ផ្ដាច់"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"បើកដំណើរការ"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"បើកដោយស្វ័យប្រវត្តិម្ដងទៀតនៅថ្ងៃស្អែក"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"មុខងារដូចជា Quick Share, រកឧបករណ៍របស់ខ្ញុំ និងប៊្លូធូសប្រើប្រាស់ទីតាំងឧបករណ៍"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"សំឡេង"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"កាស"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រងរបស់មាតាបិតាអ្នក។ មាតាបិតារបស់អ្នកអាចមើល និងគ្រប់គ្រងព័ត៌មានដូចជា កម្មវិធីដែលអ្នកប្រើ ទីតាំងរបស់អ្នក និងរយៈពេលប្រើប្រាស់ឧបករណ៍របស់អ្នកជាដើម។"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"បានដោះសោដោយភ្នាក់ងារទុកចិត្ត"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ការការពារចោរលួច\nបានចាក់សោឧបករណ៍ ការព្យាយាមដោះសោច្រើនដងពេក"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ការកំណត់សំឡេង"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ដាក់អក្សររត់លើមេឌៀដោយស្វ័យប្រវត្តិ"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ញ័រ"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s របារបញ្ជាកម្រិតសំឡេង"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ការហៅទូរសព្ទ និងការជូនដំណឹងនឹងរោទ៍ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"កំពុងចាក់ <xliff:g id="LABEL">%s</xliff:g> នៅលើ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"សំឡេងនឹងលេងនៅលើ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"កម្មវិធីសម្រួល UI ប្រព័ន្ធ"</string> <string name="status_bar" msgid="4357390266055077437">"របារស្ថានភាព"</string> <string name="demo_mode" msgid="263484519766901593">"មុខងារសាកល្បង UI ប្រព័ន្ធ"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 1f9156afc073..64179ba03a3a 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ನಾಳೆ ಪುನಃ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಮಾಡಿ"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ಕ್ವಿಕ್ ಶೇರ್, Find My Device ನಂತಹ ಫೀಚರ್ಗಳು ಮತ್ತು ಸಾಧನದ ಸ್ಥಳ ಬ್ಲೂಟೂತ್ ಬಳಸುತ್ತವೆ"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ಆಡಿಯೋ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ಹೆಡ್ಸೆಟ್"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ. ನೀವು ಬಳಸುವ ಆ್ಯಪ್ಗಳು, ನಿಮ್ಮ ಸ್ಥಳ ಮತ್ತು ನಿಮ್ಮ ವೀಕ್ಷಣಾ ಅವಧಿಯಂತಹ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನೋಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ನಿಂದ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ಕಳ್ಳತನದ ರಕ್ಷಣೆ\nಸಾಧನ ಲಾಕ್ ಆಗಿದೆ, ಅನ್ಲಾಕ್ಗೆ ಹೆಚ್ಚು ಪ್ರಯತ್ನ..."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ಸೌಂಡ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ಸ್ವಯಂಚಾಲಿತ ಶೀರ್ಷಿಕೆ ಮಾಧ್ಯಮ"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ವೈಬ್ರೇಟ್"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಕಗಳು"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"(<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>) ನಲ್ಲಿ ಕರೆಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಗಳು ರಿಂಗ್ ಆಗುತ್ತವೆ"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗು..."</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ಇಲ್ಲಿ ಆಡಿಯೋ ಪ್ಲೇ..."</string> <string name="system_ui_tuner" msgid="1471348823289954729">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್"</string> <string name="status_bar" msgid="4357390266055077437">"ಸ್ಥಿತಿ ಪಟ್ಟಿ"</string> <string name="demo_mode" msgid="263484519766901593">"ಸಿಸ್ಟಂ UI ಡೆಮೋ ಮೋಡ್"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index c0c8b32237f7..26825e0286e3 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"저장됨"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"연결 해제"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"실행"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"내일 다시 자동으로 사용 설정"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, 내 기기 찾기, 기기 위치 등의 기능에서 블루투스를 사용합니다."</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"오디오"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"헤드셋"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"부모님이 관리하는 기기입니다. 부모님이 내가 사용하는 앱, 내 위치, 기기 사용 시간과 같은 정보를 보고 관리할 수 있습니다."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent가 잠금 해제함"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"도난 방지\n기기 잠김, 잠금 해제 시도 횟수가 너무 많음"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"소리 설정"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"미디어 자막 자동 생성"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"사용 중지"</string> <string name="sound_settings" msgid="8874581353127418308">"소리 및 진동"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"설정"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"실시간 자막"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"볼륨을 안전한 수준으로 낮춤"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"헤드폰 볼륨이 권장 시간보다 오래 높은 상태였습니다."</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"헤드폰 볼륨이 이번 주 안전 한도를 초과했습니다."</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"진동"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s 볼륨 컨트롤"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"전화 및 알림이 오면 벨소리가 울림(<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> 재생 위치:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"오디오 재생 위치:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"시스템 UI 튜너"</string> <string name="status_bar" msgid="4357390266055077437">"상태 표시줄"</string> <string name="demo_mode" msgid="263484519766901593">"시스템 UI 데모 모드"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index b442f2ea255f..79546862454b 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сакталды"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажыратуу"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"иштетүү"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Эртең автоматтык түрдө кайра күйгүзүү"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Тез Бөлүшүү, \"Түзмөгүм кайда?\" жана түзмөктүн турган жерин аныктоо сыяктуу функциялар Bluetooth\'ду колдонот"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бул түзмөктү ата-энең башкарат. Ата-энең сен иштеткен колдонмолорду, кайда жүргөнүңдү жана түзмөктү канча убакыт колдонгонуңду көрүп, башкарып турат."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ишеним агенти кулпусун ачты"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Түзмөктүн уурдалышынан коргоо\nТүзмөк кулпуланды. Кулпуну ачууга өтө көп аракет жасалды"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Добуштун параметрлери"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматтык коштомо жазуулар"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өчүрүү"</string> <string name="sound_settings" msgid="8874581353127418308">"Үн жана дирилдөө"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Ыкчам коштомо жазуулар"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Үндүн катуулугу коопсуз деңгээлге чейин акырындатылды"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Гарнитуранын үнүн катуу чыгарып, сунушталгандан узагыраак угуп жатасыз"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гарнитуранын үнүнүн катуулугу бул аптада коопсуз деңгээлден жогору болду"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"дирилдөө"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s үндү башкаруу элементтери"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Чалуулар менен эскертмелердин үнү чыгарылат (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> аркылуу ойнотулууда"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио төмөнкүдө ойнотулат:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Абал тилкеси"</string> <string name="demo_mode" msgid="263484519766901593">"Системанын интерфейсинин демо режими"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index ee170ce44f8e..4c1bd4eb0d14 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍພໍ່ແມ່ຂອງທ່ານ. ພໍ່ແມ່ຂອງທ່ານສາມາດເບິ່ງ ແລະ ຈັດການຂໍ້ມູນໄດ້ ເຊັ່ນ: ແອັບທີ່ທ່ານໃຊ້, ສະຖານທີ່ ແລະ ເວລາໜ້າຈໍຂອງທ່ານ."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"ປັອດລັອກປະໄວ້ໂດຍ TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ການປ້ອງກັນການຖືກລັກ\nຂອງອຸປະກອນຖືກລັອກ, ພະຍາຍາມປົດລັອກຫຼາຍເທື່ອເກີນໄປ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ການຕັ້ງຄ່າສຽງ"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ສ້າງຄຳບັນຍາຍມີເດຍໂດຍອັດຕະໂນມັດ"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ສັ່ນເຕືອນ"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"ການຄວບຄຸມສຽງ %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ການໂທ ແລະ ການແຈ້ງເຕືອນຈະມີສຽງດັງ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"ກຳລັງຫຼິ້ນ <xliff:g id="LABEL">%s</xliff:g> ໃນ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ສຽງຈະຫຼິ້ນຕໍ່ໄປ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"ແຖບສະຖານະ"</string> <string name="demo_mode" msgid="263484519766901593">"ໂໝດເດໂມສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ລະບົບ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 5b71259382a0..9a261e05f709 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Šį įrenginį tvarko vienas iš tavo tėvų. Jis gali peržiūrėti ir tvarkyti informaciją, pvz., tavo naudojamas programas, vietovę ir įrenginio naudojimo laiką."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Atrakinta taikant „TrustAgent“"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Apsauga nuo vagystės\nĮrenginys užrakintas, per daug bandymų atrakinti"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Garso nustatymai"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Taikyti aut. medij. subtitr."</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibruoti"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Garsumo valdikliai: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Skambučiai ir pranešimai skambės (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Leidžiama „<xliff:g id="LABEL">%s</xliff:g>“"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Garsas bus leidžiamas"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sistemos naudotojo sąsajos derinimo priemonė"</string> <string name="status_bar" msgid="4357390266055077437">"Būsenos juosta"</string> <string name="demo_mode" msgid="263484519766901593">"Sistemos NS demonstracinis režimas"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index b4dae4c71a95..a9a1a3c366a4 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saglabāta"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atvienot"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizēt"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automātiski atkal ieslēgt rīt"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Tādas funkcijas kā “Ātrā kopīgošana”, “Atrast ierīci” un ierīces atrašanās vietas noteikšana izmanto tehnoloģiju Bluetooth."</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akumulators: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Austiņas"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Šo ierīci pārvalda viens no jūsu vecākiem. Vecāki var skatīt un pārvaldīt tādu informāciju kā jūsu izmantotās lietotnes, atrašanās vieta un izmantošanas ilgums."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Bloķēšanu liedzis TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Aizsardzība pret zādzību\nIerīce bloķēta; pārāk daudz atbloķēšanas mēģinājumu"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Skaņas iestatījumi"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Autom. paraksti multividei"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"atspējot"</string> <string name="sound_settings" msgid="8874581353127418308">"Skaņa un vibrācija"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Iestatījumi"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Subtitri reāllaikā"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Skaļums samazināts līdz drošākam līmenim"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Austiņu skaļums ir bijis liels ilgāk, nekā ieteicams."</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Austiņu skaļums ir pārsniedzis šīs nedēļas drošo ierobežojumu."</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrēt"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s skaļuma vadīklas"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Zvani un paziņojumi aktivizēs zvana signālu (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> — atskaņošana šeit:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio tiks atskaņots šeit:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sistēmas saskarnes regulators"</string> <string name="status_bar" msgid="4357390266055077437">"Statusa josla"</string> <string name="demo_mode" msgid="263484519766901593">"Sistēmas lietotāja saskarnes demonstrācijas režīms"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 38ed5a70ad3c..20a93f7df6cf 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Зачувано"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекини врска"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирај"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматски вклучи повторно утре"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Функциите како „Брзо споделување“, „Најди го мојот уред“ и локација на уредот користат Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батерија"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалки"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Родителот управува со уредов. Родителот може да прегледува и управува со податоците, како што се апликациите што ги користиш, твојата локација и времето поминато на уредот."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"ВПН"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Се одржува отклучен од TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Заштита од кражби\nЗаклучено. Премногу обиди за отклучување."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Поставки за звукот"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматски титлови"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"оневозможи"</string> <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрации"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Поставки"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Автоматски титлови"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Јачината на звукот е намалена на побезбедно ниво"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Јачината на звукот на слушалките беше висока подолго од препорачаното"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Јачината на звукот на слушалките го надмина безбедното ограничување за седмицава"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибрации"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Контроли на јачината на звукот за %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Повиците и известувањата ќе ѕвонат (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>: пуштено на"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиото ќе се пушти на"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Адаптер на УИ на системот"</string> <string name="status_bar" msgid="4357390266055077437">"Статусна лента"</string> <string name="demo_mode" msgid="263484519766901593">"Демо-режим на кориснички интерфејс на систем"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index a20417da5660..fc2bc47b64dc 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്. നിങ്ങൾ ഉപയോഗിക്കുന്ന ആപ്പുകൾ, സ്ക്രീൻ സമയം, ലൊക്കേഷൻ എന്നിവ പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ രക്ഷിതാവിന് കാണാനും നിയന്ത്രിക്കാനുമാകും."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തത്"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"മോഷണ പരിരക്ഷ\nഉപകരണം ലോക്ക് ചെയ്തു, നിരവധി അൺലോക്ക് ശ്രമങ്ങൾ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ശബ്ദ ക്രമീകരണം"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"മീഡിയയ്ക്ക് സ്വയമേവ ക്യാപ്ഷൻ"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"വൈബ്രേറ്റ് ചെയ്യുക"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ശബ്ദ നിയന്ത്രണങ്ങൾ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"കോളുകളും അറിയിപ്പുകളും ലഭിക്കുമ്പോൾ റിംഗ് ചെയ്യും (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യുന്നു"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ഓഡിയോ പ്ലേ ചെയ്യും"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"സിസ്റ്റം UI ട്യൂണർ"</string> <string name="status_bar" msgid="4357390266055077437">"സ്റ്റാറ്റസ് ബാർ"</string> <string name="demo_mode" msgid="263484519766901593">"സിസ്റ്റം UI ഡെമോ മോഡ്"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 378f330f5435..f5bf05a4d671 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Хадгалсан"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"салгах"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"идэвхжүүлэх"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Маргааш автоматаар дахин асаах"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Түргэн хуваалцах, Миний төхөөрөмжийг олох зэрэг онцлогууд болон төхөөрөмжийн байршил Bluetooth-г ашигладаг"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батарей"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Чихэвч"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Энэ төхөөрөмжийг таны эцэг эх удирддаг. Таны эцэг эх таны хэрэглэдэг апп, байршил, дэлгэцийн цаг зэрэг мэдээллийг харж, удирдах боломжтой."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent-р түгжээгүй байлгасан"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Хулгайн хамгаалалт\nТөхөөрөмж түгжигдсэн, түгжээг тайлах хэт олон оролдлого"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Дууны тохиргоо"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Медиад автоматаар тайлбар нэмэх"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"идэвхгүй болгох"</string> <string name="sound_settings" msgid="8874581353127418308">"Дуу, чичиргээ"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Тохиргоо"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Шууд тайлбар"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Дууны түвшнийг илүү аюулгүй түвшин рүү багасгасан"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Чихэвчийн дууны түвшин санал болгосноос удаан хугацааны туршид өндөр байсан"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Чихэвчийн дууны түвшин энэ долоо хоногийн аюулгүй хязгаараас хэтэрсэн"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"чичрэх"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s түвшний хяналт"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Дуудлага болон мэдэгдлийн хонх дуугарна (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> дээр тоглуулж байна"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиог дараахад тоглуулна"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Системийн UI Тохируулагч"</string> <string name="status_bar" msgid="4357390266055077437">"Статус самбар"</string> <string name="demo_mode" msgid="263484519766901593">"Системийн UI демо горим"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 940a7e6692e9..f9d4aca9efcd 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -148,7 +148,7 @@ <string name="accessibility_scanning_face" msgid="3093828357921541387">"चेहरा स्कॅन करत आहे"</string> <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"पाठवा"</string> <string name="cancel" msgid="1089011503403416730">"रद्द करा"</string> - <string name="biometric_dialog_confirm" msgid="2005978443007344895">"कंफर्म करा"</string> + <string name="biometric_dialog_confirm" msgid="2005978443007344895">"कन्फर्म करा"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"पुन्हा प्रयत्न करा"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ऑथेंटिकेशन रद्द करण्यासाठी टॅप करा"</string> <string name="biometric_dialog_face_icon_description_idle" msgid="4351777022315116816">"कृपया पुन्हा प्रयत्न करा"</string> @@ -205,7 +205,7 @@ <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"फेस अनलॉक उपलब्ध नाही"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट केले."</string> <string name="accessibility_bluetooth_device_icon" msgid="9163840051642587982">"ब्लूटूथ डिव्हाइस आयकन"</string> - <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"डिव्हाइसचे तपशील कॉंफिगर करण्यासाठी क्लिक करा"</string> + <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"डिव्हाइसचे तपशील कॉन्फिगर करण्यासाठी क्लिक करा"</string> <string name="accessibility_bluetooth_device_settings_see_all" msgid="9111952496905423543">"सर्व डिव्हाइस पाहण्यासाठी क्लिक करा"</string> <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"नवीन डिव्हाइस पेअर करण्यासाठी क्लिक करा"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string> @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव्ह केले"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट करा"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ॲक्टिव्हेट करा"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"उद्या पुन्हा आपोआप सुरू करा"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Find My Device आणि डिव्हाइस स्थान यांसारखी वैशिष्ट्ये ब्लूटूथ वापरतात"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बॅटरी"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ऑडिओ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे. तुम्ही वापरत असलेली ॲप्स, तुमचे स्थान आणि तुमचा स्क्रीन वेळ यांसारखी माहिती तुमचे पालक पाहू आणि व्यवस्थापित करू शकतात."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ने अनलॉक ठेवले"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"चोरीपासून संरक्षण\nडिव्हाइस लॉक केले, अनलॉक करायचे खूप प्रयत्न"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"आवाज सेटिंग्ज"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"मीडियाला आपोआप सबटायटल द्या"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"व्हायब्रेट करा"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s व्हॉल्यूम नियंत्रण"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"कॉल आणि सूचना वाजतील (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> वर प्ले करत आहे"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"यावर ऑडिओ प्ले होईल"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string> <string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string> <string name="demo_mode" msgid="263484519766901593">"सिस्टम UI डेमो मोड"</string> @@ -647,7 +648,7 @@ <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे संभाषण वैशिष्ट्यांना सपोर्ट करत नाही"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"या सूचनांमध्ये सुधारणा केली जाऊ शकत नाही."</string> <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉलशी संबंधित सूचनांमध्ये फेरबदल केला जाऊ शकत नाही."</string> - <string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉंफिगर केला जाऊ शकत नाही"</string> + <string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉन्फिगर केला जाऊ शकत नाही"</string> <string name="notification_delegate_header" msgid="1264510071031479920">"प्रॉक्सी केलेल्या सूचना"</string> <string name="notification_channel_dialog_title" msgid="6856514143093200019">"सर्व <xliff:g id="APP_NAME">%1$s</xliff:g> वरील सूचना"</string> <string name="see_more_title" msgid="7409317011708185729">"आणखी पहा"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index fdffdb7265fd..dafcfe009769 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Peranti ini diurus oleh ibu bapa anda. Ibu bapa anda dapat melihat dan mengurus maklumat seperti apl yang anda gunakan, lokasi dan masa skrin anda."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Dibiarkan tidak berkunci oleh TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Perlindungan kecurian\nDikunci, banyak percubaan membuka kunci"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Tetapan bunyi"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sari kata media automatik"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"getar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s kawalan kelantangan"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Panggilan dan pemberitahuan akan berdering (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Memainkan <xliff:g id="LABEL">%s</xliff:g> pada"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio dimainkan pada"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Penala UI Sistem"</string> <string name="status_bar" msgid="4357390266055077437">"Bar status"</string> <string name="demo_mode" msgid="263484519766901593">"Mod tunjuk cara UI sistem"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 99e2a3fcd53c..e52b899870d2 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"မနက်ဖြန် အလိုအလျောက် ထပ်ဖွင့်ရန်"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"‘အမြန် မျှဝေပါ’၊ Find My Device နှင့် စက်ပစ္စည်းတည်နေရာကဲ့သို့ တူးလ်များသည် ဘလူးတုသ်သုံးသည်"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ဘက်ထရီ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"အသံ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"မိုက်ခွက်ပါနားကြပ်"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်။ သင့်မိဘက သင်သုံးသောအက်ပ်များ၊ သင်၏တည်နေရာနှင့် အသုံးပြုချိန် ကဲ့သို့သော အချက်အလက်များကို မြင်နိုင်ပြီး စီမံခန့်ခွဲနိုင်သည်။"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ဖြင့် ဆက်ဖွင့်ထားရန်"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"သူခိုးကာကွယ်ရေး\nစက်လော့ခ်ကျ၊ အကြိမ်များစွာဖွင့်ရန်ကြိုးစားထား"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>။ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"အသံဆက်တင်များ"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"အလိုအလျောက် စာတန်းထိုးရန်"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ပိတ်ရန်"</string> <string name="sound_settings" msgid="8874581353127418308">"အသံနှင့် တုန်ခါမှု"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ဆက်တင်များ"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"တိုက်ရိုက်စာတန်း"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"အသံကို ဘေးကင်းသည့်အဆင့်သို့ လျှော့ချလိုက်သည်"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"နားကြပ်အသံသည် အကြံပြုထားသည်ထက် အချိန်ကြာရှည်စွာ ကျယ်လောင်နေသည်"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"နားကြပ်အသံသည် ဤအပတ်အတွက် ဘေးကင်းသည့်ကန့်သတ်ချက်ထက် ကျော်သွားပါပြီ"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"တုန်ခါမှု"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s အသံအတိုးအလျှော့ ခလုတ်များ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ခေါ်ဆိုမှုများနှင့် အကြောင်းကြားချက်များအတွက် အသံမြည်နှုန်း (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>) ဖြစ်သည်"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ကို ဖွင့်နေသည်"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"အောက်တွင်အသံဖွင့်မည်"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"စနစ် UI ဖမ်းစက်"</string> <string name="status_bar" msgid="4357390266055077437">"အခြေအနေပြနေရာ"</string> <string name="demo_mode" msgid="263484519766901593">"စနစ် UI စရုပ်ပြမုဒ်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 67f44e9c72c2..ed6e2931ed5f 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Lagret"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koble fra"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiver"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Slå på igjen i morgen automatisk"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funksjoner som Quick Share, Finn enheten min og enhetsposisjon bruker Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Hodetelefoner"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enheten administreres av forelderen din. Forelderen din kan se og administrere informasjon, for eksempel appene du bruker, posisjonen din og skjermtiden din."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Holdes opplåst med TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Tyveribeskyttelse\nEnheten er låst – mange opplåsingsforsøk"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Lydinnstillinger"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatisk medieteksting"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string> <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibrering"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Innstillinger"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Direkteteksting"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumet er senket til et tryggere nivå"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumet på hodetelefonene har vært høyt lenger enn anbefalt"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumet på hodetelefonene har overskredet sikkerhetsgrensen for denne uken"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrer"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s volumkontroller"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Anrop og varsler ringer (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Spiller av <xliff:g id="LABEL">%s</xliff:g> på"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Lyden spilles av på"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Statusrad"</string> <string name="demo_mode" msgid="263484519766901593">"Demomodus for systemgrensesnitt"</string> @@ -792,7 +792,7 @@ <string name="right_keycode" msgid="2480715509844798438">"Høyre-tastkode"</string> <string name="left_icon" msgid="5036278531966897006">"Venstre-ikon"</string> <string name="right_icon" msgid="1103955040645237425">"Høyre-ikon"</string> - <string name="drag_to_add_tiles" msgid="8933270127508303672">"Hold og dra for å legge til ruter"</string> + <string name="drag_to_add_tiles" msgid="8933270127508303672">"Hold og dra for å legge til brikker"</string> <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Hold og dra for å flytte på rutene"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Dra hit for å fjerne"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"Du trenger minst <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> infobrikker"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index f9fc6a65edb4..fb7680daf152 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"भोलि फेरि स्वतः अन गरियोस्"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"क्विक सेयर, Find My Device र डिभाइसको लोकेसन जस्ता सुविधाहरूले ब्लुटुथ प्रयोग गर्छन्"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ब्याट्री"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"अडियो"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ। तपाईंका अभिभावक तपाईंले प्रयोग गर्ने एप, तपाईंको स्थान र तपाईंले यन्त्र चलाएर बिताउने समय जस्ता जानकारी हेर्न तथा व्यवस्थापन गर्न सक्नुहुन्छ।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ले खुला राखेको"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"चोरीबाट सुरक्षा\nडिभाइस लक गरिएको छ, अत्यधिक धेरै पटक अनलक गर्ने प्रयास गरिएको छ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ध्वनिसम्बन्धी सेटिङहरू"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"मिडियाको स्वत: क्याप्सन बनाउनुहोस्"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"कम्पन गर्नुहोस्"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s भोल्युमका नियन्त्रणहरू"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"कल तथा सूचनाहरू आउँदा घन्टी बज्ने छ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> प्ले गरिँदै छ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"अडियो प्ले भइरहने छ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string> <string name="status_bar" msgid="4357390266055077437">"स्थिति पट्टी"</string> <string name="demo_mode" msgid="263484519766901593">"सिस्टम UI को डेमो मोड"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 668dd0eea310..a649617a5559 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dit apparaat wordt beheerd door je ouder. Je ouder kan informatie bekijken en beheren, zoals de apps die je gebruikt, je locatie en je schermtijd."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ontgrendeld gehouden door TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Diefstalbeveiliging\nApparaat vergrendeld, te veel ontgrendelpogingen"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Geluidsinstellingen"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatisch ondertitelen"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"trillen"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s-volumeknoppen"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Geluid bij gesprekken en meldingen (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> wordt afgespeeld op"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio wordt afgespeeld op"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Systeem-UI-tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Statusbalk"</string> <string name="demo_mode" msgid="263484519766901593">"Demomodus voor systeemgebruikersinterface"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index ee9a5fd3c721..b0f5022c9c17 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ସେଭ କରାଯାଇଛି"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ଚାଲୁ କରନ୍ତୁ"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ଆସନ୍ତାକାଲି ସ୍ୱତଃ ପୁଣି ଚାଲୁ ହେବ"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Find My Device ଏବଂ ଡିଭାଇସ ଲୋକେସନ ପରି ଫିଚରଗୁଡ଼ିକ ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରେ"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ବ୍ୟାଟେରୀ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ଅଡିଓ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ହେଡସେଟ୍"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ। ଆପଣଙ୍କ ବାପାମା ଆପଣ ବ୍ୟବହାର କରୁଥିବା ଆପ୍ସ, ଆପଣଙ୍କ ଲୋକେସନ୍ ଓ ସ୍କ୍ରିନ୍ ସମୟ ପରି ସୂଚନା ଦେଖିପାରିବେ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ଦ୍ୱାରା ଅନ୍ଲକ୍ ରହିଛି"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ଥେଫ୍ଟ ସୁରକ୍ଷା\nଡିଭାଇସ ଲକ କରାଯାଇଛି, ଅନେକଗୁଡ଼ିଏ ଅନଲକ ପ୍ରଚେଷ୍ଟା"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ସାଉଣ୍ଡ ସେଟିଂସ୍"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ସ୍ବଚାଳିତ କ୍ୟାପ୍ସନ୍ ମିଡିଆ"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ଅକ୍ଷମ କରନ୍ତୁ"</string> <string name="sound_settings" msgid="8874581353127418308">"ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେସନ"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ସେଟିଂସ"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"ଲାଇଭ କେପ୍ସନ"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ଭଲ୍ୟୁମକୁ ସୁରକ୍ଷିତ ଲେଭେଲକୁ କମ କରାଯାଇଛି"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ସୁପାରିଶ ଭଲ୍ୟୁମ ଠାରୁ ହେଡଫୋନର ଭଲ୍ୟୁମ ଅଧିକ ଅଛି"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ଏହି ସପ୍ତାହ ପାଇଁ ହେଡଫୋନର ଭଲ୍ୟୁମ ସୁରକ୍ଷିତ ସୀମାକୁ ଅତିକ୍ରମ କରିଛି"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ଭାଇବ୍ରେଟ୍"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ଭଲ୍ୟୁମ୍ ନିୟନ୍ତ୍ରଣ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"କଲ୍ ଓ ବିଜ୍ଞପ୍ତି ପାଇଁ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)ରେ ରିଙ୍ଗ ହେବ"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>ରେ ପ୍ଲେ କରାଯାଉଛି"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ଅଡିଓ ପ୍ଲେ ହେବ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍"</string> <string name="status_bar" msgid="4357390266055077437">"ଷ୍ଟାଟସ୍ ବାର୍"</string> <string name="demo_mode" msgid="263484519766901593">"ସିଷ୍ଟମ୍ UI ଡେମୋ ମୋଡ୍"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index f81b3b49cc81..6916fd2b3be9 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ਕੱਲ੍ਹ ਨੂੰ ਆਪਣੇ ਆਪ ਚਾਲੂ ਹੋ ਜਾਵੇਗਾ"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ਕਵਿੱਕ ਸ਼ੇਅਰ, Find My Device ਅਤੇ ਡੀਵਾਈਸ ਦਾ ਟਿਕਾਣਾ ਵਰਗੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਬਲੂਟੁੱਥ ਦੀ ਵਰਤੋਂ ਕਰਦੀਆਂ ਹਨ"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ਆਡੀਓ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ਹੈੱਡਸੈੱਟ"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਤੁਹਾਡੀਆਂ ਐਪਾਂ ਦੀ ਵਰਤੋਂ, ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਅਤੇ ਤੁਹਾਡੇ ਸਕ੍ਰੀਨ ਸਮੇਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਦੇਖ ਅਤੇ ਉਸਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੇ ਹਨ।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"ਟਰੱਸਟ-ਏਜੰਟ ਵੱਲੋਂ ਅਣਲਾਕ ਰੱਖਿਆ ਗਿਆ"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"ਚੋਰੀ ਤੋਂ ਸੁਰੱਖਿਆ\nਡੀਵਾਈਸ ਲਾਕ ਹੋ ਗਿਆ, ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕਈ ਕੋਸ਼ਿਸ਼ਾਂ ਕੀਤੀਆਂ ਗਈਆਂ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ਧੁਨੀ ਸੈਟਿੰਗਾਂ"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ਸਵੈਚਲਿਤ ਸੁਰਖੀ ਮੀਡੀਆ"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ਬੰਦ ਕਰੋ"</string> <string name="sound_settings" msgid="8874581353127418308">"ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ਸੈਟਿੰਗਾਂ"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"ਲਾਈਵ ਸੁਰਖੀਆਂ"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ਅਵਾਜ਼ ਨੂੰ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਪੱਧਰ ਤੱਕ ਘੱਟ ਕੀਤਾ ਗਿਆ"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਸਿਫ਼ਾਰਸ਼ੀ ਪੱਧਰ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਉੱਚੀ ਰਹੀ"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਇਸ ਹਫ਼ਤੇ ਦੀ ਸੁਰੱਖਿਅਤ ਸੀਮਾ ਨੂੰ ਪਾਰ ਕਰ ਗਈ"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"ਥਰਥਰਾਹਟ"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ਵੌਲਿਊਮ ਕੰਟਰੋਲ"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ਕਾਲਾਂ ਆਉਣ ਅਤੇ ਸੂਚਨਾਵਾਂ ਮਿਲਣ \'ਤੇ ਘੰਟੀ ਵਜੇਗੀ (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ਆਡੀਓ ਇਸ \'ਤੇ ਚੱਲੇਗੀ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI ਟਿਊਨਰ"</string> <string name="status_bar" msgid="4357390266055077437">"ਸਥਿਤੀ ਪੱਟੀ"</string> <string name="demo_mode" msgid="263484519766901593">"ਸਿਸਟਮ UI ਡੈਮੋ ਮੋਡ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index a22d77c17b2f..c04d6dae6e0d 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Zapisane"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatycznie włącz ponownie jutro"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funkcje takie jak Szybkie udostępnianie, Znajdź moje urządzenie i dotyczące lokalizacji urządzenia używają Bluetootha"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> naładowania baterii"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Dźwięk"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Zestaw słuchawkowy"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tym urządzeniem zarządza Twój rodzic. Rodzic może zobaczyć różne informacje, np. o aplikacjach, których używasz, lokalizacji i czasie korzystania z urządzenia, a także zarządzać tymi danymi."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Blokada anulowana przez agenta zaufania"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Ochrona przed kradzieżą\nZablokowano – za dużo prób logowania."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ustawienia dźwięku"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Autom. napisy do multimediów"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"wyłącz"</string> <string name="sound_settings" msgid="8874581353127418308">"Dźwięk i wibracje"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ustawienia"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Napisy na żywo"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Głośność obniżona do bezpieczniejszego poziomu"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Głośność na słuchawkach jest zbyt duża przez czas dłuższy niż zalecany"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Głośność na słuchawkach przekroczyła limit bezpieczeństwa na ten tydzień"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"włącz wibracje"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Sterowanie głośnością: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Połączenia i powiadomienia będą uruchamiały dzwonek (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Odtwarzam <xliff:g id="LABEL">%s</xliff:g> na"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Wyjścia dźwięku:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Kalibrator System UI"</string> <string name="status_bar" msgid="4357390266055077437">"Pasek stanu"</string> <string name="demo_mode" msgid="263484519766901593">"Tryb demonstracyjny interfejsu"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index c4e2d3fd063e..e82a1032dbc6 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ativar automaticamente de novo amanhã"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Recursos como o Quick Share, o Encontre Meu Dispositivo e a localização do dispositivo usam o Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Fone de ouvido"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Proteção contra roubo\nDispositivo bloqueado por tentativas de desbloqueio em excesso"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string> <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Legenda instantânea"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diminuído para um nível mais seguro"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"O volume dos fones de ouvido está alto há mais tempo que o recomendado"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos fones de ouvido excedeu o limite de segurança para esta semana"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controles de volume %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chamadas e notificações farão o smartphone tocar (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Tocando <xliff:g id="LABEL">%s</xliff:g> em"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"O áudio vai tocar em"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de status"</string> <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 267c8cd64bb8..8ba907b4ee41 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desassociar"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Reativar amanhã automaticamente"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"As funcionalidades como Partilha rápida, Localizar o meu dispositivo e localização do dispositivo usam o Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de bateria"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ausc. c/ mic. integ."</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerido pelos teus pais, que podem ver e gerir informações como as apps que utilizas, a tua localização e o tempo de utilização."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Mantido desbloqueado pelo TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Proteção contra roubo\nDisp. bloq., muitas tentativas de desb."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Definições de som"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Multim. legendas automáticas"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controlos de volume de %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"As chamadas e as notificações tocam (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"A ouvir <xliff:g id="LABEL">%s</xliff:g> em"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"O áudio será ouv. em"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador da interface do sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string> <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da IU do sistema"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index c4e2d3fd063e..e82a1032dbc6 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ativar automaticamente de novo amanhã"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Recursos como o Quick Share, o Encontre Meu Dispositivo e a localização do dispositivo usam o Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Fone de ouvido"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Proteção contra roubo\nDispositivo bloqueado por tentativas de desbloqueio em excesso"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string> <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Legenda instantânea"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diminuído para um nível mais seguro"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"O volume dos fones de ouvido está alto há mais tempo que o recomendado"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos fones de ouvido excedeu o limite de segurança para esta semana"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrar"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Controles de volume %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chamadas e notificações farão o smartphone tocar (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Tocando <xliff:g id="LABEL">%s</xliff:g> em"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"O áudio vai tocar em"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string> <string name="status_bar" msgid="4357390266055077437">"Barra de status"</string> <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 91a5f82fdab9..8cd2d77f9efb 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvat"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deconectează"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activează"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Activează din nou automat mâine"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funcții precum Quick Share, Găsește-mi dispozitivul și locația dispozitivului folosesc Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Căști"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dispozitivul este gestionat de unul dintre părinți. Părintele poate să vadă și să gestioneze informații cum ar fi aplicațiile pe care le folosești, locația ta și durata de folosire a dispozitivului."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Deblocat de TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Protecție anti-furt\nDispozitiv blocat, prea multe încercări de deblocare"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Setări de sunet"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Adaugă subtitrări automate la fișierele media"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"dezactivează"</string> <string name="sound_settings" msgid="8874581353127418308">"Sunete și vibrații"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setări"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Subtitrări live"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumul a fost redus la un nivel mai sigur"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumul căștilor a fost ridicat mai mult timp decât este recomandat"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumul căștilor a depășit limita de siguranță pentru săptămâna aceasta"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibrații"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Comenzi de volum pentru %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Apelurile și notificările vor suna (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Se redă <xliff:g id="LABEL">%s</xliff:g> pe"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Conținutul audio se va reda pe"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Bară de stare"</string> <string name="demo_mode" msgid="263484519766901593">"Mod demonstrativ pentru IU sistem"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index bc8e2f7fd097..614eb0617fb4 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сохранено"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"отключить"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активировать"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Включить завтра автоматически"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Bluetooth используется в сервисе \"Найти устройство\", таких функциях, как Быстрая отправка, и при определении местоположения устройства"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудиоустройство"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Этим устройством управляет один из твоих родителей. Он может видеть, например, какими приложениями ты пользуешься и где находишься, а также задавать определенные настройки (например, ограничивать время использования устройства)."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"Сеть VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Разблокировано агентом доверия"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Защита от кражи\nУстр-во заблокировано. Слишком много попыток."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>."</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Настройки звука"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматически добавлять субтитры"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"отключить"</string> <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрация"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Открыть настройки"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Автоматические субтитры"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Громкость уменьшена до безопасного уровня"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Вы используете наушники при высоком уровне громкости дольше, чем рекомендуется."</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Превышен безопасный лимит громкости наушников на этой неделе."</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"включить вибрацию"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s: регулировка громкости"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Для звонков и уведомлений включен звук (уровень громкости: <xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – запущено здесь:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Проигрывание аудио:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Строка состояния"</string> <string name="demo_mode" msgid="263484519766901593">"Интерфейс системы: деморежим"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 1e2c69546ee2..d1bcee422bd4 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"සුරැකිණි"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"විසන්ධි කරන්න"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"සක්රිය කරන්න"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"හෙට ස්වයංක්රීයව නැවත ක්රියාත්මක කරන්න"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"ඉක්මන් බෙදා ගැනීම, මගේ උපාංගය සෙවීම, සහ උපාංග ස්ථානය වැනි විශේෂාංග බ්ලූටූත් භාවිත කරයි"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ශ්රව්ය"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"හෙඩ්සෙටය"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"මෙම උපාංගය ඔබගේ මාපියන් විසින් කළමනාකරණය කෙරේ. ඔබ භාවිත කරන යෙදුම්, ඔබගේ ස්ථානය සහ ඔබගේ තිර කාලය වැනි තොරතුරු ඔබගේ මාපියන්ට බැලීමට සහ කළමනාකරණය කිරීමට හැකිය."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent මඟින් අඟුලු දමා තබා ගන්න"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"සොරකම් ආරක්ෂණය\nඋපාංගය අගුළු දමා ඇත, අගුළු හැරීමේ උත්සාහයන් වැඩියි"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ශබ්ද සැකසීම්"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"මාධ්ය ස්වයංක්රීයව සිරස්තල"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"අබල කරන්න"</string> <string name="sound_settings" msgid="8874581353127418308">"ශබ්ද සහ කම්පනය"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"සැකසීම්"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"සජීවී සිරස්තල"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"හඬ පරිමාව සුරක්ෂිත මට්ටමට අඩු කරන ලදි"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"නිර්දේශිත ප්රමාණයට වඩා වැඩි කාලයක් හෙඩ්ෆෝන් හඬ පරිමාව ඉහළ මට්ටමක පවතී"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"හෙඩ්ෆෝන් හඬ පරිමාව මෙම සතිය සඳහා සුරක්ෂිත සීමාව ඉක්මවා ඇත"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"කම්පනය"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"හඬ පරිමා පාලන %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"ඇමතුම් සහ දැනුම්දීම් (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>) නාද කරනු ඇත"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> වාදනය කරන්නේ"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ශ්රව්ය වාදනය වනු ඇත්තේ"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"පද්ධති UI සුසරකය"</string> <string name="status_bar" msgid="4357390266055077437">"තත්ත්ව තීරුව"</string> <string name="demo_mode" msgid="263484519766901593">"පද්ධති UI ආදර්ශන ප්රකාරය"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 1a3cac13bc5d..3e2b554f18b2 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uložené"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojiť"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovať"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automaticky zajtra znova zapnúť"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funkcie, ako sú Quick Share, Nájdi moje zariadenie a poloha zariadenia, používajú Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvuk"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Náhlavná súprava"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Toto zariadenie spravuje tvoj rodič. Vidí a môže spravovať informácie, napríklad aplikácie, ktoré používaš, tvoju polohu a čas používania."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Odomknutie udržiava TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Ochrana pred krádež.\nZar. uzamknuté, priveľa pokusov o odomk."</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Nastavenia zvuku"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatické titulkovanie médií"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"zakázať"</string> <string name="sound_settings" msgid="8874581353127418308">"Zvuk a vibrácie"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavenia"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Živý prepis"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hlasitosť bola znížená na bezpečnejšiu úroveň"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Hlasitosť slúchadiel bola vysoká dlhšie, ako sa odporúča"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Hlasitosť slúchadiel prekročila bezpečný limit pre tento týždeň"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"zapnite vibrovanie"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Ovládacie prvky hlasitosti %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Hovory a upozornenia spustia zvonenie (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> sa prehráva v zar."</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk prehrá zariad.:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Tuner používateľského rozhrania systému"</string> <string name="status_bar" msgid="4357390266055077437">"Stavový riadok"</string> <string name="demo_mode" msgid="263484519766901593">"Ukážka používateľského rozhrania systému"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 0611b601725c..1ea97a1f4b43 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Shranjeno"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinitev povezave"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Samodejno znova vklopi jutri"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funkcije, kot sta Hitro deljenje in Poišči mojo napravo, ter lokacija naprave, uporabljajo Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvok"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalke z mikrofonom"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"To napravo upravlja tvoj starš. Lahko si ogleda in upravlja podatke, na primer katere aplikacije uporabljaš, tvojo lokacijo in koliko časa uporabljaš napravo."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ohranja odklenjeno"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Zaščita pred krajo\nNaprava je zaklenjena, preveč poskusov odklepanja"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Nastavitve zvoka"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sam. podnapisi predstavnosti"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibriranje"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Kontrolniki glasnosti za %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Klici in obvestila bodo pozvonili (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Predvajanje »<xliff:g id="LABEL">%s</xliff:g>« v"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvok bo predvajan v"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Uglaševalnik uporabniškega vmesnika sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Vrstica stanja"</string> <string name="demo_mode" msgid="263484519766901593">"Predstavitveni način uporabniškega vmesnika sistema"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 447f162a653c..c3ccd81e6f62 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivizoje automatikisht nesër"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Veçoritë si \"Ndarja e shpejtë\", \"Gjej pajisjen time\" dhe vendndodhja e pajisjes përdorin Bluetooth-in"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> bateri"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Kufje me mikrofon"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Kjo pajisje menaxhohet nga prindi yt. Prindi yt mund të shikojë dhe menaxhojë informacionet, si p.sh. aplikacionet që përdor, vendndodhjen tënde dhe kohën para ekranit."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Mbajtur shkyçur nga TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Mbrojtje nga vjedhja\nPajisja u kyç. Shumë përpjekje shkyçjeje"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Cilësimet e zërit"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Media me titra automatike"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"çaktivizo"</string> <string name="sound_settings" msgid="8874581353127418308">"Tingulli dhe dridhjet"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cilësimet"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Titrat në çast"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumi është ulur në një nivel më të sigurt"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumi i kufjeve ka qenë i lartë për një kohë më të gjatë nga sa rekomandohet"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumi i kufjeve ka tejkaluar kufirin e sigurisë për këtë javë"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"lësho dridhje"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Kontrollet e volumit %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Do të bjerë zilja për telefonatat dhe njoftimet (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Po luhet <xliff:g id="LABEL">%s</xliff:g> në"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Do të luhet audio në"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit"</string> <string name="status_bar" msgid="4357390266055077437">"Shiriti i statusit"</string> <string name="demo_mode" msgid="263484519766901593">"Modaliteti i demonstrimit i ndërfaqes së përdoruesit të sistemit"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 5bc9db78f84d..2309d7de205c 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Овим уређајем управља родитељ. Родитељ може да види информације, као што су апликације које користиш, твоју локацију и време испред екрана, и да управља њима."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Поуздани агент спречава закључавање"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Заштита од крађе\nЗакљ. уређај, превише покушаја откључавања"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Подешавања звука"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Аутоматски титл за медије"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"вибрација"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Контроле за јачину звука за %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Мелодија звона за позиве и обавештења је укључена (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> се пушта на"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Звук се пушта на"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Тјунер за кориснички интерфејс система"</string> <string name="status_bar" msgid="4357390266055077437">"Статусна трака"</string> <string name="demo_mode" msgid="263484519766901593">"Режим демонстрације за кориснички интерфејс система"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index bbc9fd63a235..be80f7aefd2d 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sparad"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koppla från"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivera"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivera automatiskt igen i morgon"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Funktioner som Snabbdelning, Hitta min enhet och enhetens plats använder Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ljud"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Den här enheten hanteras av din förälder. Föräldern kan se och hantera information som vilka appar du använder, din plats och din skärmtid."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Hålls olåst med TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Stöldskydd\nEnheten har låsts på grund av för många försök"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ljudinställningar"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Texta media automatiskt"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inaktivera"</string> <string name="sound_settings" msgid="8874581353127418308">"Ljud och vibration"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Inställningar"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live Caption"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volymen har sänkts till en säkrare nivå"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volymen i hörlurarna har varit hög längre än vad som rekommenderas"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volymen i hörlurarna har överskridit den säkra gränsen för veckan"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"vibration"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Volymkontroller för %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Ringsignal används för samtal och aviseringar (volym: <xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Spelar upp <xliff:g id="LABEL">%s</xliff:g> på"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Ljud spelas upp på"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Inställningar för systemgränssnitt"</string> <string name="status_bar" msgid="4357390266055077437">"Statusfält"</string> <string name="demo_mode" msgid="263484519766901593">"Demoläge för systemgränssnitt"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 4a735682491a..09998200c0f4 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Imehifadhiwa"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ondoa"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"anza kutumia"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Iwashe tena kesho kiotomatiki"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Vipengele kama vile Kutuma Haraka, Tafuta Kifaa Changu na mahali kifaa kilipo hutumia Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Sauti"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Vifaa vya sauti"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Kifaa hiki kinadhibitiwa na mzazi wako. Mzazi wako anaweza kuona na kudhibiti maelezo kama vile programu unazotumia, mahali ulipo na muda unaotumia kwenye kifaa."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Imefunguliwa na kipengele cha kutathmini hali ya kuaminika"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Kifaa cha ulinzi\ndhidi ya wizi kimefungwa, kuna majaribio mengi mno ya kukifungua"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Mipangilio ya sauti"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Wekea maudhui manukuu kiotomatiki"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"tetema"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Vidhibiti %s vya sauti"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Itatoa mlio arifa ikitumwa na simu ikipigwa (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Inacheza <xliff:g id="LABEL">%s</xliff:g> kwenye"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Sauti itacheza kwenye"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Kirekebishi cha kiolesura cha mfumo"</string> <string name="status_bar" msgid="4357390266055077437">"Sehemu ya kuonyesha hali"</string> <string name="demo_mode" msgid="263484519766901593">"Hali ya onyesho la kirekebishi cha kiolesura cha mfumo"</string> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index f1017d8fe36e..b4383156dc71 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -53,4 +53,7 @@ <item>bottom_start:home</item> <item>bottom_end:create_note</item> </string-array> + + <!-- Whether volume panel should use the large screen layout or not --> + <bool name="volume_panel_is_large_screen">true</bool> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 6a1e64eb49e4..486d7f97f16e 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"சேமிக்கப்பட்டது"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"இணைப்பு நீக்கும்"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"செயல்படுத்தும்"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"நாளைக்குத் தானாகவே மீண்டும் இயக்கப்படும்"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"விரைவுப் பகிர்தல், Find My Device போன்ற அம்சங்களும் சாதன இருப்பிடமும் புளூடூத்தைப் பயன்படுத்துகின்றன"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> பேட்டரி"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ஆடியோ"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ஹெட்செட்"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது. நீங்கள் பயன்படுத்தும் ஆப்ஸ், இருப்பிடம், பயன்படுத்திய நேரம் ஆகியவற்றைப் பார்க்கவும் நிர்வகிக்கவும் உங்கள் பெற்றோரால் முடியும்."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent இதைத் திறந்தே வைத்துள்ளது"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"திருட்டைத் தடுக்க\nசாதனம் பூட்டப்பட்டது, அதிகமான அன்லாக் முயற்சிகள்"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ஒலி அமைப்புகள்"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"வசன உரைகளைத் தானாக எழுதும்"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"முடக்கும்"</string> <string name="sound_settings" msgid="8874581353127418308">"ஒலி & அதிர்வு"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"அமைப்புகள்"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"உடனடி வசனம்"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"பாதுகாப்பான நிலைக்கு ஒலியளவு குறைக்கப்பட்டது"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ஹெட்ஃபோன் ஒலியளவு பரிந்துரைக்கப்பட்டதைவிட அதிகளவில் நீண்ட நேரமாக உள்ளது"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"இந்த வாரம் ஹெட்ஃபோன் ஒலியளவு பாதுகாப்பு வரம்பைக் கடந்துவிட்டது"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"அதிர்வுறும்"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ஒலியளவுக் கட்டுப்பாடுகள்"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"அழைப்புகளும் அறிவிப்புகளும் வரும்போது ஒலிக்கச் செய்யும் (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"இதில் <xliff:g id="LABEL">%s</xliff:g> பிளே ஆகிறது"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"இல் ஆடியோ பிளே ஆகும்"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"நிலைப் பட்டி"</string> <string name="demo_mode" msgid="263484519766901593">"சிஸ்டம் பயனர் இடைமுக டெமோ பயன்முறை"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 4a494ceca1b3..227ba5a2ea4a 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ చేయబడింది"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్కనెక్ట్ చేయండి"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"రేపు మళ్లీ ఆటోమేటిక్గా ఆన్ చేస్తుంది"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"క్విక్ షేర్, Find My Device, పరికర లొకేషన్ వంటి ఫీచర్లు బ్లూటూత్ను ఉపయోగిస్తాయి"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> బ్యాటరీ"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ఆడియో"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"హెడ్సెట్"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు. మీ తల్లి/తండ్రి, మీరు ఉపయోగించే యాప్లు, మీ లొకేషన్, అలాగే మీ పరికర వినియోగ వ్యవధి వంటి సమాచారాన్ని చూడగలరు, మేనేజ్ చేయగలరు."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ద్వారా అన్లాక్ చేయబడింది"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"దొంగతనం చేయడం నుండి రక్షణ\nపరికరం లాక్ చేయబడింది, చాలా ఎక్కువ అన్లాక్ ప్రయత్నాలు జరిగాయి"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ధ్వని సెట్టింగ్లు"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"మీడియాకు ఆటోమేటిక్ క్యాప్షన్లు"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"వైబ్రేట్"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s వాల్యూమ్ నియంత్రణలు"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"కాల్స్ మరియు నోటిఫికేషన్లు రింగ్ అవుతాయి (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>లో ప్లే అవుతోంది"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"ఆడియో ప్లే అవుతుంది"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string> <string name="status_bar" msgid="4357390266055077437">"స్టేటస్ బార్"</string> <string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index fd4bead3ec43..d1e186fa73b4 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"อุปกรณ์นี้จัดการโดยผู้ปกครอง ผู้ปกครองจะดูและจัดการข้อมูลต่างๆ ได้ เช่น แอปที่คุณใช้ ตำแหน่งของคุณ และเวลาอยู่หน้าจอ"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"ปลดล็อกไว้โดย TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"การป้องกันการโจรกรรม\nอุปกรณ์ถูกล็อก ลองปลดล็อกหลายครั้งเกินไป"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g> <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"การตั้งค่าเสียง"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"แสดงคำบรรยายสื่อโดยอัตโนมัติ"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"สั่น"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"ตัวควบคุมระดับเสียง %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"สายเรียกเข้าและการแจ้งเตือนจะส่งเสียง (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"กำลังเล่น <xliff:g id="LABEL">%s</xliff:g> ใน"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"เสียงจะเล่นต่อไป"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"ตัวรับสัญญาณ UI ระบบ"</string> <string name="status_bar" msgid="4357390266055077437">"แถบสถานะ"</string> <string name="demo_mode" msgid="263484519766901593">"โหมดสาธิต UI ของระบบ"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 5388d7a9ebd0..c929e4579df9 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -530,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Pinapamahalaan ng iyong magulang ang device na ito. Makikita at mapapamahalaan ng iyong magulang ang impormasyon tulad ng mga app na ginagamit mo, iyong lokasyon, at tagal ng paggamit mo sa device."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Pinanatiling naka-unlock ng TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Theft protection\nNa-lock ang device, sobrang pag-unlock"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Mga setting ng tunog"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"I-autocaption ang media"</string> @@ -583,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"i-vibrate"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Mga kontrol ng volume ng %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Magri-ring kapag may mga tawag at notification (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Nagpe-play ang <xliff:g id="LABEL">%s</xliff:g> sa"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"I-play ang audio sa"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Tuner ng System UI"</string> <string name="status_bar" msgid="4357390266055077437">"Status bar"</string> <string name="demo_mode" msgid="263484519766901593">"Demo mode ng System UI"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index fbced87dea31..9407fbbbf3d9 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Kaydedildi"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"bağlantıyı kes"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"etkinleştir"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Yarın otomatik olarak tekrar aç"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Quick Share, Cihazımı Bul ve cihaz konumu gibi özellikler Bluetooth\'u kullanır"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ses"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Mikrofonlu kulaklık"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu cihaz ebeveyniniz tarafından yönetiliyor. Kullandığınız uygulamalar, konumunuz ve ekran başında kalma süreniz gibi bilgiler ebeveyniniz tarafından görülüp yönetilebilir."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent tarafından kilit açık tutuldu"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Hırsızlık koruması\nCihaz kilitlendi, çok fazla kilit açma denemesi"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ses ayarları"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Otomatik medya altyazısı"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"titreşim"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s ses denetimleri"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Aramalar ve bildirimler telefonun zilini çaldıracak (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> şurada çalacak:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Ses şurada çalacak:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Sistem Arayüzü Ayarlayıcısı"</string> <string name="status_bar" msgid="4357390266055077437">"Durum çubuğu"</string> <string name="demo_mode" msgid="263484519766901593">"Sistem kullanıcı arayüzü demo modu"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index c972090dc888..b7a4999865de 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Збережено"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"від’єднати"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активувати"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматично ввімкнути знову завтра"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Такі функції, як швидкий обмін, \"Знайти пристрій\" і визначення місцезнаходження пристрою, використовують Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> заряду акумулятора"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудіопристрій"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнітура"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Цим пристроєм керують твої батьки. Вони можуть бачити та контролювати, якими додатками ти користуєшся, де перебуваєш і скільки часу проводиш за пристроєм."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Розблоковує довірчий агент"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Захист від крадіжки\nПристрій заблоковано (забагато спроб)"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Налаштування звуку"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматичні субтитри (медіа)"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"вимкнути"</string> <string name="sound_settings" msgid="8874581353127418308">"Звук і вібрація"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налаштування"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Живі субтитри"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Гучність знижено до безпечнішого рівня"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Аудіо в навушниках відтворювалося з високою гучністю довше, ніж рекомендується"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гучність навушників перевищила безпечний рівень, допустимий протягом тижня"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"увімкнути вібросигнал"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Регуляторів гучності: %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Для викликів і сповіщень налаштовано звуковий сигнал (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Відтворюється <xliff:g id="LABEL">%s</xliff:g> на:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудіо гратиме на:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Рядок стану"</string> <string name="demo_mode" msgid="263484519766901593">"Демо-режим інтерфейсу системи"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index ede87fc2bf30..f9155a0e06e6 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ ہے"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"غیر منسلک کریں"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کریں"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"کل دوبارہ خودکار طور پر آن ہوگا"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"فوری اشتراک، میرا آلہ ڈھونڈیں، اور آلہ کے مقام جیسی خصوصیات بلوٹوتھ کا استعمال کرتی ہیں"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> بیٹری"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"آڈیو"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ہیڈ سیٹ"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"یہ آلہ آپ کے والدین کے زیر انتظام ہے۔ آپ کے والدین آپ کی استعمال والی ایپس، آپ کا مقام اور آپ کے اسکرین کے وقت جیسی معلومات کو دیکھ اور اس کا نظم کر سکتے ہیں۔"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"ٹرسٹ ایجنٹ نے غیر مقفل رکھا ہے"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"چوری سے تحفظ\n آلہ مقفل ہے، بہت زیادہ غیر مقفل کرنے کی کوششیں"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>۔ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"صوتی ترتیبات"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"خودکار طور پر میڈیا پر کیپشن لگائیں"</string> @@ -585,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"وائبریٹ"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s والیوم کے کنٹرولز"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"کالز اور اطلاعات موصول ہونے پر گھنٹی بجے گی (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> پر چل رہی ہے"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"آڈیو چلتی رہے گی"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"سسٹم UI ٹیونر"</string> <string name="status_bar" msgid="4357390266055077437">"اسٹیٹس بار"</string> <string name="demo_mode" msgid="263484519766901593">"سسٹم UI ڈیمو موڈ"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 6c36d3575d58..82b6b460ef67 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saqlangan"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"uzish"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"faollashtirish"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ertaga yana avtomatik yoqilsin"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Tezkor ulashuv, Qurilmamni top va qurilma geolokatsiyasi kabi funksiyalar Bluetooth ishlatadi"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Garnitura"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu – ota-onangiz tomonidan boshqariladigan qurilma. Ota-onangiz siz foydalangan ilovalar, joylashuvingiz va qurilmadan foydalanish vaqti kabi axborotlarni koʻrishi va boshqarishi mumkin."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent tomonidan ochilgan"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Oʻgʻirlanishdan himoya\nQurilma qulflandi, juda koʻp urinildi"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Tovush sozlamalari"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Avtomatik taglavha yaratish"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"faolsizlantirish"</string> <string name="sound_settings" msgid="8874581353127418308">"Tovush va tebranish"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Sozlamalar"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Jonli izoh"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Tovush xavfsiz darajaga pasaytirildi"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Quloqlik tavsiya etilganidan uzoqroq vaqt baland tovushda ishladi"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Quloqlik tovushi bu hafta xavfsiz balandlik limitidan oshib ketdi"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"tebranish"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s tovush balandligi tugmalari"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chaqiruvlar va bildirishnomalar jiringlaydi (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>da ijro etilmoqda"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio ijro etiladi"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"SystemUI Tuner"</string> <string name="status_bar" msgid="4357390266055077437">"Holat qatori"</string> <string name="demo_mode" msgid="263484519766901593">"Tizim interfeysi demo rejimi"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 3a970fb3e625..2a8d4cdce031 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Đã lưu"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ngắt kết nối"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"kích hoạt"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Tự động bật lại vào ngày mai"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Các tính năng như Chia sẻ nhanh, Tìm thiết bị của tôi và dịch vụ vị trí trên thiết bị có sử dụng Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> pin"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Âm thanh"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Tai nghe"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Thiết bị này do cha mẹ bạn quản lý. Cha mẹ có thể có thể xem và quản lý những thông tin như ứng dụng bạn dùng, vị trí của bạn và thời gian bạn sử dụng thiết bị."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Luôn được TrustAgent mở khóa"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Chống trộm\nĐã khoá thiết bị, quá nhiều lần mở khoá"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Cài đặt âm thanh"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Tự động tạo phụ đề cho nội dung nghe nhìn"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"tắt"</string> <string name="sound_settings" msgid="8874581353127418308">"Âm thanh và chế độ rung"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cài đặt"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Phụ đề trực tiếp"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Âm lượng đã giảm xuống mức an toàn hơn"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Bạn đã dùng tai nghe ở mức âm lượng cao lâu hơn khoảng thời gian khuyến nghị, điều này có thể gây tổn hại đến thính giác của bạn"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Âm lượng tai nghe đã vượt quá giới hạn an toàn của tuần này"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"rung"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"Điều khiển âm lượng %s"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Cuộc gọi và thông báo sẽ đổ chuông (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Đang phát <xliff:g id="LABEL">%s</xliff:g> trên"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Âm thanh sẽ phát ra"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Bộ điều hướng giao diện người dùng hệ thống"</string> <string name="status_bar" msgid="4357390266055077437">"Thanh trạng thái"</string> <string name="demo_mode" msgid="263484519766901593">"Chế độ thử nghiệm giao diện người dùng hệ thống"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index fbdc86c90868..ddef35f6d1b8 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"断开连接"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"启用"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自动重新开启"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"快速分享、查找我的设备、设备位置信息等功能会使用蓝牙"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> 的电量"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音频"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳机"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"此设备由您的家长管理。您的家长可以查看和管理相关信息,例如您使用的应用、您的位置信息和设备使用时间。"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"由 TrustAgent 保持解锁状态"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"防盗保护\n设备已锁定,因为尝试解锁的次数过多"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>(<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>)"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"声音设置"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"自动生成媒体字幕"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string> <string name="sound_settings" msgid="8874581353127418308">"声音和振动"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"设置"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"实时字幕"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已降至较安全的水平"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"您以高音量使用耳机的时长超过了建议值"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳机音量已超出这周的安全上限"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"振动"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s音量控件"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"有来电和通知时会响铃 (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>播放位置:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"音频播放位置:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"系统界面调节工具"</string> <string name="status_bar" msgid="4357390266055077437">"状态栏"</string> <string name="demo_mode" msgid="263484519766901593">"系统界面演示模式"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 4579ca2436cb..dbf2cc0a25c8 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"解除連結"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟動"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自動重新開啟"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"「快速共享」、「尋找我的裝置」和裝置位置等功能都會使用藍牙"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音訊"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳機"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"此裝置由你的家長管理。家長可以查看及管理裝置上的資料,例如你使用的應用程式、位置和裝置使用時間。"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"由信任的代理保持解鎖狀態"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"防盜保護\n嘗試解鎖次數過多,裝置已上鎖"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"音效設定"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"自動為媒體加入字幕"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string> <string name="sound_settings" msgid="8874581353127418308">"音效和震動"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"即時字幕"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已降至較安全的水平"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"以高音量使用耳機的時間已超過建議範圍"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳機音量已超過本週安全限制"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"震動"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s音量控制項"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"有來電和通知時會發出鈴聲 (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"正在播放「<xliff:g id="LABEL">%s</xliff:g>」的裝置:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"音訊播放媒體"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"系統使用者介面調諧器"</string> <string name="status_bar" msgid="4357390266055077437">"狀態列"</string> <string name="demo_mode" msgid="263484519766901593">"系統使用者介面示範模式"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 05d9ec319f09..d92de1cf6af9 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自動重新開啟"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"快速分享、尋找我的裝置和裝置位置資訊等功能都會使用藍牙"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音訊"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳機"</string> @@ -529,9 +527,10 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"你的個人應用程式已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路。請注意,VPN 供應商可以看見你的網路活動,包括電子郵件和瀏覽資料。"</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"開啟 VPN 設定"</string> - <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"這個裝置是由你的家長管理。家長可以查看及管理裝置上的資訊,例如你使用的應用程式、所在位置和裝置使用時間。"</string> + <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"這個裝置是由你的家長管理。家長可以查看及管理裝置上的資訊,例如你使用的應用程式、所在位置和螢幕時間。"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"由 TrustAgent 維持解鎖狀態"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"防盜保護\n解鎖失敗次數過多,裝置已鎖定"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"音效設定"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"自動產生媒體字幕"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string> <string name="sound_settings" msgid="8874581353127418308">"音效與震動"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"即時字幕"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已調低至安全範圍"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"耳機以高音量播放已超過建議時間"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳罩式耳機的音量已超過本週的安全限制"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"震動"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"「%s」音量控制項"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"有來電和通知時會響鈴 (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"正在播放「<xliff:g id="LABEL">%s</xliff:g>」的裝置:"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"將播放音訊的媒體:"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"系統使用者介面調整精靈"</string> <string name="status_bar" msgid="4357390266055077437">"狀態列"</string> <string name="demo_mode" msgid="263484519766901593">"系統 UI 展示模式"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 46ec239ed950..9cd70829c30c 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -268,10 +268,8 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ilondoloziwe"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"nqamula"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"yenza kusebenze"</string> - <!-- no translation found for turn_on_bluetooth_auto_tomorrow (414836329962473906) --> - <skip /> - <!-- no translation found for turn_on_bluetooth_auto_info (8831410009251539988) --> - <skip /> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Vula ngokuzenzekela futhi kusasa"</string> + <string name="turn_on_bluetooth_auto_info" msgid="8831410009251539988">"Izakhi ezifana Nokwabelana Ngokushesha, okuthi Thola Idivayisi Yami, kanye nendawo yedivayisi zisebenzisa i-Bluetooth"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ibhethri"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Umsindo"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ihedisethi"</string> @@ -532,6 +530,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Le divayisi iphethwe ngumzali wakho. Umzali wakho angabona futhi aphathe ulwazi olunjengezinhlelo zokusebenza ozisebenzisayo, indawo yakho, kanye nesikhathi sesikrini."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"I-VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Igcinwa ivuliwe ngo-TrustAgent"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="1265107698772588299">"Isivikelo sokweba\nIdivayisi ikhiyiwe, imizamo yokuvula eminingi kakhulu"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Izilungiselelo zomsindo"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Yenza amagama-ngcazo ngokuzenzakalela emidiya"</string> @@ -541,8 +540,7 @@ <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"khubaza"</string> <string name="sound_settings" msgid="8874581353127418308">"Umsindo nokudlidliza"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Amasethingi"</string> - <!-- no translation found for volume_panel_captioning_title (5984936949147684357) --> - <skip /> + <string name="volume_panel_captioning_title" msgid="5984936949147684357">"Okushuthwe Bukhoma"</string> <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ivolumu yehliselwe kuleveli ephephile"</string> <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ivolumu yama-headphone beyiphezulu isikhathi eside kunokunconyiwe"</string> <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Ivolumu yama-headphone ibe phezulu kunokunconyiwe, okungalimaza ukuzwa kwakho"</string> @@ -586,6 +584,8 @@ <string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"dlidliza"</string> <string name="volume_dialog_title" msgid="6502703403483577940">"%s izilawuli zevolomu"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Amakholi nezaziso zizokhala (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> + <string name="media_output_label_title" msgid="872824698593182505">"Idlala ku-<xliff:g id="LABEL">%s</xliff:g>"</string> + <string name="media_output_title_without_playing" msgid="3825663683169305013">"Umsindo uzodlala"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Isishuni se-UI yesistimu"</string> <string name="status_bar" msgid="4357390266055077437">"Ibha yesimo"</string> <string name="demo_mode" msgid="263484519766901593">"Imodi yedemo ye-UI yesistimu"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 65c69f78e9d0..beaa708b4dcc 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -1010,4 +1010,7 @@ <!-- Whether to use a machine learning model for back gesture falsing. --> <bool name="config_useBackGestureML">true</bool> + + <!-- Whether volume panel should use the large screen layout or not --> + <bool name="volume_panel_is_large_screen">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 5436642dc5a1..4be1deb3de1c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1518,6 +1518,12 @@ <!-- GLANCEABLE_HUB -> LOCKSCREEN transition: Amount to shift lockscreen content on entering --> <dimen name="hub_to_lockscreen_transition_lockscreen_translation_x">824dp</dimen> + <!-- DREAMING -> GLANCEABLE_HUB transition: Amount to shift dream overlay on entering --> + <dimen name="dreaming_to_hub_transition_dream_overlay_translation_x">-824dp</dimen> + + <!-- GLANCEABLE_HUB -> DREAMING transition: Amount to shift dream overlay on entering --> + <dimen name="hub_to_dreaming_transition_dream_overlay_translation_x">824dp</dimen> + <!-- Distance that the full shade transition takes in order for media to fully transition to the shade --> <dimen name="lockscreen_shade_media_transition_distance">120dp</dimen> @@ -1861,7 +1867,6 @@ <dimen name="dream_overlay_y_offset">80dp</dimen> <dimen name="dream_overlay_entry_y_offset">40dp</dimen> <dimen name="dream_overlay_exit_y_offset">40dp</dimen> - <dimen name="dream_overlay_exit_x_offset">824dp</dimen> <dimen name="status_view_margin_horizontal">0dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 495f20f27996..4263d9402d66 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1513,6 +1513,11 @@ <string name="volume_ringer_status_vibrate">Vibrate</string> <string name="volume_ringer_status_silent">Mute</string> + <!-- Media device casting volume slider label [CHAR_LIMIT=20] --> + <string name="media_device_cast">Cast</string> + <!-- A message shown when the notification volume changing is disabled because of the muted ring stream [CHAR_LIMIT=40]--> + <string name="stream_notification_unavailable">Unavailable because ring is muted</string> + <!-- Shown in the header of quick settings to indicate to the user that their phone ringer is on vibrate. [CHAR_LIMIT=NONE] --> <!-- Shown in the header of quick settings to indicate to the user that their phone ringer is on silent (muted). [CHAR_LIMIT=NONE] --> @@ -3129,6 +3134,8 @@ <!-- [CHAR LIMIT=25] Long label used by Note Task Shortcut --> <string name="note_task_shortcut_long_label">Note-taking, <xliff:g id="note_taking_app" example="Note-taking App">%1$s</xliff:g></string> + <!-- [CHAR LIMIT=NONE] Output switch chip text during broadcasting --> + <string name="audio_sharing_description">Sharing audio</string> <!-- [CHAR LIMIT=NONE] Le audio broadcast dialog, media app is broadcasting --> <string name="broadcasting_description_is_broadcasting">Broadcasting</string> <!-- [CHAR LIMIT=NONE] Le audio broadcast dialog, title --> diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 8b2a0ec27011..05e07a788892 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -377,7 +377,9 @@ constructor( if (mode == ZenMode.OFF) SysuiR.string::dnd_is_off.name else SysuiR.string::dnd_is_on.name ).also { data -> - clock?.run { events.onZenDataChanged(data) } + mainExecutor.execute { + clock?.run { events.onZenDataChanged(data) } + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java index 476497dea9c4..10d1891c8405 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java @@ -19,6 +19,7 @@ package com.android.keyguard; import static com.android.systemui.Flags.pinInputFieldStyledFocusState; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; +import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; import android.util.TypedValue; @@ -150,18 +151,22 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB } private void setKeyboardBasedFocusOutline(boolean isAnyKeyboardConnected) { - StateListDrawable background = (StateListDrawable) mPasswordEntry.getBackground(); - GradientDrawable stateDrawable = (GradientDrawable) background.getStateDrawable(0); + Drawable background = mPasswordEntry.getBackground(); + if (!(background instanceof StateListDrawable)) return; + Drawable stateDrawable = ((StateListDrawable) background).getStateDrawable(0); + if (!(stateDrawable instanceof GradientDrawable gradientDrawable)) return; + int color = getResources().getColor(R.color.bouncer_password_focus_color); if (!isAnyKeyboardConnected) { - stateDrawable.setStroke(0, color); + gradientDrawable.setStroke(0, color); } else { int strokeWidthInDP = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics()); - stateDrawable.setStroke(strokeWidthInDP, color); + gradientDrawable.setStroke(strokeWidthInDP, color); } } + @Override protected void onViewDetached() { super.onViewDetached(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java index d2fda4cfd186..88fa2de186d0 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java @@ -273,6 +273,10 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { } } + void onFullscreenMagnificationActivationChanged(int displayId, boolean activated) { + // Do nothing + } + @MainThread void toggleSettingsPanelVisibility(int displayId) { final MagnificationSettingsController magnificationSettingsController = diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java index ba943b07b704..b5f3aef88dc4 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java @@ -47,6 +47,12 @@ class MagnificationConnectionImpl extends IMagnificationConnection.Stub { } @Override + public void onFullscreenMagnificationActivationChanged(int displayId, boolean activated) { + mHandler.post(() -> mMagnification + .onFullscreenMagnificationActivationChanged(displayId, activated)); + } + + @Override public void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, IRemoteMagnificationAnimationCallback callback) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java index 27f9106fde7c..6299739c4461 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java @@ -464,9 +464,6 @@ class MenuView extends FrameLayout implements Bundle fragmentArgs = new Bundle(); fragmentArgs.putStringArray("targets", targets.toArray(new String[0])); args.putBundle(":settings:show_fragment_args", fragmentArgs); - // TODO: b/318748373 - The fragment should set its own title using the targets - args.putString( - ":settings:show_fragment_title", "Accessibility Shortcut"); intent.replaceExtras(args); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); return intent; diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 74ea58caf8b6..d30f33f5ba2c 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -31,6 +31,7 @@ import com.android.internal.app.IVisualQueryRecognitionStatusListener; import com.android.internal.app.IVoiceInteractionSessionListener; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.assist.domain.interactor.AssistInteractor; import com.android.systemui.assist.ui.DefaultUiController; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -149,6 +150,7 @@ public class AssistManager { private final SecureSettings mSecureSettings; private final SelectedUserInteractor mSelectedUserInteractor; private final ActivityManager mActivityManager; + private final AssistInteractor mInteractor; private final DeviceProvisionedController mDeviceProvisionedController; @@ -192,7 +194,8 @@ public class AssistManager { DisplayTracker displayTracker, SecureSettings secureSettings, SelectedUserInteractor selectedUserInteractor, - ActivityManager activityManager) { + ActivityManager activityManager, + AssistInteractor interactor) { mContext = context; mDeviceProvisionedController = controller; mCommandQueue = commandQueue; @@ -206,6 +209,7 @@ public class AssistManager { mSecureSettings = secureSettings; mSelectedUserInteractor = selectedUserInteractor; mActivityManager = activityManager; + mInteractor = interactor; registerVoiceInteractionSessionListener(); registerVisualQueryRecognitionStatusListener(); @@ -314,6 +318,7 @@ public class AssistManager { assistComponent, legacyDeviceState); logStartAssistLegacy(legacyInvocationType, legacyDeviceState); + mInteractor.onAssistantStarted(legacyInvocationType); startAssistInternal(args, assistComponent, isService); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/data/repository/AssistRepository.kt b/packages/SystemUI/src/com/android/systemui/assist/data/repository/AssistRepository.kt new file mode 100644 index 000000000000..c416c249dec4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/assist/data/repository/AssistRepository.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist.data.repository + +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow + +@SysUISingleton +class AssistRepository @Inject constructor() { + private val _latestInvocationType = + MutableSharedFlow<Int>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + /** The type of the latest invocation of the assistant. */ + val latestInvocationType: SharedFlow<Int> = _latestInvocationType.asSharedFlow() + + /** Sets the type of the latest invocation of the assistant. */ + fun setLatestInvocationType(type: Int) { + _latestInvocationType.tryEmit(type) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/assist/domain/interactor/AssistInteractor.kt b/packages/SystemUI/src/com/android/systemui/assist/domain/interactor/AssistInteractor.kt new file mode 100644 index 000000000000..d9e46aabf539 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/assist/domain/interactor/AssistInteractor.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist.domain.interactor + +import com.android.systemui.Flags +import com.android.systemui.assist.data.repository.AssistRepository +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject +import kotlinx.coroutines.flow.SharedFlow + +@SysUISingleton +class AssistInteractor +@Inject +constructor( + private val repository: AssistRepository, +) { + /** The type of the latest invocation of the assistant. */ + val latestInvocationType: SharedFlow<Int> = repository.latestInvocationType + + /** Notifies that Assistant has been started. */ + fun onAssistantStarted(type: Int) { + if (Flags.enableContextualTips() && Flags.enableContextualTipForPowerOff()) { + repository.setLatestInvocationType(type) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 716209d18a01..2c3ebe901850 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -80,6 +80,7 @@ import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlay import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; 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.Main; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; @@ -90,6 +91,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.LockscreenShadeTransitionController; @@ -116,6 +118,7 @@ import java.util.concurrent.Executor; import javax.inject.Inject; +import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; /** @@ -173,6 +176,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { mDefaultUdfpsTouchOverlayViewModel; @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor; @NonNull private final UdfpsOverlayInteractor mUdfpsOverlayInteractor; + @NonNull private final PowerInteractor mPowerInteractor; + @NonNull private final CoroutineScope mScope; @NonNull private final InputManager mInputManager; @NonNull private final UdfpsKeyguardAccessibilityDelegate mUdfpsKeyguardAccessibilityDelegate; @NonNull private final SelectedUserInteractor mSelectedUserInteractor; @@ -296,7 +301,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { mDeviceEntryUdfpsTouchOverlayViewModel, mDefaultUdfpsTouchOverlayViewModel, mShadeInteractor, - mUdfpsOverlayInteractor + mUdfpsOverlayInteractor, + mPowerInteractor, + mScope ))); } @@ -678,7 +685,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull KeyguardTransitionInteractor keyguardTransitionInteractor, Lazy<DeviceEntryUdfpsTouchOverlayViewModel> deviceEntryUdfpsTouchOverlayViewModel, Lazy<DefaultUdfpsTouchOverlayViewModel> defaultUdfpsTouchOverlayViewModel, - @NonNull UdfpsOverlayInteractor udfpsOverlayInteractor) { + @NonNull UdfpsOverlayInteractor udfpsOverlayInteractor, + @NonNull PowerInteractor powerInteractor, + @Application CoroutineScope scope) { mContext = context; mExecution = execution; mVibrator = vibrator; @@ -720,6 +729,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { mShadeInteractor = shadeInteractor; mAlternateBouncerInteractor = alternateBouncerInteractor; mUdfpsOverlayInteractor = udfpsOverlayInteractor; + mPowerInteractor = powerInteractor; + mScope = scope; mInputManager = inputManager; mUdfpsKeyguardAccessibilityDelegate = udfpsKeyguardAccessibilityDelegate; mSelectedUserInteractor = selectedUserInteractor; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index a209eae5673b..921e39532f58 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -44,6 +44,7 @@ import android.view.accessibility.AccessibilityManager.TouchExplorationStateChan import androidx.annotation.LayoutRes import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.Flags.udfpsViewPerformance import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams @@ -53,10 +54,13 @@ import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayView import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.LockscreenShadeTransitionController @@ -67,7 +71,13 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.user.domain.interactor.SelectedUserInteractor import dagger.Lazy +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch private const val TAG = "UdfpsControllerOverlay" @@ -82,36 +92,45 @@ const val SETTING_REMOVE_ENROLLMENT_UI = "udfps_overlay_remove_enrollment_ui" @ExperimentalCoroutinesApi @UiThread class UdfpsControllerOverlay @JvmOverloads constructor( - private val context: Context, - private val inflater: LayoutInflater, - private val windowManager: WindowManager, - private val accessibilityManager: AccessibilityManager, - private val statusBarStateController: StatusBarStateController, - private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager, - private val keyguardUpdateMonitor: KeyguardUpdateMonitor, - private val dialogManager: SystemUIDialogManager, - private val dumpManager: DumpManager, - private val transitionController: LockscreenShadeTransitionController, - private val configurationController: ConfigurationController, - private val keyguardStateController: KeyguardStateController, - private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController, - private var udfpsDisplayModeProvider: UdfpsDisplayModeProvider, - val requestId: Long, - @RequestReason val requestReason: Int, - private val controllerCallback: IUdfpsOverlayControllerCallback, - private val onTouch: (View, MotionEvent, Boolean) -> Boolean, - private val activityTransitionAnimator: ActivityTransitionAnimator, - private val primaryBouncerInteractor: PrimaryBouncerInteractor, - private val alternateBouncerInteractor: AlternateBouncerInteractor, - private val isDebuggable: Boolean = Build.IS_DEBUGGABLE, - private val udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate, - private val transitionInteractor: KeyguardTransitionInteractor, - private val selectedUserInteractor: SelectedUserInteractor, - private val deviceEntryUdfpsTouchOverlayViewModel: Lazy<DeviceEntryUdfpsTouchOverlayViewModel>, - private val defaultUdfpsTouchOverlayViewModel: Lazy<DefaultUdfpsTouchOverlayViewModel>, - private val shadeInteractor: ShadeInteractor, - private val udfpsOverlayInteractor: UdfpsOverlayInteractor, + private val context: Context, + private val inflater: LayoutInflater, + private val windowManager: WindowManager, + private val accessibilityManager: AccessibilityManager, + private val statusBarStateController: StatusBarStateController, + private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val dialogManager: SystemUIDialogManager, + private val dumpManager: DumpManager, + private val transitionController: LockscreenShadeTransitionController, + private val configurationController: ConfigurationController, + private val keyguardStateController: KeyguardStateController, + private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController, + private var udfpsDisplayModeProvider: UdfpsDisplayModeProvider, + val requestId: Long, + @RequestReason val requestReason: Int, + private val controllerCallback: IUdfpsOverlayControllerCallback, + private val onTouch: (View, MotionEvent, Boolean) -> Boolean, + private val activityTransitionAnimator: ActivityTransitionAnimator, + private val primaryBouncerInteractor: PrimaryBouncerInteractor, + private val alternateBouncerInteractor: AlternateBouncerInteractor, + private val isDebuggable: Boolean = Build.IS_DEBUGGABLE, + private val udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate, + private val transitionInteractor: KeyguardTransitionInteractor, + private val selectedUserInteractor: SelectedUserInteractor, + private val deviceEntryUdfpsTouchOverlayViewModel: + Lazy<DeviceEntryUdfpsTouchOverlayViewModel>, + private val defaultUdfpsTouchOverlayViewModel: Lazy<DefaultUdfpsTouchOverlayViewModel>, + private val shadeInteractor: ShadeInteractor, + private val udfpsOverlayInteractor: UdfpsOverlayInteractor, + private val powerInteractor: PowerInteractor, + @Application private val scope: CoroutineScope, ) { + private val isFinishedGoingToSleep: Flow<Unit> = + powerInteractor.detailedWakefulness + .filter { it.internalWakefulnessState == WakefulnessState.ASLEEP } + .map { } // map to Unit + private var listenForAsleepJob: Job? = null + private var addViewRunnable: Runnable? = null private var overlayViewLegacy: UdfpsView? = null private set private var overlayTouchView: UdfpsTouchOverlay? = null @@ -192,7 +211,8 @@ class UdfpsControllerOverlay @JvmOverloads constructor( if (requestReason.isImportantForAccessibility()) { importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO } - windowManager.addView(this, coreLayoutParams.updateDimensions(null)) + + addViewNowOrLater(this, null) when (requestReason) { REASON_AUTH_KEYGUARD -> UdfpsTouchOverlayBinder.bind( @@ -225,7 +245,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor( importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO } - windowManager.addView(this, coreLayoutParams.updateDimensions(animation)) + addViewNowOrLater(this, animation) sensorRect = sensorBounds } } @@ -257,6 +277,41 @@ class UdfpsControllerOverlay @JvmOverloads constructor( return false } + private fun addViewNowOrLater(view: View, animation: UdfpsAnimationViewController<*>?) { + if (udfpsViewPerformance()) { + addViewRunnable = kotlinx.coroutines.Runnable { + windowManager.addView( + view, + coreLayoutParams.updateDimensions(animation) + ) + } + if (powerInteractor.detailedWakefulness.value.internalWakefulnessState + != WakefulnessState.STARTING_TO_SLEEP) { + addViewIfPending() + } else { + listenForAsleepJob?.cancel() + listenForAsleepJob = scope.launch { + isFinishedGoingToSleep.collect { + addViewIfPending() + } + } + } + } else { + windowManager.addView( + view, + coreLayoutParams.updateDimensions(animation) + ) + } + } + + private fun addViewIfPending() { + addViewRunnable?.let { + listenForAsleepJob?.cancel() + it.run() + } + addViewRunnable = null + } + fun inflateUdfpsAnimation( view: UdfpsView, controller: UdfpsController @@ -368,6 +423,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor( overlayViewLegacy = null overlayTouchView = null overlayTouchListener = null + listenForAsleepJob?.cancel() return wasShowing } @@ -412,7 +468,8 @@ class UdfpsControllerOverlay @JvmOverloads constructor( if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { if (!shouldRotate(animation)) { Log.v( - TAG, "Skip rotating UDFPS bounds " + Surface.rotationToString(rot) + + TAG, + "Skip rotating UDFPS bounds " + Surface.rotationToString(rot) + " animation=$animation" + " isGoingToSleep=${keyguardUpdateMonitor.isGoingToSleep}" + " isOccluded=${keyguardStateController.isOccluded}" diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt index ae1539ebaf89..59b59bf1e437 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt @@ -50,6 +50,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext @@ -64,13 +65,16 @@ interface FacePropertyRepository { /** The current face sensor location in current device rotation */ val sensorLocation: StateFlow<Point?> + + /** The info of current available camera. */ + val cameraInfo: StateFlow<CameraInfo?> } /** Describes a biometric sensor */ data class FaceSensorInfo(val id: Int, val strength: SensorStrength) /** Data class for camera info */ -private data class CameraInfo( +data class CameraInfo( /** The logical id of the camera */ val cameraId: String, /** The physical id of the camera */ @@ -124,7 +128,7 @@ constructor( private val cameraInfoList: List<CameraInfo> = loadCameraInfoList() private var currentPhysicalCameraId: String? = null - private val defaultSensorLocation: StateFlow<Point?> = + override val cameraInfo: StateFlow<CameraInfo?> = ConflatedCallbackFlow.conflatedCallbackFlow { val callback = object : CameraManager.AvailabilityCallback() { @@ -142,7 +146,7 @@ constructor( physicalCameraId == it.cameraPhysicalId } trySendWithFailureLogging( - cameraInfo?.cameraLocation, + cameraInfo, TAG, "Update face sensor location to $cameraInfo." ) @@ -168,7 +172,7 @@ constructor( } currentPhysicalCameraId = cameraInfo?.cameraPhysicalId trySendWithFailureLogging( - cameraInfo?.cameraLocation, + cameraInfo, TAG, "Update face sensor location to $cameraInfo." ) @@ -181,8 +185,16 @@ constructor( .stateIn( applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = - if (cameraInfoList.isNotEmpty()) cameraInfoList[0].cameraLocation else null + initialValue = if (cameraInfoList.isNotEmpty()) cameraInfoList[0] else null + ) + + private val defaultSensorLocation: StateFlow<Point?> = + cameraInfo + .map { it?.cameraLocation } + .stateIn( + applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = null ) override val sensorLocation: StateFlow<Point?> = diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt index b0cc3bd807dd..cd5b12482d83 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt @@ -438,9 +438,20 @@ object BiometricViewBinder { // Play haptics launch { - viewModel.hapticsToPlay.collect { hapticFeedbackConstant -> - if (hapticFeedbackConstant != HapticFeedbackConstants.NO_HAPTICS) { - vibratorHelper.performHapticFeedback(view, hapticFeedbackConstant) + viewModel.hapticsToPlay.collect { haptics -> + if (haptics.hapticFeedbackConstant != HapticFeedbackConstants.NO_HAPTICS) { + if (haptics.flag != null) { + vibratorHelper.performHapticFeedback( + view, + haptics.hapticFeedbackConstant, + haptics.flag, + ) + } else { + vibratorHelper.performHapticFeedback( + view, + haptics.hapticFeedbackConstant, + ) + } viewModel.clearHaptics() } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt index 788991d2e45b..c933e0e31d40 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt @@ -53,6 +53,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch /** ViewModel for BiometricPrompt. */ @@ -144,9 +145,10 @@ constructor( private val _forceLargeSize = MutableStateFlow(false) private val _forceMediumSize = MutableStateFlow(false) - private val _hapticsToPlay = MutableStateFlow(HapticFeedbackConstants.NO_HAPTICS) + private val _hapticsToPlay = + MutableStateFlow(HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, /* flag= */ null)) - /** Event fired to the view indicating a [HapticFeedbackConstants] to be played */ + /** Event fired to the view indicating a [HapticsToPlay] */ val hapticsToPlay = _hapticsToPlay.asStateFlow() /** The current position of the prompt */ @@ -686,16 +688,26 @@ constructor( } private fun vibrateOnSuccess() { - _hapticsToPlay.value = HapticFeedbackConstants.CONFIRM + _hapticsToPlay.value = + HapticsToPlay( + HapticFeedbackConstants.CONFIRM, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING, + ) } private fun vibrateOnError() { - _hapticsToPlay.value = HapticFeedbackConstants.REJECT + _hapticsToPlay.value = + HapticsToPlay( + HapticFeedbackConstants.REJECT, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING, + ) } - /** Clears the [hapticsToPlay] variable by setting it to the NO_HAPTICS default. */ + /** Clears the [hapticsToPlay] variable by setting its constant to the NO_HAPTICS default. */ fun clearHaptics() { - _hapticsToPlay.value = HapticFeedbackConstants.NO_HAPTICS + _hapticsToPlay.update { previous -> + HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, previous.flag) + } } companion object { @@ -724,3 +736,9 @@ enum class FingerprintStartMode { val isStarted: Boolean get() = this == Normal || this == Delayed } + +/** + * The state of haptic feedback to play. It is composed by a [HapticFeedbackConstants] and a + * [HapticFeedbackConstants] flag. + */ +data class HapticsToPlay(val hapticFeedbackConstant: Int, val flag: Int?) diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java index 00bbb20ed4f9..6af0fa069dbc 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java @@ -40,6 +40,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.MediaOutputConstants; import com.android.systemui.broadcast.BroadcastSender; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.media.controls.util.MediaDataUtils; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.res.R; @@ -74,7 +75,7 @@ public class BroadcastDialogDelegate implements SystemUIDialog.Delegate { private final SystemUIDialog.Factory mSystemUIDialogFactory; private final String mCurrentBroadcastApp; private final String mOutputPackageName; - private final Executor mExecutor; + private final Executor mBgExecutor; private boolean mShouldLaunchLeBroadcastDialog; private Button mSwitchBroadcast; @@ -159,7 +160,7 @@ public class BroadcastDialogDelegate implements SystemUIDialog.Delegate { MediaOutputDialogFactory mediaOutputDialogFactory, @Nullable LocalBluetoothManager localBluetoothManager, UiEventLogger uiEventLogger, - Executor executor, + @Background Executor bgExecutor, BroadcastSender broadcastSender, SystemUIDialog.Factory systemUIDialogFactory, @Assisted(CURRENT_BROADCAST_APP) String currentBroadcastApp, @@ -171,7 +172,7 @@ public class BroadcastDialogDelegate implements SystemUIDialog.Delegate { mCurrentBroadcastApp = currentBroadcastApp; mOutputPackageName = outputPkgName; mUiEventLogger = uiEventLogger; - mExecutor = executor; + mBgExecutor = bgExecutor; mBroadcastSender = broadcastSender; if (DEBUG) { @@ -187,7 +188,7 @@ public class BroadcastDialogDelegate implements SystemUIDialog.Delegate { @Override public void onStart(SystemUIDialog dialog) { mDialogs.add(dialog); - registerBroadcastCallBack(mExecutor, mBroadcastCallback); + registerBroadcastCallBack(mBgExecutor, mBroadcastCallback); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java index 2af49cfbf1b1..b2699673f7ea 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java @@ -143,7 +143,7 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { mTextPreview.getViewTreeObserver().addOnPreDrawListener(() -> { int availableHeight = mTextPreview.getHeight() - (mTextPreview.getPaddingTop() + mTextPreview.getPaddingBottom()); - mTextPreview.setMaxLines(availableHeight / mTextPreview.getLineHeight()); + mTextPreview.setMaxLines(Math.max(availableHeight / mTextPreview.getLineHeight(), 1)); return true; }); super.onFinishInflate(); diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index f7ba5a44f4c9..8397372e0735 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -88,7 +88,6 @@ constructor( val docked = dockManager.isDocked return when { - to == KeyguardState.DREAMING -> CommunalSceneKey.Blank docked && to == KeyguardState.LOCKSCREEN && from != KeyguardState.GLANCEABLE_HUB -> { CommunalSceneKey.Communal } diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt index 9e68ff88622c..f4a3bcb7a0fa 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt @@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.scene.data.repository.SceneContainerRepository import com.android.systemui.scene.shared.flag.SceneContainerFlags -import com.android.systemui.scene.shared.model.SceneKey import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -33,14 +32,10 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Encapsulates the state of communal mode. */ interface CommunalRepository { - /** Whether the communal hub is showing. */ - val isCommunalHubShowing: Flow<Boolean> - /** * Target scene as requested by the underlying [SceneTransitionLayout] or through * [setDesiredScene]. @@ -99,11 +94,4 @@ constructor( override fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) { _transitionState.value = transitionState } - - override val isCommunalHubShowing: Flow<Boolean> = - if (sceneContainerFlags.isEnabled()) { - sceneContainerRepository.currentScene.map { sceneKey -> sceneKey == SceneKey.Communal } - } else { - desiredScene.map { sceneKey -> sceneKey == CommunalSceneKey.Communal } - } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index 988393ef0c8a..5d525413a919 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -29,6 +29,7 @@ import com.android.systemui.communal.shared.model.CommunalContentSize.FULL import com.android.systemui.communal.shared.model.CommunalContentSize.HALF import com.android.systemui.communal.shared.model.CommunalContentSize.THIRD import com.android.systemui.communal.shared.model.CommunalSceneKey +import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState import com.android.systemui.communal.widgets.CommunalAppWidgetHost import com.android.systemui.communal.widgets.EditWidgetsActivityStarter @@ -42,6 +43,10 @@ import com.android.systemui.log.dagger.CommunalLog import com.android.systemui.log.dagger.CommunalTableLog import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.model.SceneKey +import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.data.repository.SmartspaceRepository import com.android.systemui.util.kotlin.BooleanFlowOperators.and import com.android.systemui.util.kotlin.BooleanFlowOperators.not @@ -56,7 +61,9 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach @@ -78,6 +85,9 @@ constructor( communalSettingsInteractor: CommunalSettingsInteractor, private val appWidgetHost: CommunalAppWidgetHost, private val editWidgetsActivityStarter: EditWidgetsActivityStarter, + private val userTracker: UserTracker, + sceneInteractor: SceneInteractor, + sceneContainerFlags: SceneContainerFlags, @CommunalLog logBuffer: LogBuffer, @CommunalTableLog tableLogBuffer: TableLogBuffer, ) { @@ -119,8 +129,13 @@ constructor( /** * Target scene as requested by the underlying [SceneTransitionLayout] or through * [onSceneChanged]. + * + * If [isCommunalAvailable] is false, will return [CommunalSceneKey.Blank] */ - val desiredScene: StateFlow<CommunalSceneKey> = communalRepository.desiredScene + val desiredScene: Flow<CommunalSceneKey> = + communalRepository.desiredScene.combine(isCommunalAvailable) { scene, available -> + if (available) scene else CommunalSceneKey.Blank + } /** Transition state of the hub mode. */ val transitionState: StateFlow<ObservableCommunalTransitionState> = @@ -172,8 +187,14 @@ constructor( */ // TODO(b/323215860): rename to something more appropriate after cleaning up usages val isCommunalShowing: Flow<Boolean> = - communalRepository.desiredScene - .map { it == CommunalSceneKey.Communal } + flow { emit(sceneContainerFlags.isEnabled()) } + .flatMapLatest { sceneContainerEnabled -> + if (sceneContainerEnabled) { + sceneInteractor.currentScene.map { it == SceneKey.Communal } + } else { + desiredScene.map { it == CommunalSceneKey.Communal } + } + } .distinctUntilChanged() .onEach { showing -> logger.i({ "Communal is ${if (bool1) "showing" else "gone"}" }) { bool1 = showing } @@ -250,10 +271,16 @@ constructor( fun updateWidgetOrder(widgetIdToPriorityMap: Map<Int, Int>) = widgetRepository.updateWidgetOrder(widgetIdToPriorityMap) + /** All widgets present in db. */ + val communalWidgets: Flow<List<CommunalWidgetContentModel>> = + isCommunalAvailable.flatMapLatest { available -> + if (!available) emptyFlow() else widgetRepository.communalWidgets + } + /** A list of widget content to be displayed in the communal hub. */ val widgetContent: Flow<List<CommunalContentModel.Widget>> = widgetRepository.communalWidgets.map { widgets -> - widgets.map Widget@{ widget -> + filterWidgetsByExistingUsers(widgets).map Widget@{ widget -> return@Widget CommunalContentModel.Widget( appWidgetId = widget.appWidgetId, providerInfo = widget.providerInfo, @@ -333,6 +360,19 @@ constructor( return@combine ongoingContent } + /** + * Filter and retain widgets associated with an existing user, safeguarding against displaying + * stale data following user deletion. + */ + private fun filterWidgetsByExistingUsers( + list: List<CommunalWidgetContentModel>, + ): List<CommunalWidgetContentModel> { + val currentUserIds = userTracker.userProfiles.map { it.id }.toSet() + return list.filter { widget -> + currentUserIds.contains(widget.providerInfo.profile?.identifier) + } + } + companion object { /** * The user activity timeout which should be used when the communal hub is opened. A value diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt index 25dfc02a5d98..2b7db148582d 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt @@ -17,7 +17,6 @@ package com.android.systemui.communal.domain.interactor import android.provider.Settings -import com.android.systemui.communal.data.repository.CommunalRepository import com.android.systemui.communal.data.repository.CommunalTutorialRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -51,7 +50,6 @@ constructor( @Application private val scope: CoroutineScope, private val communalTutorialRepository: CommunalTutorialRepository, keyguardInteractor: KeyguardInteractor, - private val communalRepository: CommunalRepository, private val communalSettingsInteractor: CommunalSettingsInteractor, communalInteractor: CommunalInteractor, @CommunalTableLog tableLogBuffer: TableLogBuffer, @@ -92,7 +90,7 @@ constructor( if (tutorialSettingState == Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED) { return@flatMapLatest flowOf(null) } - communalRepository.isCommunalHubShowing.map { isCommunalShowing -> + communalInteractor.isCommunalShowing.map { isCommunalShowing -> nextStateAfterTransition( tutorialSettingState, isCommunalShowing, 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 8a7b5ebedb7a..3ec9a268f80c 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 @@ -34,7 +34,7 @@ abstract class BaseCommunalViewModel( private val communalInteractor: CommunalInteractor, val mediaHost: MediaHost, ) { - val currentScene: StateFlow<CommunalSceneKey> = communalInteractor.desiredScene + val currentScene: Flow<CommunalSceneKey> = communalInteractor.desiredScene /** Whether widgets are currently being re-ordered. */ open val reorderingWidgets: StateFlow<Boolean> = MutableStateFlow(false) diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt index 4ddd7681dd98..8390d62b23db 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt @@ -18,11 +18,14 @@ package com.android.systemui.communal.widgets import com.android.systemui.CoreStartable import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.settings.UserTracker import com.android.systemui.util.kotlin.BooleanFlowOperators.or import com.android.systemui.util.kotlin.pairwise +import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -37,6 +40,7 @@ class CommunalAppWidgetHostStartable constructor( private val appWidgetHost: CommunalAppWidgetHost, private val communalInteractor: CommunalInteractor, + private val userTracker: UserTracker, @Background private val bgScope: CoroutineScope, @Main private val uiDispatcher: CoroutineDispatcher ) : CoreStartable { @@ -47,6 +51,14 @@ constructor( .pairwise(false) .filter { (previous, new) -> previous != new } .onEach { (_, shouldListen) -> updateAppWidgetHostActive(shouldListen) } + .sample(communalInteractor.communalWidgets, ::Pair) + .onEach { (withPrev, widgets) -> + val (_, isActive) = withPrev + // The validation is performed once the hub becomes active. + if (isActive) { + validateWidgetsAndDeleteOrphaned(widgets) + } + } .launchIn(bgScope) appWidgetHost.appWidgetIdToRemove @@ -63,4 +75,15 @@ constructor( appWidgetHost.stopListening() } } + + /** + * Ensure the existence of all associated users for widgets, and remove widgets belonging to + * users who have been deleted. + */ + private fun validateWidgetsAndDeleteOrphaned(widgets: List<CommunalWidgetContentModel>) { + val currentUserIds = userTracker.userProfiles.map { it.id }.toSet() + widgets + .filter { widget -> !currentUserIds.contains(widget.providerInfo.profile?.identifier) } + .onEach { widget -> communalInteractor.deleteWidget(id = widget.appWidgetId) } + } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index 0f038e10dd4e..bc07b95c5d7f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -36,6 +36,7 @@ import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.controls.settings.ControlsSettingsRepository import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.VibratorHelper @@ -47,16 +48,16 @@ import javax.inject.Inject @SysUISingleton class ControlActionCoordinatorImpl @Inject constructor( - private val context: Context, - private val bgExecutor: DelayableExecutor, - @Main private val uiExecutor: DelayableExecutor, - private val activityStarter: ActivityStarter, - private val broadcastSender: BroadcastSender, - private val keyguardStateController: KeyguardStateController, - private val taskViewFactory: Optional<TaskViewFactory>, - private val controlsMetricsLogger: ControlsMetricsLogger, - private val vibrator: VibratorHelper, - private val controlsSettingsRepository: ControlsSettingsRepository, + private val context: Context, + @Background private val bgExecutor: DelayableExecutor, + @Main private val uiExecutor: DelayableExecutor, + private val activityStarter: ActivityStarter, + private val broadcastSender: BroadcastSender, + private val keyguardStateController: KeyguardStateController, + private val taskViewFactory: Optional<TaskViewFactory>, + private val controlsMetricsLogger: ControlsMetricsLogger, + private val vibrator: VibratorHelper, + private val controlsSettingsRepository: ControlsSettingsRepository, ) : ControlActionCoordinator { private var dialog: Dialog? = null private var pendingAction: Action? = null diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index e8931770b15e..1157d97f2f2e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -126,6 +126,7 @@ import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.PolicyModule; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.dagger.SmartRepliesInflationModule; import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule; @@ -358,6 +359,7 @@ public abstract class SystemUIModule { VisualInterruptionDecisionProvider visualInterruptionDecisionProvider, ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, + SensitiveNotificationProtectionController sensitiveNotificationProtectionController, CommonNotifCollection notifCollection, NotifPipeline notifPipeline, SysUiState sysUiState, @@ -376,6 +378,7 @@ public abstract class SystemUIModule { visualInterruptionDecisionProvider, zenModeController, notifUserManager, + sensitiveNotificationProtectionController, notifCollection, notifPipeline, sysUiState, diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt index cf91e147d1b3..0c9fbc27cc5d 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt @@ -189,6 +189,18 @@ constructor( } } .launchIn(applicationScope) + + facePropertyRepository.cameraInfo + .onEach { + if (it != null && isRunning()) { + repository.cancel() + runFaceAuth( + FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED, + fallbackToDetect = true + ) + } + } + .launchIn(applicationScope) } private suspend fun resetLockedOutState(currentUserId: Int) { diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt index ee220d5fb713..08a6166fe557 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt @@ -31,6 +31,7 @@ import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ALTERNATE import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ASSISTANT_VISIBILITY_CHANGED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.AUTH_REQUEST_DURING_CANCELLATION import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.BIOMETRIC_ENABLED +import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.CAMERA_AVAILABLE_CHANGED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.CAMERA_LAUNCHED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DEVICE_WOKEN_UP_ON_REACH_GESTURE import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DISPLAY_OFF @@ -130,6 +131,7 @@ private object InternalFaceAuthReasons { "Face auth stopped because non strong biometric allowed changed" const val POSTURE_CHANGED = "Face auth started/stopped due to device posture changed." const val DISPLAY_OFF = "Face auth stopped due to display state OFF." + const val CAMERA_AVAILABLE_CHANGED = "Face auth started due to the available camera changed" } /** @@ -221,7 +223,9 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) : @UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED) FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED), @UiEvent(doc = ACCESSIBILITY_ACTION) FACE_AUTH_ACCESSIBILITY_ACTION(1454, ACCESSIBILITY_ACTION), - @UiEvent(doc = DISPLAY_OFF) FACE_AUTH_DISPLAY_OFF(1461, DISPLAY_OFF); + @UiEvent(doc = DISPLAY_OFF) FACE_AUTH_DISPLAY_OFF(1461, DISPLAY_OFF), + @UiEvent(doc = CAMERA_AVAILABLE_CHANGED) + FACE_AUTH_CAMERA_AVAILABLE_CHANGED(1623, CAMERA_AVAILABLE_CHANGED); override fun getId(): Int = this.id diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt index 9000da33312c..b97bace9584f 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt @@ -40,7 +40,6 @@ import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.DreamLog import com.android.systemui.statusbar.BlurUtils import com.android.systemui.statusbar.CrossFadeHelper -import com.android.systemui.statusbar.policy.ConfigurationController import javax.inject.Inject import javax.inject.Named import kotlinx.coroutines.launch @@ -55,7 +54,6 @@ constructor( private val mOverlayStateController: DreamOverlayStateController, @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, private val dreamOverlayViewModel: DreamOverlayViewModel, - private val configController: ConfigurationController, @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) private val mDreamInBlurAnimDurationMs: Long, @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt index dd67a4c8706c..bd99f4b8230e 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt @@ -20,6 +20,7 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -33,16 +34,16 @@ class DreamOverlayViewModel @Inject constructor( configurationInteractor: ConfigurationInteractor, - private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, + toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, + fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, ) { val dreamOverlayTranslationX: Flow<Float> = - configurationInteractor - .dimensionPixelSize(R.dimen.dream_overlay_exit_x_offset) - .flatMapLatest { px: Int -> - toGlanceableHubTransitionViewModel.dreamOverlayTranslationX(px) - } + merge( + toGlanceableHubTransitionViewModel.dreamOverlayTranslationX, + fromGlanceableHubTransitionInteractor.dreamOverlayTranslationX, + ) val dreamOverlayTranslationY: Flow<Float> = configurationInteractor @@ -55,6 +56,7 @@ constructor( merge( toLockscreenTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamOverlayAlpha, + fromGlanceableHubTransitionInteractor.dreamOverlayAlpha, ) val transitionEnded = toLockscreenTransitionViewModel.transitionEnded diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt index e35c5a636bde..301942f6242b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt @@ -170,7 +170,6 @@ constructor( KeyguardIndicationAreaBinder.bind( notificationShadeWindowView.requireViewById(R.id.keyguard_indication_area), keyguardIndicationAreaViewModel, - aodAlphaViewModel, indicationController, ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index c6b99528b2ba..6d917bbde82b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -40,6 +40,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.Flags.notifyPowerManagerUserActivityBackground; import static com.android.systemui.Flags.refactorGetCurrentUser; import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; @@ -1488,7 +1489,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } public void userActivity() { - mPM.userActivity(mSystemClock.uptimeMillis(), false); + if (notifyPowerManagerUserActivityBackground()) { + mUiBgExecutor.execute(() -> mPM.userActivity(mSystemClock.uptimeMillis(), false)); + } else { + mPM.userActivity(mSystemClock.uptimeMillis(), false); + } } private void setupLocked() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt index b152eea63028..2bede977c958 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.shareIn @@ -177,92 +178,99 @@ constructor( // TODO(b/322555228) Remove after consolidating device entry auth messages with BP auth messages // in BiometricStatusRepository + /** + * FingerprintAuthenticationStatus Multiple statuses may arrive in immediate sequence (ie: + * acquired, failed, help, error), so we use a buffer to ensure consumers receive each distinct + * status. + */ override val authenticationStatus: Flow<FingerprintAuthenticationStatus> - get() = conflatedCallbackFlow { - val callback = - object : KeyguardUpdateMonitorCallback() { - override fun onBiometricAuthenticated( - userId: Int, - biometricSourceType: BiometricSourceType, - isStrongBiometric: Boolean, - ) { - sendUpdateIfFingerprint( - biometricSourceType, - SuccessFingerprintAuthenticationStatus( - userId, - isStrongBiometric, - ), - ) - } + get() = + conflatedCallbackFlow { + val callback = + object : KeyguardUpdateMonitorCallback() { + override fun onBiometricAuthenticated( + userId: Int, + biometricSourceType: BiometricSourceType, + isStrongBiometric: Boolean, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + SuccessFingerprintAuthenticationStatus( + userId, + isStrongBiometric, + ), + ) + } - override fun onBiometricError( - msgId: Int, - errString: String?, - biometricSourceType: BiometricSourceType, - ) { - sendUpdateIfFingerprint( - biometricSourceType, - ErrorFingerprintAuthenticationStatus( - msgId, - errString, - ), - ) - } + override fun onBiometricError( + msgId: Int, + errString: String?, + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + ErrorFingerprintAuthenticationStatus( + msgId, + errString, + ), + ) + } - override fun onBiometricHelp( - msgId: Int, - helpString: String?, - biometricSourceType: BiometricSourceType, - ) { - sendUpdateIfFingerprint( - biometricSourceType, - HelpFingerprintAuthenticationStatus( - msgId, - helpString, - ), - ) - } + override fun onBiometricHelp( + msgId: Int, + helpString: String?, + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + HelpFingerprintAuthenticationStatus( + msgId, + helpString, + ), + ) + } - override fun onBiometricAuthFailed( - biometricSourceType: BiometricSourceType, - ) { - sendUpdateIfFingerprint( - biometricSourceType, - FailFingerprintAuthenticationStatus, - ) - } + override fun onBiometricAuthFailed( + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + FailFingerprintAuthenticationStatus, + ) + } - override fun onBiometricAcquired( - biometricSourceType: BiometricSourceType, - acquireInfo: Int, - ) { - sendUpdateIfFingerprint( - biometricSourceType, - AcquiredFingerprintAuthenticationStatus( - AuthenticationReason.DeviceEntryAuthentication, - acquireInfo - ), - ) - } + override fun onBiometricAcquired( + biometricSourceType: BiometricSourceType, + acquireInfo: Int, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + AcquiredFingerprintAuthenticationStatus( + AuthenticationReason.DeviceEntryAuthentication, + acquireInfo + ), + ) + } - private fun sendUpdateIfFingerprint( - biometricSourceType: BiometricSourceType, - authenticationStatus: FingerprintAuthenticationStatus - ) { - if (biometricSourceType != BiometricSourceType.FINGERPRINT) { - return - } + private fun sendUpdateIfFingerprint( + biometricSourceType: BiometricSourceType, + authenticationStatus: FingerprintAuthenticationStatus + ) { + if (biometricSourceType != BiometricSourceType.FINGERPRINT) { + return + } - trySendWithFailureLogging( - authenticationStatus, - TAG, - "new fingerprint authentication status" - ) - } + trySendWithFailureLogging( + authenticationStatus, + TAG, + "new fingerprint authentication status" + ) + } + } + keyguardUpdateMonitor.registerCallback(callback) + awaitClose { keyguardUpdateMonitor.removeCallback(callback) } } - keyguardUpdateMonitor.registerCallback(callback) - awaitClose { keyguardUpdateMonitor.removeCallback(callback) } - } + .buffer(capacity = 4) override val shouldUpdateIndicatorVisibility: Flow<Boolean> = conflatedCallbackFlow { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt index 0cf74a1ff32e..9fc36923b04d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -156,5 +156,6 @@ constructor( val TO_GONE_DURATION = 500.milliseconds val TO_AOD_DURATION = TRANSITION_DURATION_MS val TO_PRIMARY_BOUNCER_DURATION = TRANSITION_DURATION_MS + val TO_DOZING_DURATION = TRANSITION_DURATION_MS } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index e2a8b6c53daa..54d5908e9fa4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -115,5 +115,7 @@ constructor( const val TAG = "FromDozingTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION + val TO_GONE_DURATION = DEFAULT_DURATION + val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index c6594ef317d6..acfa107cc1f1 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.communalHub import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -64,12 +65,13 @@ constructor( private fun listenForDreamingToGlanceableHub() { if (!communalHub()) return - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForDreamingToGlanceableHub", - transitionOwnerName = TAG, - fromState = KeyguardState.DREAMING, - toState = KeyguardState.GLANCEABLE_HUB, - ) + scope.launch("$TAG#listenForDreamingToGlanceableHub", mainDispatcher) { + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.DREAMING, + toState = KeyguardState.GLANCEABLE_HUB, + ) + } } fun startToLockscreenTransition() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index fbf195eb0952..786c3c6697d9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -27,13 +27,16 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled import com.android.systemui.power.domain.interactor.PowerInteractor -import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleMultiple +import com.android.systemui.util.kotlin.BooleanFlowOperators.and +import com.android.systemui.util.kotlin.BooleanFlowOperators.not import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @SysUISingleton class FromGlanceableHubTransitionInteractor @@ -58,13 +61,12 @@ constructor( if (!Flags.communalHub()) { return } - listenForHubToLockscreen() + listenForHubToLockscreenOrDreaming() listenForHubToDozing() listenForHubToPrimaryBouncer() listenForHubToAlternateBouncer() listenForHubToOccluded() listenForHubToGone() - listenForHubToDreaming() } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { @@ -82,13 +84,24 @@ constructor( * Listens for the glanceable hub transition to lock screen and directly drives the keyguard * transition. */ - private fun listenForHubToLockscreen() { - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForHubToLockscreen", - transitionOwnerName = TAG, - fromState = KeyguardState.GLANCEABLE_HUB, - toState = KeyguardState.LOCKSCREEN, - ) + private fun listenForHubToLockscreenOrDreaming() { + scope.launch("$TAG#listenForGlanceableHubToLockscreenOrDream") { + keyguardInteractor.isDreaming.collectLatest { dreaming -> + withContext(mainDispatcher) { + val toState = + if (dreaming) { + KeyguardState.DREAMING + } else { + KeyguardState.LOCKSCREEN + } + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.GLANCEABLE_HUB, + toState = toState, + ) + } + } + } } private fun listenForHubToPrimaryBouncer() { @@ -137,31 +150,15 @@ constructor( } } - private fun listenForHubToDreaming() { - val invalidFromStates = setOf(KeyguardState.AOD, KeyguardState.DOZING) - scope.launch("$TAG#listenForHubToDreaming") { - keyguardInteractor.isAbleToDream - .sampleMultiple(startedKeyguardTransitionStep, finishedKeyguardState) - .collect { (isAbleToDream, lastStartedTransition, finishedKeyguardState) -> - val isOnHub = finishedKeyguardState == KeyguardState.GLANCEABLE_HUB - val isTransitionInterruptible = - lastStartedTransition.to == KeyguardState.GLANCEABLE_HUB && - !invalidFromStates.contains(lastStartedTransition.from) - if (isAbleToDream && (isOnHub || isTransitionInterruptible)) { - startTransitionTo(KeyguardState.DREAMING) - } - } - } - } - private fun listenForHubToOccluded() { scope.launch { - keyguardInteractor.isKeyguardOccluded.sample(startedKeyguardState, ::Pair).collect { - (isOccluded, keyguardState) -> - if (isOccluded && keyguardState == fromState) { - startTransitionTo(KeyguardState.OCCLUDED) + and(keyguardInteractor.isKeyguardOccluded, not(keyguardInteractor.isDreaming)) + .sample(startedKeyguardState, ::Pair) + .collect { (isOccludedAndNotDreaming, keyguardState) -> + if (isOccludedAndNotDreaming && keyguardState == fromState) { + startTransitionTo(KeyguardState.OCCLUDED) + } } - } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index 40b2c638823d..7263ae96b3a8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -360,13 +360,13 @@ constructor( if (!com.android.systemui.Flags.communalHub()) { return } - - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForLockscreenToGlanceableHub", - transitionOwnerName = TAG, - fromState = KeyguardState.LOCKSCREEN, - toState = KeyguardState.GLANCEABLE_HUB, - ) + scope.launch(mainDispatcher) { + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.LOCKSCREEN, + toState = KeyguardState.GLANCEABLE_HUB, + ) + } } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index acbd9fb4c407..c5a28463bf7e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -134,8 +134,9 @@ constructor( powerInteractor.isAwake, startedKeyguardTransitionStep, keyguardInteractor.isKeyguardOccluded, + keyguardInteractor.isDreaming, keyguardInteractor.isActiveDreamLockscreenHosted, - communalInteractor.isIdleOnCommunal + communalInteractor.isIdleOnCommunal, ) .collect { ( @@ -143,6 +144,7 @@ constructor( isAwake, lastStartedTransitionStep, occluded, + isDreaming, isActiveDreamLockscreenHosted, isIdleOnCommunal) -> if ( @@ -152,10 +154,12 @@ constructor( !isActiveDreamLockscreenHosted ) { val toState = - if (occluded) { + if (occluded && !isDreaming) { KeyguardState.OCCLUDED } else if (isIdleOnCommunal) { KeyguardState.GLANCEABLE_HUB + } else if (isDreaming) { + KeyguardState.DREAMING } else { KeyguardState.LOCKSCREEN } @@ -270,5 +274,6 @@ constructor( val TO_GONE_SHORT_DURATION = 200.milliseconds val TO_AOD_DURATION = DEFAULT_DURATION val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION + val TO_DOZING_DURATION = DEFAULT_DURATION } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt index 809c0aee9882..6cb1eb493db3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt @@ -18,11 +18,9 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators -import com.android.app.tracing.coroutines.launch import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalTransitionProgress import com.android.systemui.communal.shared.model.CommunalSceneKey -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState @@ -32,13 +30,11 @@ import com.android.systemui.util.kotlin.sample import java.util.UUID import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOn class GlanceableHubTransitions @Inject constructor( - @Application private val scope: CoroutineScope, @Background private val bgDispatcher: CoroutineDispatcher, private val transitionInteractor: KeyguardTransitionInteractor, private val transitionRepository: KeyguardTransitionRepository, @@ -52,105 +48,101 @@ constructor( * externally. The progress is used for both transitions caused by user touch input or by * programmatic changes. */ - fun listenForGlanceableHubTransition( - transitionName: String, + suspend fun listenForGlanceableHubTransition( transitionOwnerName: String, fromState: KeyguardState, toState: KeyguardState, ) { val toScene = - if (toState == KeyguardState.GLANCEABLE_HUB) { - CommunalSceneKey.Communal - } else { + if (fromState == KeyguardState.GLANCEABLE_HUB) { CommunalSceneKey.Blank + } else { + CommunalSceneKey.Communal } var transitionId: UUID? = null - scope.launch("$transitionOwnerName#$transitionName") { - communalInteractor - .transitionProgressToScene(toScene) - .sample( - transitionInteractor.startedKeyguardTransitionStep.flowOn(bgDispatcher), - ::Pair - ) - .collect { pair -> - val (transitionProgress, lastStartedStep) = pair - val id = transitionId - if (id == null) { - // No transition started. - if ( - transitionProgress is CommunalTransitionProgress.Transition && - lastStartedStep.to == fromState - ) { - transitionId = - transitionRepository.startTransition( - TransitionInfo( - ownerName = transitionOwnerName, - from = fromState, - to = toState, - animator = null, // transition will be manually controlled - ) + communalInteractor + .transitionProgressToScene(toScene) + .sample( + transitionInteractor.startedKeyguardTransitionStep.flowOn(bgDispatcher), + ::Pair, + ) + .collect { (transitionProgress, lastStartedStep) -> + val id = transitionId + if (id == null) { + // No transition started. + if ( + transitionProgress is CommunalTransitionProgress.Transition && + lastStartedStep.to == fromState + ) { + transitionId = + transitionRepository.startTransition( + TransitionInfo( + ownerName = transitionOwnerName, + from = fromState, + to = toState, + animator = null, // transition will be manually controlled ) - } - } else { - if (lastStartedStep.to != toState) { - return@collect - } - // An existing `id` means a transition is started, and calls to - // `updateTransition` will control it until FINISHED or CANCELED - val nextState: TransitionState - val progressFraction: Float - when (transitionProgress) { - is CommunalTransitionProgress.Idle -> { - if (transitionProgress.scene == toScene) { - nextState = TransitionState.FINISHED - progressFraction = 1f - } else { - nextState = TransitionState.CANCELED - progressFraction = 0f - } - } - is CommunalTransitionProgress.Transition -> { - nextState = TransitionState.RUNNING - progressFraction = transitionProgress.progress - } - is CommunalTransitionProgress.OtherTransition -> { - // Shouldn't happen but if another transition starts during the - // current one, mark the current one as canceled. + ) + } + } else { + if (lastStartedStep.to != toState) { + return@collect + } + // An existing `id` means a transition is started, and calls to + // `updateTransition` will control it until FINISHED or CANCELED + val nextState: TransitionState + val progressFraction: Float + when (transitionProgress) { + is CommunalTransitionProgress.Idle -> { + if (transitionProgress.scene == toScene) { + nextState = TransitionState.FINISHED + progressFraction = 1f + } else { nextState = TransitionState.CANCELED progressFraction = 0f } } - transitionRepository.updateTransition( - id, - progressFraction, - nextState, - ) - - if ( - nextState == TransitionState.CANCELED || - nextState == TransitionState.FINISHED - ) { - transitionId = null + is CommunalTransitionProgress.Transition -> { + nextState = TransitionState.RUNNING + progressFraction = transitionProgress.progress } + is CommunalTransitionProgress.OtherTransition -> { + // Shouldn't happen but if another transition starts during the + // current one, mark the current one as canceled. + nextState = TransitionState.CANCELED + progressFraction = 0f + } + } + transitionRepository.updateTransition( + id, + progressFraction, + nextState, + ) - // If canceled, just put the state back. - if (nextState == TransitionState.CANCELED) { - transitionRepository.startTransition( - TransitionInfo( - ownerName = transitionOwnerName, - from = toState, - to = fromState, - animator = - ValueAnimator().apply { - interpolator = Interpolators.LINEAR - duration = 0 - } - ) + if ( + nextState == TransitionState.CANCELED || + nextState == TransitionState.FINISHED + ) { + transitionId = null + } + + // If canceled, just put the state back. + if (nextState == TransitionState.CANCELED) { + transitionRepository.startTransition( + TransitionInfo( + ownerName = transitionOwnerName, + from = toState, + to = fromState, + animator = + ValueAnimator().apply { + interpolator = Interpolators.LINEAR + duration = 0 + } ) - } + ) } } - } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt index 56d64a298bc0..bc3f0cce2fc7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt @@ -15,12 +15,15 @@ * */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.keyguard.domain.interactor import android.content.Context import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository +import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint @@ -29,7 +32,9 @@ import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.Intra import com.android.systemui.statusbar.policy.SplitShadeStateController import javax.inject.Inject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch @@ -41,6 +46,7 @@ constructor( @Application private val applicationScope: CoroutineScope, private val context: Context, private val splitShadeStateController: SplitShadeStateController, + private val clockInteractor: KeyguardClockInteractor, ) { /** The current blueprint for the lockscreen. */ @@ -58,6 +64,7 @@ constructor( .onStart { emit(Unit) } .collect { updateBlueprint() } } + applicationScope.launch { clockInteractor.currentClock.collect { updateBlueprint() } } } /** @@ -67,12 +74,17 @@ constructor( private fun updateBlueprint() { val useSplitShade = splitShadeStateController.shouldUseSplitNotificationShade(context.resources) + // TODO(b/326098079): Make ID a constant value. + val useWeatherClockLayout = + clockInteractor.currentClock.value?.config?.id == "DIGITAL_CLOCK_WEATHER" && + ComposeLockscreen.isEnabled val blueprintId = - if (useSplitShade) { - SplitShadeKeyguardBlueprint.ID - } else { - DefaultKeyguardBlueprint.DEFAULT + when { + useWeatherClockLayout && useSplitShade -> SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID + useWeatherClockLayout -> WEATHER_CLOCK_BLUEPRINT_ID + useSplitShade -> SplitShadeKeyguardBlueprint.ID + else -> DefaultKeyguardBlueprint.DEFAULT } transitionToBlueprint(blueprintId) @@ -107,4 +119,13 @@ constructor( fun getCurrentBlueprint(): KeyguardBlueprint { return keyguardBlueprintRepository.blueprint.value } + + companion object { + /** + * These values live here because classes in the composable package do not exist in some + * systems. + */ + const val WEATHER_CLOCK_BLUEPRINT_ID = "weather-clock" + const val SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID = "split-shade-weather-clock" + } } 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 7c1368af652c..841f52d7aa64 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,7 +23,7 @@ import android.widget.TextView import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.Flags.keyguardBottomAreaRefactor -import com.android.systemui.keyguard.ui.viewmodel.AodAlphaViewModel +import com.android.systemui.Flags.migrateClocksToBlueprint import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R @@ -51,7 +51,6 @@ object KeyguardIndicationAreaBinder { fun bind( view: ViewGroup, viewModel: KeyguardIndicationAreaViewModel, - aodAlphaViewModel: AodAlphaViewModel, indicationController: KeyguardIndicationController, ): DisposableHandle { indicationController.setIndicationArea(view) @@ -68,30 +67,10 @@ object KeyguardIndicationAreaBinder { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { launch { - if (keyguardBottomAreaRefactor()) { - aodAlphaViewModel.alpha.collect { alpha -> - view.apply { - this.importantForAccessibility = - if (alpha == 0f) { - View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - } else { - View.IMPORTANT_FOR_ACCESSIBILITY_AUTO - } - this.alpha = alpha - } - } - } else { - viewModel.alpha.collect { alpha -> - view.apply { - this.importantForAccessibility = - if (alpha == 0f) { - View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - } else { - View.IMPORTANT_FOR_ACCESSIBILITY_AUTO - } - this.alpha = alpha - } - } + // Do not independently apply alpha, as [KeyguardRootViewModel] should work + // for this and all its children + if (!(migrateClocksToBlueprint() || keyguardBottomAreaRefactor())) { + viewModel.alpha.collect { alpha -> view.alpha = alpha } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt index 951df5aeb65c..1abf4a6e2f1c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt @@ -16,15 +16,20 @@ package com.android.systemui.keyguard.ui.transitions import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToDozingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.DozingToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DozingToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.DozingToPrimaryBouncerTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GoneToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.GoneToDozingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GoneToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDozingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel @@ -32,6 +37,7 @@ import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTran import com.android.systemui.keyguard.ui.viewmodel.OccludedToAodTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToDozingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel import dagger.Binds import dagger.Module @@ -49,6 +55,12 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun alternateBouncerToDozing( + impl: AlternateBouncerToDozingTransitionViewModel + ): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun alternateBouncerToGone( impl: AlternateBouncerToGoneTransitionViewModel ): DeviceEntryIconTransition @@ -71,12 +83,22 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun dozingToGone(impl: DozingToGoneTransitionViewModel): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun dozingToLockscreen( impl: DozingToLockscreenTransitionViewModel ): DeviceEntryIconTransition @Binds @IntoSet + abstract fun dozingToPrimaryBouncer( + impl: DozingToPrimaryBouncerTransitionViewModel + ): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun dreamingToLockscreen( impl: DreamingToLockscreenTransitionViewModel ): DeviceEntryIconTransition @@ -89,6 +111,12 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun lockscreenToDozing( + impl: LockscreenToDozingTransitionViewModel + ): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun lockscreenToDreaming( impl: LockscreenToDreamingTransitionViewModel ): DeviceEntryIconTransition @@ -123,6 +151,10 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun goneToDozing(impl: GoneToDozingTransitionViewModel): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun occludedToAod(impl: OccludedToAodTransitionViewModel): DeviceEntryIconTransition @Binds @@ -139,6 +171,12 @@ abstract class DeviceEntryIconTransitionModule { @Binds @IntoSet + abstract fun primaryBouncerToDozing( + impl: PrimaryBouncerToDozingTransitionViewModel + ): DeviceEntryIconTransition + + @Binds + @IntoSet abstract fun primaryBouncerToLockscreen( impl: PrimaryBouncerToLockscreenTransitionViewModel ): DeviceEntryIconTransition diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt index 78099d9f5d90..a53c6d77d328 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt @@ -50,6 +50,15 @@ class KeyguardIndicationArea( ) } + override fun setAlpha(alpha: Float) { + super.setAlpha(alpha) + + if (alpha == 0f) { + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS + } else { + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO + } + } private fun indicationTopRow(): KeyguardIndicationTextView { return KeyguardIndicationTextView(context, attrs).apply { id = R.id.keyguard_indication_text diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt index 4f1a754adbd5..b4e57cc93962 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt @@ -17,10 +17,13 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints -import com.android.systemui.communal.ui.view.layout.blueprints.DefaultCommunalBlueprint +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID import com.android.systemui.keyguard.shared.model.KeyguardBlueprint +import com.android.systemui.keyguard.shared.model.KeyguardSection import dagger.Binds import dagger.Module +import dagger.Provides import dagger.multibindings.IntoSet @Module @@ -43,9 +46,25 @@ abstract class KeyguardBlueprintModule { shortcutsBesideUdfpsLockscreenBlueprint: ShortcutsBesideUdfpsKeyguardBlueprint ): KeyguardBlueprint - @Binds - @IntoSet - abstract fun bindDefaultCommunalBlueprint( - defaultCommunalBlueprint: DefaultCommunalBlueprint - ): KeyguardBlueprint + companion object { + /** This is a place holder for weather clock in compose. */ + @Provides + @IntoSet + fun bindWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint { + return object : KeyguardBlueprint { + override val id: String = WEATHER_CLOCK_BLUEPRINT_ID + override val sections: List<KeyguardSection> = listOf() + } + } + + /** This is a place holder for weather clock in compose. */ + @Provides + @IntoSet + fun bindSplitShadeWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint { + return object : KeyguardBlueprint { + override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID + override val sections: List<KeyguardSection> = listOf() + } + } + } } 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 ea05c1d878b8..3361343423a9 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 @@ -25,7 +25,6 @@ import com.android.systemui.Flags.keyguardBottomAreaRefactor 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.AodAlphaViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController @@ -37,7 +36,6 @@ class DefaultIndicationAreaSection constructor( private val context: Context, private val keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel, - private val aodAlphaViewModel: AodAlphaViewModel, private val indicationController: KeyguardIndicationController, ) : KeyguardSection() { private val indicationAreaViewId = R.id.keyguard_indication_area @@ -56,7 +54,6 @@ constructor( KeyguardIndicationAreaBinder.bind( constraintLayout.requireViewById(R.id.keyguard_indication_area), keyguardIndicationAreaViewModel, - aodAlphaViewModel, indicationController, ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt index 4bc2d86e6b54..a203c53be01e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt @@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintSet.BOTTOM import androidx.constraintlayout.widget.ConstraintSet.END import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.constraintlayout.widget.ConstraintSet.VISIBILITY_MODE_IGNORE import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT import androidx.core.view.isVisible import com.android.systemui.Flags.keyguardBottomAreaRefactor @@ -103,7 +104,8 @@ constructor( BOTTOM, resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset) ) - setVisibility(R.id.keyguard_settings_button, View.GONE) + // Ignore ConstrainSet's default visibility, and let the view choose + setVisibilityMode(R.id.keyguard_settings_button, VISIBILITY_MODE_IGNORE) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt index d0f57c7f9ded..02c889dd771d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt @@ -111,7 +111,7 @@ constructor( sceneContainerFlags, controller, notificationStackSizeCalculator, - mainDispatcher, + mainImmediateDispatcher = mainDispatcher, ) ) @@ -123,6 +123,7 @@ constructor( notificationStackAppearanceViewModel, ambientState, controller, + mainImmediateDispatcher = mainDispatcher, ) ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt index b4b48a8fb932..4fd92d70fb07 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt @@ -25,7 +25,6 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest /** @@ -60,7 +59,7 @@ constructor( if (udfpsEnrolledAndEnabled) { transitionAnimation.immediatelyTransitionTo(1f) } else { - emptyFlow() + transitionAnimation.immediatelyTransitionTo(0f) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt new file mode 100644 index 000000000000..9649af73eadb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor +import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest + +/** + * Breaks down ALTERNATE BOUNCER->DOZING transition into discrete steps for corresponding views to + * consume. + */ +@ExperimentalCoroutinesApi +@SysUISingleton +class AlternateBouncerToDozingTransitionViewModel +@Inject +constructor( + deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, + animationFlow: KeyguardTransitionAnimationFlow, +) : DeviceEntryIconTransition { + private val transitionAnimation = + animationFlow.setup( + duration = FromAlternateBouncerTransitionInteractor.TO_DOZING_DURATION, + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.DOZING, + ) + + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) + + override val deviceEntryParentViewAlpha: Flow<Float> = + deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { udfpsEnrolledAndEnabled + -> + if (udfpsEnrolledAndEnabled) { + transitionAnimation.immediatelyTransitionTo(1f) + } else { + transitionAnimation.immediatelyTransitionTo(0f) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt index 302ba7226e77..662a77ee7193 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt @@ -46,6 +46,11 @@ constructor( dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, alternateBouncerToAodTransitionViewModel: AlternateBouncerToAodTransitionViewModel, goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel, + goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel, + primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel, + lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel, + dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel, + alternateBouncerToDozingTransitionViewModel: AlternateBouncerToDozingTransitionViewModel, ) { val color: Flow<Int> = deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground -> @@ -82,6 +87,11 @@ constructor( dreamingToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha, alternateBouncerToAodTransitionViewModel.deviceEntryBackgroundViewAlpha, goneToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha, + goneToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, + primaryBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, + lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, + dozingToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha, + alternateBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, ) .merge() } else { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt index ad6a36c71e39..d657c24d7ae0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt @@ -48,9 +48,9 @@ constructor( deviceEntryIconViewModel: DeviceEntryIconViewModel, udfpsOverlayInteractor: UdfpsOverlayInteractor, ) { - private val isShowingAod: Flow<Boolean> = + private val isShowingAodOrDozing: Flow<Boolean> = transitionInteractor.startedKeyguardState.map { keyguardState -> - keyguardState == KeyguardState.AOD + keyguardState == KeyguardState.AOD || keyguardState == KeyguardState.DOZING } private fun getColor(usingBackgroundProtection: Boolean): Int { @@ -68,11 +68,12 @@ constructor( .onStart { emit(getColor(useBgProtection)) } } + // While dozing, the display can show the AOD UI; show the AOD udfps when dozing private val useAodIconVariant: Flow<Boolean> = - combine(isShowingAod, deviceEntryUdfpsInteractor.isUdfpsSupported) { - isTransitionToAod, + combine(isShowingAodOrDozing, deviceEntryUdfpsInteractor.isUdfpsSupported) { + isTransitionToAodOrDozing, isUdfps -> - isTransitionToAod && isUdfps + isTransitionToAodOrDozing && isUdfps } .distinctUntilChanged() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt new file mode 100644 index 000000000000..fca1604946e1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromDozingTransitionInteractor.Companion.TO_GONE_DURATION +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow + +/** Breaks down DOZING->GONE transition into discrete steps for corresponding views to consume. */ +@ExperimentalCoroutinesApi +@SysUISingleton +class DozingToGoneTransitionViewModel +@Inject +constructor( + animationFlow: KeyguardTransitionAnimationFlow, +) : DeviceEntryIconTransition { + + private val transitionAnimation = + animationFlow.setup( + duration = TO_GONE_DURATION, + from = KeyguardState.DOZING, + to = KeyguardState.GONE, + ) + + override val deviceEntryParentViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) +} 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 f81941bf064b..168d6e16daa2 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 @@ -52,6 +52,9 @@ constructor( val lockscreenAlpha: Flow<Float> = shortcutsAlpha + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(1f) + override val deviceEntryParentViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt new file mode 100644 index 000000000000..4395c3436a71 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromDozingTransitionInteractor.Companion.TO_PRIMARY_BOUNCER_DURATION +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow + +/** + * Breaks down DOZING->PRIMARY BOUNCER transition into discrete steps for corresponding views to + * consume. + */ +@ExperimentalCoroutinesApi +@SysUISingleton +class DozingToPrimaryBouncerTransitionViewModel +@Inject +constructor( + animationFlow: KeyguardTransitionAnimationFlow, +) : DeviceEntryIconTransition { + + private val transitionAnimation = + animationFlow.setup( + duration = TO_PRIMARY_BOUNCER_DURATION, + from = KeyguardState.DOZING, + to = KeyguardState.PRIMARY_BOUNCER, + ) + + override val deviceEntryParentViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt index 374a93275ff2..c64f277b519a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt @@ -17,18 +17,26 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.app.animation.Interpolators.EMPHASIZED +import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.res.R import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class DreamingToGlanceableHubTransitionViewModel @Inject -constructor(animationFlow: KeyguardTransitionAnimationFlow) { +constructor( + animationFlow: KeyguardTransitionAnimationFlow, + configurationInteractor: ConfigurationInteractor, +) { private val transitionAnimation = animationFlow.setup( @@ -37,14 +45,18 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow) { to = KeyguardState.GLANCEABLE_HUB, ) - fun dreamOverlayTranslationX(translatePx: Int): Flow<Float> { - return transitionAnimation.sharedFlow( - duration = TO_GLANCEABLE_HUB_DURATION, - onStep = { it * -translatePx }, - interpolator = EMPHASIZED, - name = "DREAMING->GLANCEABLE_HUB: overlayTranslationX", - ) - } + val dreamOverlayTranslationX: Flow<Float> = + configurationInteractor + .dimensionPixelSize(R.dimen.dreaming_to_hub_transition_dream_overlay_translation_x) + .flatMapLatest { translatePx -> + transitionAnimation.sharedFlow( + duration = TO_GLANCEABLE_HUB_DURATION, + onStep = { value -> value * translatePx }, + interpolator = EMPHASIZED, + onCancel = { 0f }, + name = "DREAMING->GLANCEABLE_HUB: overlayTranslationX", + ) + } val dreamOverlayAlpha: Flow<Float> = transitionAnimation.sharedFlow( 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 3802d5de5811..d3277cd295ac 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 @@ -18,7 +18,6 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.app.animation.Interpolators.EMPHASIZED import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor @@ -43,7 +42,6 @@ class DreamingToLockscreenTransitionViewModel constructor( keyguardTransitionInteractor: KeyguardTransitionInteractor, private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor, - private val deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, animationFlow: KeyguardTransitionAnimationFlow, ) : DeviceEntryIconTransition { fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt new file mode 100644 index 000000000000..478c4faa1be3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.app.animation.Interpolators +import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.res.R +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest + +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton +class GlanceableHubToDreamingTransitionViewModel +@Inject +constructor( + animationFlow: KeyguardTransitionAnimationFlow, + configurationInteractor: ConfigurationInteractor, +) { + + private val transitionAnimation = + animationFlow.setup( + duration = FROM_GLANCEABLE_HUB_DURATION, + from = KeyguardState.GLANCEABLE_HUB, + to = KeyguardState.DREAMING, + ) + + val dreamOverlayAlpha: Flow<Float> = + transitionAnimation.sharedFlow( + duration = 167.milliseconds, + startTime = 167.milliseconds, + onStep = { it }, + name = "GLANCEABLE_HUB->DREAMING: dreamOverlayAlpha", + ) + + val dreamOverlayTranslationX: Flow<Float> = + configurationInteractor + .dimensionPixelSize(R.dimen.hub_to_dreaming_transition_dream_overlay_translation_x) + .flatMapLatest { translatePx: Int -> + transitionAnimation.sharedFlow( + duration = FROM_GLANCEABLE_HUB_DURATION, + onStep = { value -> -translatePx + value * translatePx }, + interpolator = Interpolators.EMPHASIZED, + onCancel = { -translatePx.toFloat() }, + name = "GLANCEABLE_HUB->LOCKSCREEN: dreamOverlayTranslationX" + ) + } + + private companion object { + val FROM_GLANCEABLE_HUB_DURATION = 1.seconds + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt index 55a289ef890f..80a6bda65b99 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt @@ -17,13 +17,17 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DOZING_DURATION import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest /** Breaks down GONE->DOZING transition into discrete steps for corresponding views to consume. */ @ExperimentalCoroutinesApi @@ -31,8 +35,9 @@ import kotlinx.coroutines.flow.Flow class GoneToDozingTransitionViewModel @Inject constructor( + deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, animationFlow: KeyguardTransitionAnimationFlow, -) { +) : DeviceEntryIconTransition { private val transitionAnimation = animationFlow.setup( @@ -48,4 +53,17 @@ constructor( onCancel = { 1f }, onFinish = { 1f }, ) + + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) + + override val deviceEntryParentViewAlpha: Flow<Float> = + deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { + isUdfpsEnrolledAndEnabled -> + if (isUdfpsEnrolledAndEnabled) { + transitionAnimation.immediatelyTransitionTo(1f) + } else { + emptyFlow() + } + } } 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 4c0cd2f58eb7..b60c52b1c3df 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 @@ -17,19 +17,25 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DOZING_DURATION import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class LockscreenToDozingTransitionViewModel @Inject constructor( + deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, animationFlow: KeyguardTransitionAnimationFlow, -) { +) : DeviceEntryIconTransition { private val transitionAnimation = animationFlow.setup( @@ -45,4 +51,19 @@ constructor( onFinish = { 0f }, onCancel = { 1f }, ) + + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) + + override val deviceEntryParentViewAlpha: Flow<Float> = + deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { + isUdfpsEnrolledAndEnabled -> + transitionAnimation.immediatelyTransitionTo( + if (isUdfpsEnrolledAndEnabled) { + 1f + } else { + 0f + } + ) + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt new file mode 100644 index 000000000000..13f651a9ff5d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor +import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_DOZING_DURATION +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest + +/** + * Breaks down PRIMARY BOUNCER->DOZING transition into discrete steps for corresponding views to + * consume. + */ +@ExperimentalCoroutinesApi +@SysUISingleton +class PrimaryBouncerToDozingTransitionViewModel +@Inject +constructor( + deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, + animationFlow: KeyguardTransitionAnimationFlow, +) : DeviceEntryIconTransition { + + private val transitionAnimation = + animationFlow.setup( + duration = TO_DOZING_DURATION, + from = KeyguardState.PRIMARY_BOUNCER, + to = KeyguardState.DOZING, + ) + + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) + + override val deviceEntryParentViewAlpha: Flow<Float> = + deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { + isUdfpsEnrolledAndEnabled -> + if (isUdfpsEnrolledAndEnabled) { + transitionAnimation.immediatelyTransitionTo(1f) + } else { + emptyFlow() + } + } +} 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 cc3729b5b4d1..8b7c85b65824 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -119,6 +119,16 @@ public class LogModule { return factory.create("LSShadeTransitionLog", 50); } + /** */ + @Provides + @SysUISingleton + @SensitiveNotificationProtectionLog + public static LogBuffer provideSensitiveNotificationProtectionLogBuffer( + LogBufferFactory factory + ) { + return factory.create("SensitiveNotificationProtectionLog", 10); + } + /** Provides a logging buffer for shade window messages. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/SensitiveNotificationProtectionLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/SensitiveNotificationProtectionLog.kt new file mode 100644 index 000000000000..54e87cde4686 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/SensitiveNotificationProtectionLog.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 SensitiveNotificationProtection. */ +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class SensitiveNotificationProtectionLog diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS index 69ea57bfd397..5eb14fc40327 100644 --- a/packages/SystemUI/src/com/android/systemui/media/OWNERS +++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS @@ -1 +1,9 @@ -per-file MediaProjectionPermissionActivity.java = michaelwr@google.com +# Bug component: 78010 + +asc@google.com +ethibodeau@google.com +michaelmikhil@google.com + +# Audio team +per-file RingtonePlayer.java = file:/services/core/java/com/android/server/audio/OWNERS +per-file NotificationPlayer.java = file:/services/core/java/com/android/server/audio/OWNERS diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt index 84a96909fc4a..6fc22ea60a9e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt @@ -583,6 +583,10 @@ class MediaDataManager( } return } + // Update last active if media was still active. + if (it.active) { + it.lastActive = systemClock.elapsedRealtime() + } it.active = !timedOut if (DEBUG) Log.d(TAG, "Updating $key timedOut: $timedOut") onMediaDataLoaded(key, key, it) @@ -1520,6 +1524,12 @@ class MediaDataManager( context.packageManager.getLaunchIntentForPackage(data.packageName)?.let { PendingIntent.getActivity(context, 0, it, PendingIntent.FLAG_IMMUTABLE) } + val lastActive = + if (data.active) { + systemClock.elapsedRealtime() + } else { + data.lastActive + } val updated = data.copy( token = null, @@ -1531,6 +1541,7 @@ class MediaDataManager( isPlaying = false, isClearable = true, clickIntent = launcherIntent, + lastActive = lastActive, ) val pkg = data.packageName val migrate = mediaEntries.put(pkg, updated) == null diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt index 42d68bab49f8..f4d70a5e78c9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt @@ -30,6 +30,8 @@ import androidx.annotation.MainThread import androidx.annotation.WorkerThread import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.settingslib.flags.Flags.enableLeAudioSharing +import com.android.settingslib.flags.Flags.legacyLeAudioSharing import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.media.PhoneMediaDevice @@ -332,14 +334,28 @@ constructor( @WorkerThread private fun updateCurrent() { if (isLeAudioBroadcastEnabled()) { - current = - MediaDeviceData( - /* enabled */ true, - /* icon */ context.getDrawable(R.drawable.settings_input_antenna), - /* name */ broadcastDescription, - /* intent */ null, - /* showBroadcastButton */ showBroadcastButton = true - ) + if (enableLeAudioSharing()) { + current = + MediaDeviceData( + enabled = false, + icon = + context.getDrawable( + com.android.settingslib.R.drawable.ic_bt_le_audio_sharing + ), + name = context.getString(R.string.audio_sharing_description), + intent = null, + showBroadcastButton = false + ) + } else { + current = + MediaDeviceData( + /* enabled */ true, + /* icon */ context.getDrawable(R.drawable.settings_input_antenna), + /* name */ broadcastDescription, + /* intent */ null, + /* showBroadcastButton */ showBroadcastButton = true + ) + } } else { val aboutToConnect = aboutToConnectDeviceOverride if ( @@ -420,6 +436,7 @@ constructor( @WorkerThread private fun isLeAudioBroadcastEnabled(): Boolean { + if (!enableLeAudioSharing() && !legacyLeAudioSharing()) return false val localBluetoothManager = localBluetoothManager.get() if (localBluetoothManager != null) { val profileManager = localBluetoothManager.profileManager diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt index 9206af28eeff..ba7d41008a01 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt @@ -300,10 +300,17 @@ constructor( private fun setVisibility(view: ViewGroup?, newVisibility: Int) { val currentMediaContainer = view ?: return - val previousVisibility = currentMediaContainer.visibility - currentMediaContainer.visibility = newVisibility - if (previousVisibility != newVisibility && currentMediaContainer is MediaContainerView) { - visibilityChangedListener?.invoke(newVisibility == View.VISIBLE) + val isVisible = newVisibility == View.VISIBLE + + if (currentMediaContainer is MediaContainerView) { + val previousVisibility = currentMediaContainer.visibility + + currentMediaContainer.setKeyguardVisibility(isVisible) + if (previousVisibility != newVisibility) { + visibilityChangedListener?.invoke(isVisible) + } + } else { + currentMediaContainer.visibility = newVisibility } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java index e8ad4d325591..840b309aee39 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java @@ -18,7 +18,7 @@ package com.android.systemui.media.controls.ui.controller; import static android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS; -import static com.android.systemui.Flags.legacyLeAudioSharing; +import static com.android.settingslib.flags.Flags.legacyLeAudioSharing; import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS; import android.animation.Animator; @@ -260,7 +260,6 @@ public class MediaControlPanel { private TurbulenceNoiseController mTurbulenceNoiseController; private LoadingEffect mLoadingEffect; private final GlobalSettings mGlobalSettings; - private final Random mRandom = new Random(); private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig; private boolean mWasPlaying = false; private boolean mButtonClicked = false; @@ -1294,13 +1293,14 @@ public class MediaControlPanel { mMediaViewHolder.getTurbulenceNoiseView(); int width = targetView.getWidth(); int height = targetView.getHeight(); + Random random = new Random(); return new TurbulenceNoiseAnimationConfig( /* gridCount= */ 2.14f, TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER, - /* noiseOffsetX= */ mRandom.nextFloat(), - /* noiseOffsetY= */ mRandom.nextFloat(), - /* noiseOffsetZ= */ mRandom.nextFloat(), + /* noiseOffsetX= */ random.nextFloat(), + /* noiseOffsetY= */ random.nextFloat(), + /* noiseOffsetZ= */ random.nextFloat(), /* noiseMoveSpeedX= */ 0.42f, /* noiseMoveSpeedY= */ 0f, TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt index 3b989d935cbd..dbd71f3e3a04 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt @@ -58,6 +58,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.SplitShadeStateController import com.android.systemui.util.animation.UniqueObjectHostView +import com.android.systemui.util.kotlin.BooleanFlowOperators.and import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -583,12 +584,14 @@ constructor( UserHandle.USER_ALL ) - // Listen to the communal UI state. + // Listen to the communal UI state. Make sure that communal UI is showing and hub itself is + // available, ie. not disabled and able to be shown. coroutineScope.launch { - communalInteractor.isCommunalShowing.collect { value -> - isCommunalShowing = value - updateDesiredLocation(forceNoAnimation = true) - } + and(communalInteractor.isCommunalShowing, communalInteractor.isCommunalAvailable) + .collect { value -> + isCommunalShowing = value + updateDesiredLocation() + } } } @@ -1150,12 +1153,16 @@ constructor( when { mediaFlags.isSceneContainerEnabled() -> desiredLocation dreamOverlayActive && dreamMediaComplicationActive -> LOCATION_DREAM_OVERLAY + + // UMO should show in communal unless the shade is expanding or visible. + isCommunalShowing && qsExpansion == 0.0f -> LOCATION_COMMUNAL_HUB (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS qsExpansion > 0.4f && onLockscreen -> LOCATION_QS onLockscreen && isSplitShadeExpanding() -> LOCATION_QS onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS - // TODO(b/311234666): revisit logic once interactions between the hub and - // shade/keyguard state are finalized + + // Communal does not have its own StatusBarState so it should always have higher + // priority for the UMO over the lockscreen. isCommunalShowing -> LOCATION_COMMUNAL_HUB onLockscreen && allowMediaPlayerOnLockScreen -> LOCATION_LOCKSCREEN else -> LOCATION_QQS diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java index 8e0191ec330f..1e317554859c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java @@ -16,6 +16,8 @@ package com.android.systemui.media.dialog; +import static com.android.settingslib.flags.Flags.legacyLeAudioSharing; + import android.app.AlertDialog; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastAssistant; @@ -492,6 +494,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override public boolean isBroadcastSupported() { + if (!legacyLeAudioSharing()) return false; boolean isBluetoothLeDevice = false; if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice( diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index c379d0e68e76..eb6a32023eb7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -16,7 +16,7 @@ package com.android.systemui.media.dialog; -import static com.android.systemui.Flags.legacyLeAudioSharing; +import static com.android.settingslib.flags.Flags.legacyLeAudioSharing; import android.content.Context; import android.os.Bundle; diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt index 1002cc3bd3bb..38d31ed92141 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt @@ -16,6 +16,7 @@ package com.android.systemui.media.dialog +import com.android.settingslib.flags.Flags.legacyLeAudioSharing import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -44,6 +45,7 @@ class MediaOutputDialogReceiver @Inject constructor( mediaOutputDialogFactory.createDialogForSystemRouting() } MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG -> { + if (!legacyLeAudioSharing()) return val packageName: String? = intent.getStringExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME) launchMediaOutputBroadcastDialogIfPossible(packageName) diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS new file mode 100644 index 000000000000..95b8fa74feeb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 1280508 + +# Files in this directory should still be reviewed by a member of SystemUI team diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 416eae1b2d0c..4f062afc2af7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -72,7 +72,7 @@ open class MediaTttChipControllerReceiver @Inject constructor( context: Context, logger: MediaTttReceiverLogger, windowManager: WindowManager, - mainExecutor: DelayableExecutor, + @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, dumpManager: DumpManager, diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionServiceHelper.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionServiceHelper.kt index afe628527833..f1cade7512e2 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionServiceHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionServiceHelper.kt @@ -16,9 +16,6 @@ package com.android.systemui.mediaprojection -import android.compat.annotation.ChangeId -import android.compat.annotation.Disabled -import android.compat.annotation.Overridable import android.content.Context import android.media.projection.IMediaProjection import android.media.projection.IMediaProjectionManager @@ -34,18 +31,6 @@ import android.util.Log */ class MediaProjectionServiceHelper { companion object { - /** - * This change id ensures that users are presented with a choice of capturing a single app - * or the entire screen when initiating a MediaProjection session, overriding the usage of - * MediaProjectionConfig#createConfigForDefaultDisplay. - * - * @hide - */ - @ChangeId - @Overridable - @Disabled - const val OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION = 316897322L // buganizer id - private const val TAG = "MediaProjectionServiceHelper" private val service = IMediaProjectionManager.Stub.asInterface( diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS b/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS new file mode 100644 index 000000000000..bd7407729774 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 1345447 + +include /media/java/android/media/projection/OWNERS +chrisgollner@google.com +nickchameyev@google.com diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java index 0769731bffb1..8b034b293dcb 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java @@ -16,26 +16,21 @@ package com.android.systemui.mediaprojection.permission; -import static android.Manifest.permission.LOG_COMPAT_CHANGE; -import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; import static android.media.projection.IMediaProjectionManager.EXTRA_PACKAGE_REUSING_GRANTED_CONSENT; import static android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT; import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL; import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; -import static com.android.systemui.mediaprojection.MediaProjectionServiceHelper.OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION; import static com.android.systemui.mediaprojection.permission.ScreenShareOptionKt.ENTIRE_SCREEN; import static com.android.systemui.mediaprojection.permission.ScreenShareOptionKt.SINGLE_APP; import android.annotation.Nullable; -import android.annotation.RequiresPermission; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions.LaunchCookie; import android.app.AlertDialog; import android.app.StatusBarManager; -import android.app.compat.CompatChanges; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -109,7 +104,6 @@ public class MediaProjectionPermissionActivity extends Activity } @Override - @RequiresPermission(allOf = {READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE}) public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -237,9 +231,6 @@ public class MediaProjectionPermissionActivity extends Activity // the correct screen width when in split screen. Context dialogContext = getApplicationContext(); if (isPartialScreenSharingEnabled()) { - final boolean overrideDisableSingleAppOption = CompatChanges.isChangeEnabled( - OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION, - mPackageName, getHostUserHandle()); MediaProjectionPermissionDialogDelegate delegate = new MediaProjectionPermissionDialogDelegate( dialogContext, @@ -251,7 +242,6 @@ public class MediaProjectionPermissionActivity extends Activity }, () -> finish(RECORD_CANCEL, /* projection= */ null), appName, - overrideDisableSingleAppOption, mUid, mMediaProjectionMetricsLogger); mDialog = diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt index 9ce8070131fa..0f54e934f3cf 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt @@ -30,12 +30,11 @@ class MediaProjectionPermissionDialogDelegate( private val onStartRecordingClicked: Consumer<MediaProjectionPermissionDialogDelegate>, private val onCancelClicked: Runnable, private val appName: String?, - forceShowPartialScreenshare: Boolean, hostUid: Int, mediaProjectionMetricsLogger: MediaProjectionMetricsLogger, ) : BaseMediaProjectionPermissionDialogDelegate<AlertDialog>( - createOptionList(context, appName, mediaProjectionConfig, forceShowPartialScreenshare), + createOptionList(context, appName, mediaProjectionConfig), appName, hostUid, mediaProjectionMetricsLogger @@ -66,8 +65,7 @@ class MediaProjectionPermissionDialogDelegate( private fun createOptionList( context: Context, appName: String?, - mediaProjectionConfig: MediaProjectionConfig?, - overrideDisableSingleAppOption: Boolean = false, + mediaProjectionConfig: MediaProjectionConfig? ): List<ScreenShareOption> { val singleAppWarningText = if (appName == null) { @@ -82,13 +80,8 @@ class MediaProjectionPermissionDialogDelegate( R.string.media_projection_entry_app_permission_dialog_warning_entire_screen } - // The single app option should only be disabled if there is an app name provided, - // the client has setup a MediaProjection with - // MediaProjectionConfig#createConfigForDefaultDisplay, AND it hasn't been overridden by - // the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override. val singleAppOptionDisabled = appName != null && - !overrideDisableSingleAppOption && mediaProjectionConfig?.regionToCapture == MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index aa03e6e00859..5dd1bd80140b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -495,10 +495,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; } - private boolean isImmersiveMode() { - return mBehavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; - } - public void onConfigurationChanged(Configuration configuration) { mEdgeBackGestureHandler.onConfigurationChanged(configuration); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt index e718eea09665..a2bb9e9a2f63 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt @@ -6,6 +6,8 @@ import android.os.UserHandle import android.provider.Settings import android.util.Log import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.common.shared.model.PackageChangeModel.Empty.user import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -13,18 +15,28 @@ import com.android.systemui.qs.pipeline.data.model.RestoreData import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredRepository.Companion.BUFFER_CAPACITY import com.android.systemui.qs.pipeline.data.repository.TilesSettingConverter.toTilesList import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.util.kotlin.emitOnStart import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flattenConcat import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.shareIn +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock /** Provides restored data (from Backup and Restore) for Quick Settings pipeline */ interface QSSettingsRestoredRepository { @@ -44,34 +56,87 @@ class QSSettingsRestoredBroadcastRepository @Inject constructor( broadcastDispatcher: BroadcastDispatcher, + private val deviceProvisionedController: DeviceProvisionedController, logger: QSPipelineLogger, @Application private val scope: CoroutineScope, @Background private val backgroundDispatcher: CoroutineDispatcher, ) : QSSettingsRestoredRepository { + private val onUserSetupChangedForSomeUser = + conflatedCallbackFlow { + val callback = + object : DeviceProvisionedController.DeviceProvisionedListener { + override fun onUserSetupChanged() { + trySend(Unit) + } + } + deviceProvisionedController.addCallback(callback) + awaitClose { deviceProvisionedController.removeCallback(callback) } + } + .emitOnStart() + + @OptIn(ExperimentalCoroutinesApi::class) override val restoreData = - flow { + run { + val mutex = Mutex() val firstIntent = mutableMapOf<Int, Intent>() - broadcastDispatcher - .broadcastFlow(INTENT_FILTER, UserHandle.ALL) { intent, receiver -> - intent to receiver.sendingUserId - } - .filter { it.first.isCorrectSetting() } - .collect { (intent, user) -> - if (user !in firstIntent) { - firstIntent[user] = intent - } else { - val firstRestored = firstIntent.remove(user)!! - emit(processIntents(user, firstRestored, intent)) + + val restoresFromTwoBroadcasts: Flow<RestoreData> = + broadcastDispatcher + .broadcastFlow(INTENT_FILTER, UserHandle.ALL) { intent, receiver -> + intent to receiver.sendingUserId } - } + .filter { it.first.isCorrectSetting() } + .mapNotNull { (intent, user) -> + mutex.withLock { + if (user !in firstIntent) { + firstIntent[user] = intent + null + } else { + val firstRestored = firstIntent.remove(user)!! + processIntents(user, firstRestored, intent) + } + } + } + .catch { Log.e(TAG, "Error parsing broadcast", it) } + + val restoresFromUserSetup: Flow<RestoreData> = + onUserSetupChangedForSomeUser + .map { + mutex.withLock { + firstIntent + .filter { (userId, _) -> + deviceProvisionedController.isUserSetup(userId) + } + .onEach { firstIntent.remove(it.key) } + .map { processSingleIntent(it.key, it.value) } + .asFlow() + } + } + .flattenConcat() + .catch { Log.e(TAG, "Error parsing tiles intent after user setup", it) } + .onEach { logger.logSettingsRestoredOnUserSetupComplete(it.userId) } + merge(restoresFromTwoBroadcasts, restoresFromUserSetup) } - .catch { Log.e(TAG, "Error parsing broadcast", it) } .flowOn(backgroundDispatcher) .buffer(BUFFER_CAPACITY) .shareIn(scope, SharingStarted.Eagerly) .onEach(logger::logSettingsRestored) + private fun processSingleIntent(user: Int, intent: Intent): RestoreData { + intent.validateIntent() + if (intent.getStringExtra(Intent.EXTRA_SETTING_NAME) != TILES_SETTING) { + throw IllegalStateException( + "Single intent restored for user $user is not tiles: $intent" + ) + } + return RestoreData( + (intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE) ?: "").toTilesList(), + emptySet(), + user, + ) + } + private fun processIntents(user: Int, intent1: Intent, intent2: Intent): RestoreData { intent1.validateIntent() intent2.validateIntent() diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt index 7d2c6c8f70fb..e237ca9f462b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt @@ -221,6 +221,15 @@ constructor( ) } + fun logSettingsRestoredOnUserSetupComplete(userId: Int) { + restoreLogBuffer.log( + RESTORE_TAG, + LogLevel.DEBUG, + { int1 = userId }, + { "Restored from single intent after user setup complete for user $int1" } + ) + } + fun logSettingsRestored(restoreData: RestoreData) { restoreLogBuffer.log( RESTORE_TAG, diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt index 72a5c468ea94..c1b20374dbac 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt @@ -84,6 +84,10 @@ interface QSSceneAdapter { */ val qsHeight: Int + /** Compatibility for use by LockscreenShadeTransitionController. Matches default from [QS] */ + val isQsFullyCollapsed: Boolean + get() = true + sealed interface State { val isVisible: Boolean @@ -165,6 +169,10 @@ constructor( override val qsHeight: Int get() = qsImpl.value?.qsHeight ?: 0 + // If value is null, there's no QS and therefore it's fully collapsed. + override val isQsFullyCollapsed: Boolean + get() = qsImpl.value?.isFullyCollapsed ?: true + // Same config changes as in FragmentHostManager private val interestingChanges = InterestingConfigChanges( diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt index 494c86c7b8c8..0add4443fa7a 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt @@ -19,7 +19,6 @@ package com.android.systemui.scene.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor -import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.data.repository.SceneContainerRepository import com.android.systemui.scene.shared.logger.SceneLogger import com.android.systemui.scene.shared.model.ObservableTransitionState @@ -50,7 +49,6 @@ class SceneInteractor constructor( @Application private val applicationScope: CoroutineScope, private val repository: SceneContainerRepository, - private val powerInteractor: PowerInteractor, private val logger: SceneLogger, private val deviceUnlockedInteractor: DeviceUnlockedInteractor, ) { @@ -189,9 +187,4 @@ constructor( fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { repository.setTransitionState(transitionState) } - - /** Handles a user input event. */ - fun onUserInput() { - powerInteractor.onUserTouch() - } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/UserActionResult.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/UserActionResult.kt index e1b96e4db938..c6ae21505c68 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/UserActionResult.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/UserActionResult.kt @@ -22,13 +22,6 @@ data class UserActionResult( val toScene: SceneKey, /** - * The distance the action takes to animate from 0% to 100%. - * - * If `null`, a default distance will be used depending on the [UserAction] performed. - */ - val distance: UserActionDistance? = null, - - /** * The key of the transition that should be used, if a specific one should be used. * * If `null`, the transition used will be the corresponding transition from the collection diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt index 8bf68df01428..4cd3baa7a52e 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt @@ -20,6 +20,7 @@ import android.view.MotionEvent import com.android.systemui.classifier.Classifier import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey @@ -34,6 +35,7 @@ class SceneContainerViewModel constructor( private val sceneInteractor: SceneInteractor, private val falsingInteractor: FalsingInteractor, + private val powerInteractor: PowerInteractor, ) { /** * Keys of all scenes in the container. @@ -64,7 +66,7 @@ constructor( * Call this before the [MotionEvent] starts to propagate through the UI hierarchy. */ fun onMotionEvent(event: MotionEvent) { - sceneInteractor.onUserInput() + powerInteractor.onUserTouch() falsingInteractor.onTouchEvent(event) } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt index bee315261f89..fb5339df7212 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt @@ -31,10 +31,13 @@ import android.view.WindowManager import android.view.WindowManagerGlobal import com.android.app.tracing.coroutines.launch import com.android.internal.infra.ServiceConnector +import com.android.systemui.Flags.screenshotActionDismissSystemWindows import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.settings.DisplayTracker +import com.android.systemui.shared.system.ActivityManagerWrapper +import com.android.systemui.statusbar.phone.CentralSurfaces import javax.inject.Inject import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineDispatcher @@ -46,9 +49,11 @@ class ActionIntentExecutor @Inject constructor( private val context: Context, + private val activityManagerWrapper: ActivityManagerWrapper, @Application private val applicationScope: CoroutineScope, @Main private val mainDispatcher: CoroutineDispatcher, private val displayTracker: DisplayTracker, + private val keyguardController: ScreenshotKeyguardController, ) { /** * Execute the given intent with startActivity while performing operations for screenshot action @@ -74,7 +79,14 @@ constructor( user: UserHandle, overrideTransition: Boolean, ) { - dismissKeyguard() + if (screenshotActionDismissSystemWindows()) { + keyguardController.dismiss() + activityManagerWrapper.closeSystemWindows( + CentralSurfaces.SYSTEM_DIALOG_REASON_SCREENSHOT + ) + } else { + dismissKeyguard() + } if (user == myUserHandle()) { withContext(mainDispatcher) { context.startActivity(intent, options) } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotKeyguardController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotKeyguardController.kt new file mode 100644 index 000000000000..7696bbe3763e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotKeyguardController.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. + */ + +package com.android.systemui.screenshot + +import android.content.Context +import android.content.Intent +import com.android.internal.infra.ServiceConnector +import javax.inject.Inject +import kotlinx.coroutines.CompletableDeferred + +open class ScreenshotKeyguardController @Inject constructor(context: Context) { + private val proxyConnector: ServiceConnector<IScreenshotProxy> = + ServiceConnector.Impl( + context, + Intent(context, ScreenshotProxyService::class.java), + Context.BIND_AUTO_CREATE or Context.BIND_WAIVE_PRIORITY or Context.BIND_NOT_VISIBLE, + context.userId, + IScreenshotProxy.Stub::asInterface + ) + + suspend fun dismiss() { + val completion = CompletableDeferred<Unit>() + val onDoneBinder = + object : IOnDoneCallback.Stub() { + override fun onDone(success: Boolean) { + completion.complete(Unit) + } + } + proxyConnector.post { it.dismissKeyguard(onDoneBinder) } + completion.await() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt index 86f652389b42..d5ab3066bfde 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt @@ -17,15 +17,16 @@ package com.android.systemui.screenshot import android.content.Intent import android.os.IBinder +import android.os.RemoteException import android.util.Log import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope +import com.android.app.tracing.coroutines.launch import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.shade.ShadeExpansionStateManager import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -import com.android.app.tracing.coroutines.launch import kotlinx.coroutines.withContext /** Provides state from the main SystemUI process on behalf of the Screenshot process. */ @@ -56,7 +57,13 @@ constructor( private suspend fun executeAfterDismissing(callback: IOnDoneCallback) = withContext(mMainDispatcher) { activityStarter.executeRunnableDismissingKeyguard( - Runnable { callback.onDone(true) }, + { + try { + callback.onDone(true) + } catch (e: RemoteException) { + Log.w(TAG, "Failed to complete callback transaction", e) + } + }, null, true /* dismissShade */, true /* afterKeyguardGone */, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt index 238a552604ca..2c0bddecc58e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt @@ -58,8 +58,16 @@ constructor( } override fun playCameraSound(): Deferred<Unit> { - return coroutineScope.async("playCameraSound", bgDispatcher) { player.await()?.start() } + return coroutineScope.async("playCameraSound", bgDispatcher) { + try { + player.await()?.start() + } catch (e: IllegalStateException) { + Log.w(TAG, "Screenshot sound failed to play", e) + releaseScreenshotSound() + } + } } + override fun releaseScreenshotSound(): Deferred<Unit> { return coroutineScope.async("releaseScreenshotSound", bgDispatcher) { try { diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt index f2fa0ef3f30f..0a1f649691a1 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt @@ -121,7 +121,6 @@ open class UserTrackerImpl internal constructor( @GuardedBy("callbacks") private val callbacks: MutableList<DataItem> = ArrayList() - private var beforeUserSwitchingJob: Job? = null private var userSwitchingJob: Job? = null private var afterUserSwitchingJob: Job? = null @@ -194,14 +193,7 @@ open class UserTrackerImpl internal constructor( private fun registerUserSwitchObserver() { iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() { override fun onBeforeUserSwitching(newUserId: Int) { - if (isBackgroundUserSwitchEnabled) { - beforeUserSwitchingJob?.cancel() - beforeUserSwitchingJob = appScope.launch(backgroundContext) { - handleBeforeUserSwitching(newUserId) - } - } else { - handleBeforeUserSwitching(newUserId) - } + handleBeforeUserSwitching(newUserId) } override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) { @@ -233,15 +225,12 @@ open class UserTrackerImpl internal constructor( @WorkerThread protected open fun handleBeforeUserSwitching(newUserId: Int) { - Assert.isNotMainThread() setUserIdInternal(newUserId) - val list = synchronized(callbacks) { - callbacks.toList() - } - list.forEach { - it.callback.get()?.onBeforeUserSwitching(newUserId) - } + notifySubscribers { callback, resultCallback -> + callback.onBeforeUserSwitching(newUserId) + resultCallback.run() + }.await() } @WorkerThread @@ -249,21 +238,9 @@ open class UserTrackerImpl internal constructor( Assert.isNotMainThread() Log.i(TAG, "Switching to user $newUserId") - val list = synchronized(callbacks) { - callbacks.toList() - } - val latch = CountDownLatch(list.size) - list.forEach { - val callback = it.callback.get() - if (callback != null) { - it.executor.execute { - callback.onUserChanging(userId, userContext) { latch.countDown() } - } - } else { - latch.countDown() - } - } - latch.await() + notifySubscribers { callback, resultCallback -> + callback.onUserChanging(newUserId, userContext, resultCallback) + }.await() } @WorkerThread @@ -293,9 +270,9 @@ open class UserTrackerImpl internal constructor( Assert.isNotMainThread() Log.i(TAG, "Switched to user $newUserId") - notifySubscribers { - onUserChanged(newUserId, userContext) - onProfilesChanged(userProfiles) + notifySubscribers { callback, _ -> + callback.onUserChanged(newUserId, userContext) + callback.onProfilesChanged(userProfiles) } } @@ -307,8 +284,8 @@ open class UserTrackerImpl internal constructor( synchronized(mutex) { userProfiles = profiles.map { UserInfo(it) } // save a "deep" copy } - notifySubscribers { - onProfilesChanged(profiles) + notifySubscribers { callback, _ -> + callback.onProfilesChanged(profiles) } } @@ -324,18 +301,24 @@ open class UserTrackerImpl internal constructor( } } - private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) { + private inline fun notifySubscribers( + crossinline action: (UserTracker.Callback, resultCallback: Runnable) -> Unit + ): CountDownLatch { val list = synchronized(callbacks) { callbacks.toList() } - + val latch = CountDownLatch(list.size) list.forEach { - if (it.callback.get() != null) { + val callback = it.callback.get() + if (callback != null) { it.executor.execute { - it.callback.get()?.action() + action(callback) { latch.countDown() } } + } else { + latch.countDown() } } + return latch } override fun dump(pw: PrintWriter, args: Array<out String>) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 7f06778e9438..7068f5fcc32b 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -165,6 +165,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController.StateList import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.power.shared.model.WakefulnessModel; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.shade.data.repository.FlingInfo; import com.android.systemui.shade.data.repository.ShadeRepository; import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor; @@ -4595,8 +4596,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump public void onViewAttachedToWindow(View v) { mFragmentService.getFragmentHostManager(mView) .addTagListener(QS.TAG, mQsController.getQsFragmentListener()); - mStatusBarStateController.addCallback(mStatusBarStateListener); - mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState()); + if (!SceneContainerFlag.isEnabled()) { + mStatusBarStateController.addCallback(mStatusBarStateListener); + mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState()); + } mConfigurationController.addCallback(mConfigurationListener); // Theme might have changed between inflating this view and attaching it to the // window, so diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepository.kt new file mode 100644 index 000000000000..a9bf2dfdef9e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepository.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.data.repository + +import android.app.PendingIntent +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.policy.NextAlarmController +import javax.inject.Inject + +@SysUISingleton +class ShadeHeaderClockRepository +@Inject +constructor( + nextAlarmController: NextAlarmController, +) { + private val nextAlarmCallback = + NextAlarmController.NextAlarmChangeCallback { nextAlarm -> + nextAlarmIntent = nextAlarm?.showIntent + } + + init { + nextAlarmController.addCallback(nextAlarmCallback) + } + + /** Intent to show the next active alarm. */ + var nextAlarmIntent: PendingIntent? = null + private set +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt new file mode 100644 index 000000000000..186bfcbbc8e2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 android.content.Intent +import android.provider.AlarmClock +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.shade.data.repository.ShadeHeaderClockRepository +import javax.inject.Inject + +@SysUISingleton +class ShadeHeaderClockInteractor +@Inject +constructor( + private val repository: ShadeHeaderClockRepository, + private val activityStarter: ActivityStarter, +) { + /** Launch the clock activity. */ + fun launchClockActivity() { + val nextAlarmIntent = repository.nextAlarmIntent + if (nextAlarmIntent != null) { + activityStarter.postStartActivityDismissingKeyguard(nextAlarmIntent) + } else { + activityStarter.postStartActivityDismissingKeyguard( + Intent(AlarmClock.ACTION_SHOW_ALARMS), + 0 + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt index 700825dd639c..1191c0f247f9 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt @@ -29,6 +29,7 @@ import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyItem import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.PrivacyChipInteractor +import com.android.systemui.shade.domain.interactor.ShadeHeaderClockInteractor import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel import java.util.Date @@ -55,6 +56,7 @@ constructor( mobileIconsInteractor: MobileIconsInteractor, val mobileIconsViewModel: MobileIconsViewModel, private val privacyChipInteractor: PrivacyChipInteractor, + private val clockInteractor: ShadeHeaderClockInteractor, broadcastDispatcher: BroadcastDispatcher, ) { /** True if there is exactly one mobile connection. */ @@ -121,6 +123,11 @@ constructor( privacyChipInteractor.onPrivacyChipClicked(privacyChip) } + /** Notifies that the clock was clicked. */ + fun onClockClicked() { + clockInteractor.launchClockActivity() + } + private fun updateDateTexts(invalidateFormats: Boolean) { if (invalidateFormats) { longerDateFormat.value = getFormatFromPattern(longerPattern) diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt index abdfa536f63d..38358a8f244e 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt @@ -28,6 +28,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Models UI state and handles user input for the shade scene. */ @@ -63,6 +64,16 @@ constructor( ), ) + /** Whether or not the shade container should be clickable. */ + val isClickable: StateFlow<Boolean> = + upDestinationSceneKey + .map { it == SceneKey.Lockscreen } + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false + ) + /** Notifies that some content in the shade was clicked. */ fun onContentClicked() = deviceEntryInteractor.attemptDeviceEntry() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 3908edec7da5..ca19f71bd391 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -615,7 +615,14 @@ public class CommandQueue extends IStatusBar.Stub implements args.argi2 = state1; args.argi3 = state2; args.argi4 = animate ? 1 : 0; - mHandler.obtainMessage(MSG_DISABLE, args).sendToTarget(); + Message msg = mHandler.obtainMessage(MSG_DISABLE, args); + if (Looper.myLooper() == mHandler.getLooper()) { + // If its the right looper execute immediately so hides can be handled quickly. + mHandler.handleMessage(msg); + msg.recycle(); + } else { + msg.sendToTarget(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt index 4d0552e7cb31..adca3f2d25d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt @@ -21,9 +21,9 @@ import android.util.IndentingPrintWriter import android.util.MathUtils import androidx.annotation.FloatRange import androidx.annotation.Px -import com.android.systemui.res.R import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS +import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.SplitShadeStateController import dagger.assisted.Assisted @@ -38,7 +38,7 @@ constructor( context: Context, configurationController: ConfigurationController, dumpManager: DumpManager, - @Assisted private val qsProvider: () -> QS, + @Assisted private val qsProvider: () -> QS?, splitShadeStateController: SplitShadeStateController ) : AbstractLockscreenShadeTransitionController( @@ -48,7 +48,7 @@ constructor( splitShadeStateController ) { - private val qs: QS + private val qs: QS? get() = qsProvider() /** @@ -135,7 +135,7 @@ constructor( /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance) ) isTransitioningToFullShade = dragDownAmount > 0.0f - qs.setTransitionToFullShadeProgress( + qs?.setTransitionToFullShadeProgress( isTransitioningToFullShade, qsTransitionFraction, qsSquishTransitionFraction @@ -163,6 +163,6 @@ constructor( @AssistedFactory fun interface Factory { - fun create(qsProvider: () -> QS): LockscreenShadeQsTransitionController + fun create(qsProvider: () -> QS?): LockscreenShadeQsTransitionController } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index a59d753971f6..4ee83497b368 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -31,6 +31,7 @@ import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QS import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.ui.adapter.QSSceneAdapter import com.android.systemui.res.R import com.android.systemui.shade.ShadeLockscreenInteractor import com.android.systemui.shade.data.repository.ShadeRepository @@ -84,6 +85,7 @@ constructor( private val splitShadeStateController: SplitShadeStateController, private val shadeLockscreenInteractorLazy: Lazy<ShadeLockscreenInteractor>, naturalScrollingSettingObserver: NaturalScrollingSettingObserver, + private val lazyQSSceneAdapter: Lazy<QSSceneAdapter>, ) : Dumpable { private var pulseHeight: Float = 0f @@ -93,7 +95,11 @@ constructor( private var useSplitShade: Boolean = false private lateinit var nsslController: NotificationStackScrollLayoutController lateinit var centralSurfaces: CentralSurfaces - lateinit var qS: QS + + // When in scene container mode, this will be null. In that case, we use the adapter if needed + var qS: QS? = null + private val isQsFullyCollapsed: Boolean + get() = qS?.isFullyCollapsed ?: lazyQSSceneAdapter.get().isQsFullyCollapsed /** A handler that handles the next keyguard dismiss animation. */ private var animationHandlerOnKeyguardDismiss: ((Long) -> Unit)? = null @@ -286,7 +292,8 @@ constructor( /** @return true if the interaction is accepted, false if it should be cancelled */ internal fun canDragDown(): Boolean { return (statusBarStateController.state == StatusBarState.KEYGUARD || - nsslController.isInLockedDownShade()) && (qS.isFullyCollapsed || useSplitShade) + nsslController.isInLockedDownShade()) && + (isQsFullyCollapsed || useSplitShade) } /** Called by the touch helper when when a gesture has completed all the way and released. */ @@ -410,7 +417,7 @@ constructor( get() = (statusBarStateController.getState() == StatusBarState.KEYGUARD && !keyguardBypassController.bypassEnabled && - (qS.isFullyCollapsed || useSplitShade)) + (isQsFullyCollapsed || useSplitShade)) /** The amount in pixels that the user has dragged down. */ internal var dragDownAmount = 0f diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt index 692a9977c364..4ab78aab372d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt @@ -1,8 +1,8 @@ package com.android.systemui.statusbar +import android.app.Flags.lifetimeExtensionRefactor import android.app.Notification import android.os.RemoteException -import android.util.Log import com.android.internal.statusbar.IStatusBarService import com.android.internal.statusbar.NotificationVisibility import com.android.systemui.dagger.SysUISingleton @@ -58,9 +58,14 @@ public class NotificationClickNotifier @Inject constructor( } catch (e: RemoteException) { // nothing } + if (lifetimeExtensionRefactor()) { + notifyListenersAboutInteraction(key) + } } - mainExecutor.execute { - notifyListenersAboutInteraction(key) + if (!lifetimeExtensionRefactor()) { + mainExecutor.execute { + notifyListenersAboutInteraction(key) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt index e47c914341a6..612a365dbe8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt @@ -27,7 +27,7 @@ constructor( private val context: Context, private val scrimController: ScrimController, private val statusBarStateController: SysuiStatusBarStateController, - @Assisted private val qSProvider: () -> QS, + @Assisted private val qSProvider: () -> QS?, @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController ) : LockScreenShadeOverScroller { @@ -37,7 +37,7 @@ constructor( private var maxOverScrollAmount = 0 private var previousOverscrollAmount = 0 - private val qS: QS + private val qS: QS? get() = qSProvider() private val nsslController: NotificationStackScrollLayoutController @@ -90,7 +90,7 @@ constructor( } private fun applyOverscroll(overscrollAmount: Int) { - qS.setOverScrollAmount(overscrollAmount) + qS?.setOverScrollAmount(overscrollAmount) scrimController.setNotificationsOverScrollAmount(overscrollAmount) nsslController.setOverScrollAmount(overscrollAmount) } @@ -109,7 +109,7 @@ constructor( val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0) animator.addUpdateListener { val overScrollAmount = it.animatedValue as Int - qS.setOverScrollAmount(overScrollAmount) + qS?.setOverScrollAmount(overScrollAmount) scrimController.setNotificationsOverScrollAmount(overScrollAmount) nsslController.setOverScrollAmount(overScrollAmount) } @@ -143,7 +143,7 @@ constructor( @AssistedFactory fun interface Factory { fun create( - qSProvider: () -> QS, + qSProvider: () -> QS?, nsslControllerProvider: () -> NotificationStackScrollLayoutController ): SplitShadeLockScreenOverScroller } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 537f8a866fed..36fc9bb3a2da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_TO_AOD; +import static com.android.systemui.util.kotlin.JavaAdapterKt.combineFlows; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -43,19 +44,26 @@ import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardClockSwitch; import com.android.systemui.DejankUtils; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.res.R; +import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; +import com.android.systemui.scene.shared.model.SceneKey; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.policy.CallbackController; import com.android.systemui.util.Compile; import com.android.systemui.util.kotlin.JavaAdapter; +import com.google.common.base.Preconditions; + import dagger.Lazy; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Comparator; +import java.util.Map; import javax.inject.Inject; @@ -97,6 +105,8 @@ public class StatusBarStateControllerImpl implements private final InteractionJankMonitor mInteractionJankMonitor; private final JavaAdapter mJavaAdapter; private final Lazy<ShadeInteractor> mShadeInteractorLazy; + private final Lazy<DeviceUnlockedInteractor> mDeviceUnlockedInteractorLazy; + private final Lazy<SceneInteractor> mSceneInteractorLazy; private int mState; private int mLastState; private int mUpcomingState; @@ -160,11 +170,15 @@ public class StatusBarStateControllerImpl implements UiEventLogger uiEventLogger, InteractionJankMonitor interactionJankMonitor, JavaAdapter javaAdapter, - Lazy<ShadeInteractor> shadeInteractorLazy) { + Lazy<ShadeInteractor> shadeInteractorLazy, + Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy, + Lazy<SceneInteractor> sceneInteractorLazy) { mUiEventLogger = uiEventLogger; mInteractionJankMonitor = interactionJankMonitor; mJavaAdapter = javaAdapter; mShadeInteractorLazy = shadeInteractorLazy; + mDeviceUnlockedInteractorLazy = deviceUnlockedInteractorLazy; + mSceneInteractorLazy = sceneInteractorLazy; for (int i = 0; i < HISTORY_SIZE; i++) { mHistoricalRecords[i] = new HistoricalState(); } @@ -174,6 +188,15 @@ public class StatusBarStateControllerImpl implements public void start() { mJavaAdapter.alwaysCollectFlow(mShadeInteractorLazy.get().isAnyExpanded(), this::onShadeOrQsExpanded); + + if (SceneContainerFlag.isEnabled()) { + mJavaAdapter.alwaysCollectFlow( + combineFlows( + mDeviceUnlockedInteractorLazy.get().isDeviceUnlocked(), + mSceneInteractorLazy.get().getCurrentScene(), + this::calculateStateFromSceneFramework), + this::onStatusBarStateChanged); + } } @Override @@ -183,6 +206,10 @@ public class StatusBarStateControllerImpl implements @Override public boolean setState(int state, boolean force) { + if (SceneContainerFlag.isEnabled()) { + return false; + } + if (state > MAX_STATE || state < MIN_STATE) { throw new IllegalArgumentException("Invalid state " + state); } @@ -194,6 +221,14 @@ public class StatusBarStateControllerImpl implements return false; } + updateStateAndNotifyListeners(state); + return true; + } + + /** + * Updates the {@link StatusBarState} and notifies registered listeners, if needed. + */ + private void updateStateAndNotifyListeners(int state) { if (state != mUpcomingState) { Log.d(TAG, "setState: requested state " + StatusBarState.toString(state) + "!= upcomingState: " + StatusBarState.toString(mUpcomingState) + ". " @@ -229,15 +264,16 @@ public class StatusBarStateControllerImpl implements } DejankUtils.stopDetectingBlockingIpcs(tag); } - - return true; } @Override public void setUpcomingState(int nextState) { + if (SceneContainerFlag.isEnabled()) { + return; + } + recordHistoricalState(nextState /* newState */, mState /* lastState */, true); updateUpcomingState(nextState); - } private void updateUpcomingState(int upcomingState) { @@ -468,7 +504,7 @@ public class StatusBarStateControllerImpl implements @Override public boolean goingToFullShade() { - return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide; + return getState() == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide; } @Override @@ -599,6 +635,37 @@ public class StatusBarStateControllerImpl implements state.mUpcoming = upcoming; } + private int calculateStateFromSceneFramework( + boolean isDeviceUnlocked, + SceneKey currentScene) { + SceneContainerFlag.isUnexpectedlyInLegacyMode(); + + if (isDeviceUnlocked) { + return StatusBarState.SHADE; + } else { + return Preconditions.checkNotNull(sStatusBarStateByLockedSceneKey.get(currentScene)); + } + } + + /** Notifies that the {@link StatusBarState} has changed to the given new state. */ + private void onStatusBarStateChanged(int newState) { + SceneContainerFlag.isUnexpectedlyInLegacyMode(); + + if (newState == mState) { + return; + } + + updateStateAndNotifyListeners(newState); + } + + private static final Map<SceneKey, Integer> sStatusBarStateByLockedSceneKey = Map.of( + SceneKey.Lockscreen.INSTANCE, StatusBarState.KEYGUARD, + SceneKey.Bouncer.INSTANCE, StatusBarState.KEYGUARD, + SceneKey.Communal.INSTANCE, StatusBarState.KEYGUARD, + SceneKey.Shade.INSTANCE, StatusBarState.SHADE_LOCKED, + SceneKey.QuickSettings.INSTANCE, StatusBarState.SHADE_LOCKED + ); + /** * For keeping track of our previous state to help with debugging */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt index c416d434a8fb..0f0ab2e36b8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ColorUpdateLogger.kt @@ -108,7 +108,7 @@ constructor( fun trim() { if (events.size > maxEventsPerFrame) { - events.removeFirst() + events.removeAt(0) trimmedEvents++ } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt index bd659d294223..b9d1dde82eeb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt @@ -53,6 +53,7 @@ class NotifCoordinatorsImpl @Inject constructor( mediaCoordinator: MediaCoordinator, preparationCoordinator: PreparationCoordinator, remoteInputCoordinator: RemoteInputCoordinator, + rowAlertTimeCoordinator: RowAlertTimeCoordinator, rowAppearanceCoordinator: RowAppearanceCoordinator, stackCoordinator: StackCoordinator, shadeEventCoordinator: ShadeEventCoordinator, @@ -69,9 +70,7 @@ class NotifCoordinatorsImpl @Inject constructor( private val mCoordinators: MutableList<Coordinator> = ArrayList() private val mOrderedSections: MutableList<NotifSectioner> = ArrayList() - /** - * Creates all the coordinators. - */ + /** Creates all the coordinators. */ init { // Attach core coordinators. mCoreCoordinators.add(dataStoreCoordinator) @@ -89,6 +88,7 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(groupCountCoordinator) mCoordinators.add(groupWhenCoordinator) mCoordinators.add(mediaCoordinator) + mCoordinators.add(rowAlertTimeCoordinator) mCoordinators.add(rowAppearanceCoordinator) mCoordinators.add(stackCoordinator) mCoordinators.add(shadeEventCoordinator) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt new file mode 100644 index 000000000000..12de339871bb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.statusbar.notification.collection.coordinator + +import android.util.ArrayMap +import com.android.systemui.statusbar.notification.collection.GroupEntry +import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope +import com.android.systemui.statusbar.notification.collection.render.NotifRowController +import javax.inject.Inject +import kotlin.math.max + +/** + * A small coordinator which ensures the "alerted" bell shows not just for recently alerted entries, + * but also on the summary for every such entry. + */ +@CoordinatorScope +class RowAlertTimeCoordinator @Inject constructor() : Coordinator { + + private val latestAlertTimeBySummary = ArrayMap<NotificationEntry, Long>() + + override fun attach(pipeline: NotifPipeline) { + pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilterListener) + pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry) + } + + private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) { + latestAlertTimeBySummary.clear() + entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry -> + val summary = checkNotNull(groupEntry.summary) + latestAlertTimeBySummary[summary] = groupEntry.calculateLatestAlertTime() + } + } + + private fun onAfterRenderEntry(entry: NotificationEntry, controller: NotifRowController) { + // Show the "alerted" bell icon based on the latest group member for summaries + val lastAudiblyAlerted = latestAlertTimeBySummary[entry] ?: entry.lastAudiblyAlertedMs + controller.setLastAudibleMs(lastAudiblyAlerted) + } + + private fun GroupEntry.calculateLatestAlertTime(): Long { + val lastChildAlertedTime = children.maxOf { it.lastAudiblyAlertedMs } + val summaryAlertedTime = checkNotNull(summary).lastAudiblyAlertedMs + return max(lastChildAlertedTime, summaryAlertedTime) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt index f2b84827f3a3..df694bb67684 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt @@ -75,7 +75,5 @@ class RowAppearanceCoordinator @Inject internal constructor( (mAutoExpandFirstNotification && entry == entryToExpand)) // Show/hide the feedback icon controller.setFeedbackIcon(mAssistantFeedbackController.getFeedbackIcon(entry)) - // Show the "alerted" bell icon - controller.setLastAudibleMs(entry.lastAudiblyAlertedMs) } } 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 8189fe03b2ed..dfe6cd5f25b8 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 @@ -25,6 +25,7 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -92,7 +93,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { @Inject public VisualStabilityCoordinator( - DelayableExecutor delayableExecutor, + @Background DelayableExecutor delayableExecutor, DumpManager dumpManager, HeadsUpManager headsUpManager, ShadeAnimationInteractor shadeAnimationInteractor, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 2a1ec3e9c64f..6548967c7462 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -16,12 +16,18 @@ package com.android.systemui.statusbar.notification.dagger; +import android.app.NotificationManager; import android.content.Context; import android.service.notification.NotificationListenerService; import com.android.internal.jank.InteractionJankMonitor; +import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepository; +import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepositoryImpl; +import com.android.settingslib.statusbar.notification.domain.interactor.NotificationsSoundPolicyInteractor; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Application; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.res.R; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -79,13 +85,15 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; import com.android.systemui.statusbar.policy.HeadsUpManager; +import javax.inject.Provider; + import dagger.Binds; import dagger.Module; import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; - -import javax.inject.Provider; +import kotlin.coroutines.CoroutineContext; +import kotlinx.coroutines.CoroutineScope; /** * Dagger Module for classes found within the com.android.systemui.statusbar.notification package. @@ -259,4 +267,22 @@ public interface NotificationsModule { @ClassKey(VisualInterruptionDecisionProvider.class) CoreStartable startVisualInterruptionDecisionProvider( VisualInterruptionDecisionProvider provider); + + @Provides + @SysUISingleton + public static NotificationsSoundPolicyRepository provideNotificationsSoundPolicyRepository( + Context context, + NotificationManager notificationManager, + @Application CoroutineScope coroutineScope, + @Background CoroutineContext coroutineContext) { + return new NotificationsSoundPolicyRepositoryImpl(context, notificationManager, + coroutineScope, coroutineContext); + } + + @Provides + @SysUISingleton + public static NotificationsSoundPolicyInteractor provideNotificationsSoundPolicyInteractror( + NotificationsSoundPolicyRepository repository) { + return new NotificationsSoundPolicyInteractor(repository); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt index 76e5fd3bd4f2..a5f42bb99e10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt @@ -45,10 +45,12 @@ import javax.inject.Inject * icons and keeping the icon assets themselves up to date as notifications change. * * TODO: Much of this code was copied whole-sale in order to get it out of NotificationEntry. - * Long-term, it should probably live somewhere in the content inflation pipeline. + * Long-term, it should probably live somewhere in the content inflation pipeline. */ @SysUISingleton -class IconManager @Inject constructor( +class IconManager +@Inject +constructor( private val notifCollection: CommonNotifCollection, private val launcherApps: LauncherApps, private val iconBuilder: IconBuilder @@ -59,30 +61,30 @@ class IconManager @Inject constructor( notifCollection.addCollectionListener(entryListener) } - private val entryListener = object : NotifCollectionListener { - override fun onEntryInit(entry: NotificationEntry) { - entry.addOnSensitivityChangedListener(sensitivityListener) - } + private val entryListener = + object : NotifCollectionListener { + override fun onEntryInit(entry: NotificationEntry) { + entry.addOnSensitivityChangedListener(sensitivityListener) + } - override fun onEntryCleanUp(entry: NotificationEntry) { - entry.removeOnSensitivityChangedListener(sensitivityListener) - } + override fun onEntryCleanUp(entry: NotificationEntry) { + entry.removeOnSensitivityChangedListener(sensitivityListener) + } - override fun onRankingApplied() { - // rankings affect whether a conversation is important, which can change the icons - recalculateForImportantConversationChange() + override fun onRankingApplied() { + // rankings affect whether a conversation is important, which can change the icons + recalculateForImportantConversationChange() + } } - } - private val sensitivityListener = NotificationEntry.OnSensitivityChangedListener { - entry -> updateIconsSafe(entry) - } + private val sensitivityListener = + NotificationEntry.OnSensitivityChangedListener { entry -> updateIconsSafe(entry) } private fun recalculateForImportantConversationChange() { for (entry in notifCollection.allNotifs) { val isImportant = isImportantConversation(entry) - if (entry.icons.areIconsAvailable && - isImportant != entry.icons.isImportantConversation + if ( + entry.icons.areIconsAvailable && isImportant != entry.icons.isImportantConversation ) { updateIconsSafe(entry) } @@ -97,34 +99,35 @@ class IconManager @Inject constructor( * @throws InflationException Exception if required icons are not valid or specified */ @Throws(InflationException::class) - fun createIcons(entry: NotificationEntry) = traceSection("IconManager.createIcons") { - // Construct the status bar icon view. - val sbIcon = iconBuilder.createIconView(entry) - sbIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE - - // Construct the shelf icon view. - val shelfIcon = iconBuilder.createIconView(entry) - shelfIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE - shelfIcon.visibility = View.INVISIBLE - - // Construct the aod icon view. - val aodIcon = iconBuilder.createIconView(entry) - aodIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE - aodIcon.setIncreasedSize(true) - - // Set the icon views' icons - val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry) - - try { - setIcon(entry, normalIconDescriptor, sbIcon) - setIcon(entry, sensitiveIconDescriptor, shelfIcon) - setIcon(entry, sensitiveIconDescriptor, aodIcon) - entry.icons = IconPack.buildPack(sbIcon, shelfIcon, aodIcon, entry.icons) - } catch (e: InflationException) { - entry.icons = IconPack.buildEmptyPack(entry.icons) - throw e + fun createIcons(entry: NotificationEntry) = + traceSection("IconManager.createIcons") { + // Construct the status bar icon view. + val sbIcon = iconBuilder.createIconView(entry) + sbIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE + + // Construct the shelf icon view. + val shelfIcon = iconBuilder.createIconView(entry) + shelfIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE + shelfIcon.visibility = View.INVISIBLE + + // Construct the aod icon view. + val aodIcon = iconBuilder.createIconView(entry) + aodIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE + aodIcon.setIncreasedSize(true) + + // Set the icon views' icons + val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry) + + try { + setIcon(entry, normalIconDescriptor, sbIcon) + setIcon(entry, sensitiveIconDescriptor, shelfIcon) + setIcon(entry, sensitiveIconDescriptor, aodIcon) + entry.icons = IconPack.buildPack(sbIcon, shelfIcon, aodIcon, entry.icons) + } catch (e: InflationException) { + entry.icons = IconPack.buildEmptyPack(entry.icons) + throw e + } } - } /** * Update the notification icons. @@ -133,33 +136,33 @@ class IconManager @Inject constructor( * @throws InflationException Exception if required icons are not valid or specified */ @Throws(InflationException::class) - fun updateIcons(entry: NotificationEntry) = traceSection("IconManager.updateIcons") { - if (!entry.icons.areIconsAvailable) { - return@traceSection - } - entry.icons.smallIconDescriptor = null - entry.icons.peopleAvatarDescriptor = null + fun updateIcons(entry: NotificationEntry) = + traceSection("IconManager.updateIcons") { + if (!entry.icons.areIconsAvailable) { + return@traceSection + } + entry.icons.smallIconDescriptor = null + entry.icons.peopleAvatarDescriptor = null - val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry) - val notificationContentDescription = entry.sbn.notification?.let { - iconBuilder.getIconContentDescription(it) - } + val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry) + val notificationContentDescription = + entry.sbn.notification?.let { iconBuilder.getIconContentDescription(it) } - entry.icons.statusBarIcon?.let { - it.setNotification(entry.sbn, notificationContentDescription) - setIcon(entry, normalIconDescriptor, it) - } + entry.icons.statusBarIcon?.let { + it.setNotification(entry.sbn, notificationContentDescription) + setIcon(entry, normalIconDescriptor, it) + } - entry.icons.shelfIcon?.let { - it.setNotification(entry.sbn, notificationContentDescription) - setIcon(entry, normalIconDescriptor, it) - } + entry.icons.shelfIcon?.let { + it.setNotification(entry.sbn, notificationContentDescription) + setIcon(entry, sensitiveIconDescriptor, it) + } - entry.icons.aodIcon?.let { - it.setNotification(entry.sbn, notificationContentDescription) - setIcon(entry, sensitiveIconDescriptor, it) + entry.icons.aodIcon?.let { + it.setNotification(entry.sbn, notificationContentDescription) + setIcon(entry, sensitiveIconDescriptor, it) + } } - } private fun updateIconsSafe(entry: NotificationEntry) { try { @@ -173,11 +176,12 @@ class IconManager @Inject constructor( @Throws(InflationException::class) private fun getIconDescriptors(entry: NotificationEntry): Pair<StatusBarIcon, StatusBarIcon> { val iconDescriptor = getIconDescriptor(entry, redact = false) - val sensitiveDescriptor = if (entry.isSensitive) { - getIconDescriptor(entry, redact = true) - } else { - iconDescriptor - } + val sensitiveDescriptor = + if (entry.isSensitive) { + getIconDescriptor(entry, redact = true) + } else { + iconDescriptor + } return Pair(iconDescriptor, sensitiveDescriptor) } @@ -197,14 +201,15 @@ class IconManager @Inject constructor( } val icon = - (if (showPeopleAvatar) { - createPeopleAvatar(entry) - } else { - n.smallIcon - }) ?: throw InflationException( - "No icon in notification from " + entry.sbn.packageName) - - val ic = StatusBarIcon( + (if (showPeopleAvatar) { + createPeopleAvatar(entry) + } else { + n.smallIcon + }) + ?: throw InflationException("No icon in notification from " + entry.sbn.packageName) + + val ic = + StatusBarIcon( entry.sbn.user, entry.sbn.packageName, icon, @@ -282,8 +287,8 @@ class IconManager @Inject constructor( /** * Determines if this icon shows a conversation based on the sensitivity of the icon, its - * context and the user's indicated sensitivity preference. If we're using a fall back icon - * of the small icon, we don't consider this to be showing a conversation + * context and the user's indicated sensitivity preference. If we're using a fall back icon of + * the small icon, we don't consider this to be showing a conversation * * @param iconView The icon that shows the conversation. */ @@ -293,19 +298,20 @@ class IconManager @Inject constructor( iconDescriptor: StatusBarIcon ): Boolean { val usedInSensitiveContext = - iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon + iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon) - return isImportantConversation(entry) && !isSmallIcon && - (!usedInSensitiveContext || !entry.isSensitive) + return isImportantConversation(entry) && + !isSmallIcon && + (!usedInSensitiveContext || !entry.isSensitive) } private fun isImportantConversation(entry: NotificationEntry): Boolean { // Also verify that the Notification is MessagingStyle, since we're going to access // MessagingStyle-specific data (EXTRA_MESSAGES, EXTRA_MESSAGING_PERSON). return entry.ranking.channel != null && - entry.ranking.channel.isImportantConversation && - entry.sbn.notification.isStyle(MessagingStyle::class.java) && - entry.key !in unimportantConversationKeys + entry.ranking.channel.isImportantConversation && + entry.sbn.notification.isStyle(MessagingStyle::class.java) && + entry.key !in unimportantConversationKeys } override fun setUnimportantConversations(keys: Collection<String>) { @@ -323,8 +329,8 @@ private const val TAG = "IconManager" interface ConversationIconManager { /** * Sets the complete current set of notification keys which should (for the purposes of icon - * presentation) be considered unimportant. This tells the icon manager to remove the avatar - * of a group from which the priority notification has been removed. + * presentation) be considered unimportant. This tells the icon manager to remove the avatar of + * a group from which the priority notification has been removed. */ fun setUnimportantConversations(keys: Collection<String>) -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d828ad70f5c4..decb244947ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -849,6 +849,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void setNotificationGroupWhen(long whenMillis) { if (mIsSummaryWithChildren) { mChildrenContainer.setNotificationGroupWhen(whenMillis); + mPublicLayout.setNotificationWhen(whenMillis); } else { Log.w(TAG, "setNotificationGroupWhen( whenMillis: " + whenMillis + ")" + " mIsSummaryWithChildren: false" @@ -2704,6 +2705,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } private void onAttachedChildrenCountChanged() { + final boolean wasSummary = mIsSummaryWithChildren; mIsSummaryWithChildren = mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0; if (mIsSummaryWithChildren) { @@ -2714,6 +2716,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView isConversation()); } } + if (!mIsSummaryWithChildren && wasSummary) { + // Reset the 'when' once the row stops being a summary + mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().when); + } getShowingLayout().updateBackgroundColor(false /* animate */); mPrivateLayout.updateExpandButtons(isExpandable()); updateChildrenAppearance(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 402ea51bebb6..374248252d1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -59,6 +59,7 @@ import com.android.systemui.statusbar.notification.collection.render.GroupMember import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation; import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper; +import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder; @@ -2314,6 +2315,13 @@ public class NotificationContentView extends FrameLayout implements Notification return false; } + public void setNotificationWhen(long whenMillis) { + NotificationViewWrapper wrapper = getNotificationViewWrapper(); + if (wrapper instanceof NotificationHeaderViewWrapper headerViewWrapper) { + headerViewWrapper.setNotificationWhen(whenMillis); + } + } + private static class RemoteInputViewData { @Nullable RemoteInputView mView; @Nullable RemoteInputViewController mController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt index bae5baaf91ed..5551ab46262c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt @@ -22,6 +22,8 @@ import android.graphics.Canvas import android.graphics.Path import android.graphics.RectF import android.util.AttributeSet +import android.util.Log +import com.android.systemui.Flags import com.android.systemui.res.R import com.android.systemui.statusbar.notification.row.ExpandableView @@ -87,4 +89,63 @@ class MediaContainerView(context: Context, attrs: AttributeSet?) : ExpandableVie ) { // No animation, it doesn't need it, this would be local } + + override fun setVisibility(visibility: Int) { + if (Flags.bindKeyguardMediaVisibility()) { + if (isVisibilityValid(visibility)) { + super.setVisibility(visibility) + } + } else { + super.setVisibility(visibility) + } + + assertMediaContainerVisibility(visibility) + } + + /** + * visibility should be aligned with MediaContainerView visibility on the keyguard. + */ + private fun isVisibilityValid(visibility: Int): Boolean { + val currentViewState = viewState as? MediaContainerViewState ?: return true + val shouldBeGone = !currentViewState.shouldBeVisible + return if (shouldBeGone) visibility == GONE else visibility != GONE + } + + /** + * b/298213983 + * MediaContainerView's visibility is changed to VISIBLE when it should be GONE. + * This method check this state and logs. + */ + private fun assertMediaContainerVisibility(visibility: Int) { + val currentViewState = viewState + + if (currentViewState is MediaContainerViewState) { + if (!currentViewState.shouldBeVisible && visibility == VISIBLE) { + Log.wtf("MediaContainerView", "MediaContainerView should be GONE " + + "but its visibility changed to VISIBLE") + } + } + } + + fun setKeyguardVisibility(isVisible: Boolean) { + val currentViewState = viewState + if (currentViewState is MediaContainerViewState) { + currentViewState.shouldBeVisible = isVisible + } + + visibility = if (isVisible) VISIBLE else GONE + } + + override fun createExpandableViewState(): ExpandableViewState = MediaContainerViewState() + + class MediaContainerViewState : ExpandableViewState() { + var shouldBeVisible: Boolean = false + + override fun copyFrom(viewState: ViewState) { + super.copyFrom(viewState) + if (viewState is MediaContainerViewState) { + shouldBeVisible = viewState.shouldBeVisible + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 7925a1ce97ee..e397a70ea1f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -573,7 +573,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * Do notifications dismiss with normal transitioning */ private boolean mDismissUsingRowTranslationX = true; - private NotificationEntry mTopHeadsUpEntry; + private ExpandableNotificationRow mTopHeadsUpRow; private long mNumHeadsUp; private NotificationStackScrollLayoutController.TouchHandler mTouchHandler; private final ScreenOffAnimationController mScreenOffAnimationController; @@ -1688,10 +1688,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * is mainly used when dragging down from a heads up notification. */ private int getTopHeadsUpPinnedHeight() { - if (mTopHeadsUpEntry == null) { + if (mTopHeadsUpRow == null) { return 0; } - ExpandableNotificationRow row = mTopHeadsUpEntry.getRow(); + ExpandableNotificationRow row = mTopHeadsUpRow; if (row.isChildInGroup()) { final NotificationEntry groupSummary = mGroupMembershipManager.getGroupSummary(row.getEntry()); @@ -1872,8 +1872,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (slidingChild instanceof ExpandableNotificationRow row) { NotificationEntry entry = row.getEntry(); if (!mIsExpanded && row.isHeadsUp() && row.isPinned() - && mTopHeadsUpEntry.getRow() != row - && mGroupMembershipManager.getGroupSummary(mTopHeadsUpEntry) != entry) { + && mTopHeadsUpRow != row + && mGroupMembershipManager.getGroupSummary(mTopHeadsUpRow.getEntry()) + != entry) { continue; } return row.getViewAtPosition(touchY - childTop); @@ -5724,8 +5725,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mShelf.updateAppearance(); } - void setTopHeadsUpEntry(NotificationEntry topEntry) { - mTopHeadsUpEntry = topEntry; + void setTopHeadsUpRow(ExpandableNotificationRow topHeadsUpRow) { + mTopHeadsUpRow = topHeadsUpRow; } void setNumHeadsUp(long numHeadsUp) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 8dfac8617ff1..7c138776d5a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -692,7 +692,7 @@ public class NotificationStackScrollLayoutController implements Dumpable { long numEntries = mHeadsUpManager.getAllEntries().count(); NotificationEntry topEntry = mHeadsUpManager.getTopEntry(); mView.setNumHeadsUp(numEntries); - mView.setTopHeadsUpEntry(topEntry); + mView.setTopHeadsUpRow(topEntry != null ? topEntry.getRow() : null); generateHeadsUpAnimation(entry, isHeadsUp); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 634de7a17ef7..1ef9a8f3d7ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -853,7 +853,7 @@ public class StackScrollAlgorithm { } } if (row.isHeadsUpAnimatingAway()) { - if (NotificationsImprovedHunAnimation.isEnabled()) { + if (NotificationsImprovedHunAnimation.isEnabled() && !ambientState.isDozing()) { if (shouldHunAppearFromBottom(ambientState, childState)) { // move to the bottom of the screen childState.setYTranslation( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/SceneContainerFlagsExtension.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/SceneContainerFlagsExtension.kt index 5a71bd6fa116..7dfd53e544c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/SceneContainerFlagsExtension.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/SceneContainerFlagsExtension.kt @@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.stack.shared import com.android.systemui.scene.shared.flag.SceneContainerFlags -private const val FLEXI_NOTIFS = false +private const val FLEXI_NOTIFS = true /** * Returns whether flexiglass is displaying notifications, which is currently an optional piece of diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt index a1577854e732..76495cb23947 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt @@ -20,12 +20,14 @@ import android.content.Context import android.util.TypedValue import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.stack.AmbientState import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel import kotlin.math.roundToInt +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.launch @@ -40,8 +42,9 @@ object NotificationStackAppearanceViewBinder { viewModel: NotificationStackAppearanceViewModel, ambientState: AmbientState, controller: NotificationStackScrollLayoutController, + @Main mainImmediateDispatcher: CoroutineDispatcher, ): DisposableHandle { - return view.repeatWhenAttached { + return view.repeatWhenAttached(mainImmediateDispatcher) { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.stackBounds.collect { bounds -> 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 5191053b6f72..566c0303b286 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 @@ -75,6 +75,24 @@ object SharedNotificationContainerBinder { } } + // Required to capture keyguard media changes and ensure the notification count is correct + val layoutChangeListener = + object : View.OnLayoutChangeListener { + override fun onLayoutChange( + view: View, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + viewModel.notificationStackChanged() + } + } + val burnInParams = MutableStateFlow(BurnInParameters()) val viewState = ViewStateAccessor( @@ -170,6 +188,7 @@ object SharedNotificationContainerBinder { } insets } + view.addOnLayoutChangeListener(layoutChangeListener) return object : DisposableHandle { override fun dispose() { @@ -177,6 +196,7 @@ object SharedNotificationContainerBinder { disposableHandleMainImmediate.dispose() controller.setOnHeightChangedRunnable(null) view.setOnApplyWindowInsetsListener(null) + view.removeOnLayoutChangeListener(layoutChangeListener) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 9052409b4d8d..a1fae03a2090 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -39,11 +39,11 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.AuthKeyguardMessageArea; import com.android.systemui.Dumpable; import com.android.systemui.animation.ActivityTransitionAnimator; +import com.android.systemui.animation.RemoteAnimationRunnerCompat; import com.android.systemui.display.data.repository.DisplayMetricsRepository; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import com.android.systemui.qs.QSPanelController; -import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.util.Compile; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index b772158b0825..db15144340e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -1375,7 +1375,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { || !mKeyguardStateController.canDismissLockScreen() || mKeyguardViewMediator.isAnySimPinSecure() || (mQsController.getExpanded() && trackingTouch) - || mShadeSurface.getBarState() == StatusBarState.SHADE_LOCKED) { + || mShadeSurface.getBarState() == StatusBarState.SHADE_LOCKED + // This last one causes a race condition when the shade resets. Don't send a 0 + // and let StatusBarStateController process a keyguard state change instead + || 1f - fraction == 0f) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 4fd33ba458d8..5610ed926f70 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -55,6 +55,7 @@ import com.android.systemui.EventLogTags; import com.android.systemui.animation.ActivityTransitionAnimator; import com.android.systemui.assist.AssistManager; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.power.domain.interactor.PowerInteractor; @@ -138,7 +139,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit Context context, @DisplayId int displayId, Handler mainThreadHandler, - Executor uiBgExecutor, + @Background Executor uiBgExecutor, NotificationVisibilityProvider visibilityProvider, HeadsUpManager headsUpManager, ActivityStarter activityStarter, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt index f73d089c36b9..3e3ea855ccf7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt @@ -315,8 +315,8 @@ constructor( // TTL for satellite polling is one hour const val POLLING_INTERVAL_MS: Long = 1000 * 60 * 60 - // Let the system boot up (5s) and stabilize before we check for system support - const val MIN_UPTIME: Long = 1000 * 5 + // Let the system boot up and stabilize before we check for system support + const val MIN_UPTIME: Long = 1000 * 60 private const val TAG = "DeviceBasedSatelliteRepo" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt index a078dd5cf28c..2ad4d361df1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt @@ -23,6 +23,7 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.net.Uri +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.res.R import com.android.systemui.util.concurrency.DelayableExecutor import javax.inject.Inject @@ -34,7 +35,7 @@ import javax.inject.Inject class BatteryStateNotifier @Inject constructor( val controller: BatteryController, val noMan: NotificationManager, - val delayableExecutor: DelayableExecutor, + @Background val delayableExecutor: DelayableExecutor, val context: Context ) : BatteryController.BatteryStateChangeCallback { var stateUnknown = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java index 6956a7d8a8e3..18ec68bd89eb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java @@ -51,6 +51,7 @@ import javax.inject.Inject; public class SensitiveNotificationProtectionControllerImpl implements SensitiveNotificationProtectionController { private static final String LOG_TAG = "SNPC"; + private final SensitiveNotificationProtectionControllerLogger mLogger; private final ArraySet<String> mExemptPackages = new ArraySet<>(); private final ListenerSet<Runnable> mListeners = new ListenerSet<>(); private volatile MediaProjectionInfo mProjection; @@ -66,6 +67,7 @@ public class SensitiveNotificationProtectionControllerImpl if (mDisableScreenShareProtections) { Log.w(LOG_TAG, "Screen share protections disabled, ignoring projectionstart"); + mLogger.logProjectionStart(false, info.getPackageName()); return; } @@ -73,6 +75,7 @@ public class SensitiveNotificationProtectionControllerImpl // Launch cookie only set (non-null) if sharing single app/task updateProjectionStateAndNotifyListeners( (info.getLaunchCookie() == null) ? info : null); + mLogger.logProjectionStart(isSensitiveStateActive(), info.getPackageName()); } finally { Trace.endSection(); } @@ -82,6 +85,7 @@ public class SensitiveNotificationProtectionControllerImpl public void onStop(MediaProjectionInfo info) { Trace.beginSection("SNPC.onProjectionStop"); try { + mLogger.logProjectionStop(); updateProjectionStateAndNotifyListeners(null); } finally { Trace.endSection(); @@ -96,7 +100,10 @@ public class SensitiveNotificationProtectionControllerImpl MediaProjectionManager mediaProjectionManager, IActivityManager activityManager, @Main Handler mainHandler, - @Background Executor bgExecutor) { + @Background Executor bgExecutor, + SensitiveNotificationProtectionControllerLogger logger) { + mLogger = logger; + if (!screenshareNotificationHiding()) { return; } @@ -202,8 +209,6 @@ public class SensitiveNotificationProtectionControllerImpl return false; } - // TODO(b/316955558): Add disabled by developer option - return !mExemptPackages.contains(projection.getPackageName()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerLogger.kt new file mode 100644 index 000000000000..70c5239f0ec6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerLogger.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.dagger.SensitiveNotificationProtectionLog +import javax.inject.Inject + +/** Logger for [SensitiveNotificationProtectionController]. */ +class SensitiveNotificationProtectionControllerLogger +@Inject +constructor(@SensitiveNotificationProtectionLog private val buffer: LogBuffer) { + fun logProjectionStart(protectionEnabled: Boolean, pkg: String) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + bool1 = protectionEnabled + str1 = pkg + }, + { "Projection started - protection enabled:$bool1, pkg=$str1" } + ) + } + + fun logProjectionStop() { + buffer.log(TAG, LogLevel.DEBUG, {}, { "Projection ended - protection disabled" }) + } +} + +private const val TAG = "SNPC" diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java index 6124f6383fff..2cad8442e3ba 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java @@ -124,15 +124,6 @@ public abstract class SysUIConcurrencyModule { } /** - * Provide a Background-Thread Executor by default. - */ - @Provides - @SysUISingleton - public static Executor provideExecutor(@Background Looper looper) { - return new ExecutorImpl(looper); - } - - /** * Provide a BroadcastRunning Executor (for sending and receiving broadcasts). */ @Provides @@ -174,15 +165,6 @@ public abstract class SysUIConcurrencyModule { } /** - * Provide a Background-Thread Executor by default. - */ - @Provides - @SysUISingleton - public static DelayableExecutor provideDelayableExecutor(@Background Looper looper) { - return new ExecutorImpl(looper); - } - - /** * Provide a Background-Thread Executor. */ @Provides @@ -193,15 +175,6 @@ public abstract class SysUIConcurrencyModule { } /** - * Provide a Background-Thread Executor by default. - */ - @Provides - @SysUISingleton - public static RepeatableExecutor provideRepeatableExecutor(@Background DelayableExecutor exec) { - return new RepeatableExecutorImpl(exec); - } - - /** * Provide a Background-Thread Executor. */ @Provides diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt index d47413faeadf..bb907cc0055e 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt @@ -245,6 +245,29 @@ fun <T> Flow<T>.throttle(periodMs: Long, clock: SystemClock = SystemClockImpl()) } } +inline fun <T1, T2, T3, T4, T5, T6, R> combine( + flow: Flow<T1>, + flow2: Flow<T2>, + flow3: Flow<T3>, + flow4: Flow<T4>, + flow5: Flow<T5>, + flow6: Flow<T6>, + crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R +): Flow<R> { + return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6) { + args: Array<*> -> + @Suppress("UNCHECKED_CAST") + transform( + args[0] as T1, + args[1] as T2, + args[2] as T3, + args[3] as T4, + args[4] as T5, + args[5] as T6, + ) + } +} + inline fun <T1, T2, T3, T4, T5, T6, T7, R> combine( flow: Flow<T1>, flow2: Flow<T2>, diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt index fa0d0306f157..a88be065d722 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt @@ -36,6 +36,17 @@ class Utils { fun <A, B, C, D, E, F> toSextuple(a: A, bcdef: Quint<B, C, D, E, F>) = Sextuple(a, bcdef.first, bcdef.second, bcdef.third, bcdef.fourth, bcdef.fifth) + fun <A, B, C, D, E, F, G> toSeptuple(a: A, bcdefg: Sextuple<B, C, D, E, F, G>) = + Septuple( + a, + bcdefg.first, + bcdefg.second, + bcdefg.third, + bcdefg.fourth, + bcdefg.fifth, + bcdefg.sixth + ) + /** * Samples the provided flows, emitting a tuple of the original flow's value as well as each * of the combined flows' values. @@ -90,6 +101,24 @@ class Utils { ): Flow<Sextuple<A, B, C, D, E, F>> { return this.sample(combine(b, c, d, e, f, ::Quint), ::toSextuple) } + + /** + * Samples the provided flows, emitting a tuple of the original flow's value as well as each + * of the combined flows' values. + * + * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>, Flow<G>) -> (A, B, C, D, E, + * F, G) + */ + fun <A, B, C, D, E, F, G> Flow<A>.sample( + b: Flow<B>, + c: Flow<C>, + d: Flow<D>, + e: Flow<E>, + f: Flow<F>, + g: Flow<G>, + ): Flow<Septuple<A, B, C, D, E, F, G>> { + return this.sample(combine(b, c, d, e, f, g, ::Sextuple), ::toSeptuple) + } } } @@ -112,6 +141,16 @@ data class Sextuple<A, B, C, D, E, F>( val sixth: F, ) +data class Septuple<A, B, C, D, E, F, G>( + val first: A, + val second: B, + val third: C, + val fourth: D, + val fifth: E, + val sixth: F, + val seventh: G, +) + fun Int.toPx(context: Context): Int { return (this * context.resources.displayMetrics.density).toInt() } diff --git a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java index 3d724e1caa5d..0dcbe9b2bfc4 100644 --- a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java +++ b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java @@ -158,11 +158,11 @@ public class ObservableServiceConnection<T> implements ServiceConnection { try { bindResult = mContext.bindServiceAsUser(mServiceIntent, this, mFlags, mUserTracker.getUserHandle()); + mBoundCalled = true; } catch (SecurityException e) { Log.d(TAG, "Could not bind to service", e); mContext.unbindService(this); } - mBoundCalled = true; if (DEBUG) { Log.d(TAG, "bind. bound:" + bindResult); } diff --git a/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java b/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java index 9b72eb710588..5979f3e60cb9 100644 --- a/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java +++ b/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java @@ -28,6 +28,7 @@ import android.util.Log; import androidx.annotation.NonNull; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.time.SystemClock; @@ -94,10 +95,12 @@ public class PersistentConnectionManager<T> implements Dumpable { } }; + // TODO: b/326449074 - Ensure the DelayableExecutor is on the correct thread, and update the + // qualifier (to @Main) or name (to bgExecutor) to be consistent with that. @Inject public PersistentConnectionManager( SystemClock clock, - DelayableExecutor mainExecutor, + @Background DelayableExecutor mainExecutor, DumpManager dumpManager, @Named(DUMPSYS_NAME) String dumpsysName, @Named(SERVICE_CONNECTION) ObservableServiceConnection<T> serviceConnection, diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt index 67d6a7f5d735..9dedf5c70da1 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/AudioModule.kt @@ -16,19 +16,15 @@ package com.android.systemui.volume.dagger -import android.app.NotificationManager import android.content.Context import android.media.AudioManager -import com.android.settingslib.media.data.repository.SpatializerRepository -import com.android.settingslib.media.data.repository.SpatializerRepositoryImpl -import com.android.settingslib.media.domain.interactor.SpatializerInteractor -import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepository -import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepositoryImpl +import com.android.settingslib.statusbar.notification.domain.interactor.NotificationsSoundPolicyInteractor import com.android.settingslib.volume.data.repository.AudioRepository import com.android.settingslib.volume.data.repository.AudioRepositoryImpl import com.android.settingslib.volume.domain.interactor.AudioModeInteractor -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiverImpl +import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver +import com.android.settingslib.volume.shared.AudioManagerEventsReceiverImpl import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import dagger.Module @@ -46,11 +42,11 @@ interface AudioModule { fun provideAudioManagerIntentsReceiver( @Application context: Context, @Application coroutineScope: CoroutineScope, - ): AudioManagerIntentsReceiver = AudioManagerIntentsReceiverImpl(context, coroutineScope) + ): AudioManagerEventsReceiver = AudioManagerEventsReceiverImpl(context, coroutineScope) @Provides fun provideAudioRepository( - intentsReceiver: AudioManagerIntentsReceiver, + intentsReceiver: AudioManagerEventsReceiver, audioManager: AudioManager, @Background coroutineContext: CoroutineContext, @Application coroutineScope: CoroutineScope, @@ -62,28 +58,10 @@ interface AudioModule { AudioModeInteractor(repository) @Provides - fun provdieSpatializerRepository( - audioManager: AudioManager, - @Background backgroundContext: CoroutineContext, - ): SpatializerRepository = - SpatializerRepositoryImpl(audioManager.spatializer, backgroundContext) - - @Provides - fun provideSpatializerInetractor(repository: SpatializerRepository): SpatializerInteractor = - SpatializerInteractor(repository) - - @Provides - fun provideNotificationsSoundPolicyRepository( - context: Context, - notificationManager: NotificationManager, - @Background coroutineContext: CoroutineContext, - @Application coroutineScope: CoroutineScope, - ): NotificationsSoundPolicyRepository = - NotificationsSoundPolicyRepositoryImpl( - context, - notificationManager, - coroutineScope, - coroutineContext, - ) + fun provideAudioVolumeInteractor( + audioRepository: AudioRepository, + notificationsSoundPolicyInteractor: NotificationsSoundPolicyInteractor, + ): AudioVolumeInteractor = + AudioVolumeInteractor(audioRepository, notificationsSoundPolicyInteractor) } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/MediaDevicesModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/MediaDevicesModule.kt index 9f99e9778ef2..d134e60ef72f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/MediaDevicesModule.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/MediaDevicesModule.kt @@ -18,9 +18,11 @@ package com.android.systemui.volume.dagger import android.media.session.MediaSessionManager import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.settingslib.volume.data.repository.LocalMediaRepository import com.android.settingslib.volume.data.repository.MediaControllerRepository import com.android.settingslib.volume.data.repository.MediaControllerRepositoryImpl -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver +import com.android.settingslib.volume.domain.interactor.LocalMediaInteractor +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -44,8 +46,21 @@ interface MediaDevicesModule { @Provides @SysUISingleton + fun provideLocalMediaRepository( + factory: LocalMediaRepositoryFactory + ): LocalMediaRepository = factory.create(null) + + @Provides + @SysUISingleton + fun provideLocalMediaInteractor( + repository: LocalMediaRepository, + @Application scope: CoroutineScope, + ): LocalMediaInteractor = LocalMediaInteractor(repository, scope) + + @Provides + @SysUISingleton fun provideMediaDeviceSessionRepository( - intentsReceiver: AudioManagerIntentsReceiver, + intentsReceiver: AudioManagerEventsReceiver, mediaSessionManager: MediaSessionManager, localBluetoothManager: LocalBluetoothManager?, @Application coroutineScope: CoroutineScope, diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt new file mode 100644 index 000000000000..18a9161ac0e3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.dagger + +import android.media.AudioManager +import android.media.Spatializer +import com.android.settingslib.media.data.repository.SpatializerRepository +import com.android.settingslib.media.data.repository.SpatializerRepositoryImpl +import com.android.settingslib.media.domain.interactor.SpatializerInteractor +import com.android.systemui.dagger.qualifiers.Background +import dagger.Module +import dagger.Provides +import kotlin.coroutines.CoroutineContext + +/** Spatializer module. */ +@Module +interface SpatializerModule { + companion object { + @Provides + fun provideSpatializer( + audioManager: AudioManager, + ): Spatializer = audioManager.spatializer + + @Provides + fun provdieSpatializerRepository( + spatializer: Spatializer, + @Background backgroundContext: CoroutineContext, + ): SpatializerRepository = SpatializerRepositoryImpl(spatializer, backgroundContext) + + @Provides + fun provideSpatializerInetractor(repository: SpatializerRepository): SpatializerInteractor = + SpatializerInteractor(repository) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java index c6aee428ce6a..64a5644bc452 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java @@ -59,7 +59,8 @@ import dagger.multibindings.IntoSet; AudioModule.class, AncModule.class, CaptioningModule.class, - MediaDevicesModule.class + MediaDevicesModule.class, + SpatializerModule.class, }, subcomponents = { VolumePanelComponent.class diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/LocalMediaRepositoryFactory.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/LocalMediaRepositoryFactory.kt index d8cd128af0c5..11b4690e59ee 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/LocalMediaRepositoryFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/LocalMediaRepositoryFactory.kt @@ -18,7 +18,7 @@ package com.android.systemui.volume.panel.component.mediaoutput.data.repository import android.media.MediaRouter2Manager import com.android.settingslib.volume.data.repository.LocalMediaRepository import com.android.settingslib.volume.data.repository.LocalMediaRepositoryImpl -import com.android.settingslib.volume.shared.AudioManagerIntentsReceiver +import com.android.settingslib.volume.shared.AudioManagerEventsReceiver import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.media.controls.util.LocalMediaManagerFactory @@ -34,7 +34,7 @@ interface LocalMediaRepositoryFactory { class LocalMediaRepositoryFactoryImpl @Inject constructor( - private val intentsReceiver: AudioManagerIntentsReceiver, + private val eventsReceiver: AudioManagerEventsReceiver, private val mediaRouter2Manager: MediaRouter2Manager, private val localMediaManagerFactory: LocalMediaManagerFactory, @Application private val coroutineScope: CoroutineScope, @@ -43,7 +43,7 @@ constructor( override fun create(packageName: String?): LocalMediaRepository = LocalMediaRepositoryImpl( - intentsReceiver, + eventsReceiver, localMediaManagerFactory.create(packageName), mediaRouter2Manager, coroutineScope, diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt index f11ac5e1a8e4..9d801fc9bfa1 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt @@ -22,6 +22,7 @@ object VolumePanelComponents { const val MEDIA_OUTPUT: VolumePanelComponentKey = "media_output" const val BOTTOM_BAR: VolumePanelComponentKey = "bottom_bar" + const val VOLUME_SLIDERS: VolumePanelComponentKey = "volume_sliders" const val CAPTIONING: VolumePanelComponentKey = "captioning" const val ANC: VolumePanelComponentKey = "anc" } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/CastVolumeInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/CastVolumeInteractor.kt new file mode 100644 index 000000000000..6b62074e023d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/CastVolumeInteractor.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.domain.interactor + +import com.android.settingslib.volume.domain.interactor.LocalMediaInteractor +import com.android.settingslib.volume.domain.model.RoutingSession +import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn + +/** Provides a remote media casting state. */ +@VolumePanelScope +class CastVolumeInteractor +@Inject +constructor( + @VolumePanelScope private val coroutineScope: CoroutineScope, + private val localMediaInteractor: LocalMediaInteractor, +) { + + /** Returns a list of [RoutingSession] to show in the UI. */ + val remoteRoutingSessions: StateFlow<List<RoutingSession>> = + localMediaInteractor.remoteRoutingSessions + .map { it.filter { routingSession -> routingSession.isVolumeSeekBarEnabled } } + .stateIn(coroutineScope, SharingStarted.Eagerly, emptyList()) + + /** Sets [routingSession] volume to [volume]. */ + suspend fun setVolume(routingSession: RoutingSession, volume: Int) { + localMediaInteractor.adjustSessionVolume(routingSession.routingSessionInfo.id, volume) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt new file mode 100644 index 000000000000..0c91bbf60f1b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.domain.interactor + +import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import javax.inject.Inject + +/** Converts from slider value to volume and back. */ +@VolumePanelScope +class VolumeSliderInteractor @Inject constructor() { + + /** mimic percentage volume setting */ + val displayValueRange: ClosedFloatingPointRange<Float> = 0f..100f + + /** + * Translates [volume], that belongs to [volumeRange] to the value that belongs to + * [displayValueRange]. + * + * [currentValue] is the raw value received from the slider. Returns [currentValue] when it + * translates to the same volume as [volume] parameter. This ensures smooth slider experience + * (avoids snapping when the user stops dragging). + */ + fun processVolumeToValue( + volume: Int, + volumeRange: ClosedRange<Int>, + currentValue: Float?, + isMuted: Boolean, + ): Float { + if (isMuted) { + return 0f + } + val changedVolume: Int? = currentValue?.let { translateValueToVolume(it, volumeRange) } + return if (volume != volumeRange.start && volume == changedVolume) { + currentValue + } else { + translateToRange( + currentValue = volume.toFloat(), + currentRangeStart = volumeRange.start.toFloat(), + currentRangeEnd = volumeRange.endInclusive.toFloat(), + targetRangeStart = displayValueRange.start, + targetRangeEnd = displayValueRange.endInclusive, + ) + } + } + + /** Translates [value] from [displayValueRange] to volume that has [volumeRange]. */ + fun translateValueToVolume( + value: Float, + volumeRange: ClosedRange<Int>, + ): Int { + return translateToRange( + currentValue = value, + currentRangeStart = displayValueRange.start, + currentRangeEnd = displayValueRange.endInclusive, + targetRangeStart = volumeRange.start.toFloat(), + targetRangeEnd = volumeRange.endInclusive.toFloat(), + ) + .toInt() + } + + /** + * Translates a value from one range to another. + * + * ``` + * Given: currentValue=3, currentRange=[0, 8], targetRange=[0, 100] + * Result: 37.5 + * ``` + */ + private fun translateToRange( + currentValue: Float, + currentRangeStart: Float, + currentRangeEnd: Float, + targetRangeStart: Float, + targetRangeEnd: Float, + ): Float { + val currentRangeLength: Float = (currentRangeEnd - currentRangeStart) + val targetRangeLength: Float = targetRangeEnd - targetRangeStart + if (currentRangeLength == 0f || targetRangeLength == 0f) { + return 0f + } + val volumeFraction: Float = (currentValue - currentRangeStart) / currentRangeLength + return targetRangeStart + volumeFraction * targetRangeLength + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt new file mode 100644 index 000000000000..b97123b29b68 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.domain.model + +import com.android.settingslib.volume.shared.model.AudioStream + +/** The type of volume slider that can be shown at the UI. */ +sealed interface SliderType { + + /** The slider represents one of the device volume streams. */ + data class Stream(val stream: AudioStream) : SliderType + + /** The represents media device casting volume. */ + data object MediaDeviceCast : SliderType +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt new file mode 100644 index 000000000000..faf743475579 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel + +import android.content.Context +import android.media.AudioManager +import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor +import com.android.settingslib.volume.shared.model.AudioStream +import com.android.settingslib.volume.shared.model.AudioStreamModel +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.res.R +import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch + +/** Models a particular slider state. */ +class AudioStreamSliderViewModel +@AssistedInject +constructor( + @Assisted private val audioStreamWrapper: FactoryAudioStreamWrapper, + @Assisted private val coroutineScope: CoroutineScope, + private val context: Context, + private val audioVolumeInteractor: AudioVolumeInteractor, + private val volumeSliderInteractor: VolumeSliderInteractor, +) : SliderViewModel { + + private val audioStream = audioStreamWrapper.audioStream + private val iconsByStream = + mapOf( + AudioStream(AudioManager.STREAM_MUSIC) to R.drawable.ic_music_note, + AudioStream(AudioManager.STREAM_VOICE_CALL) to R.drawable.ic_call, + AudioStream(AudioManager.STREAM_RING) to R.drawable.ic_ring_volume, + AudioStream(AudioManager.STREAM_NOTIFICATION) to R.drawable.ic_volume_ringer, + AudioStream(AudioManager.STREAM_ALARM) to R.drawable.ic_volume_alarm, + ) + private val mutedIconsByStream = + mapOf( + AudioStream(AudioManager.STREAM_MUSIC) to R.drawable.ic_volume_off, + AudioStream(AudioManager.STREAM_VOICE_CALL) to R.drawable.ic_volume_off, + AudioStream(AudioManager.STREAM_RING) to R.drawable.ic_volume_off, + AudioStream(AudioManager.STREAM_NOTIFICATION) to R.drawable.ic_volume_off, + AudioStream(AudioManager.STREAM_ALARM) to R.drawable.ic_volume_off, + ) + private val labelsByStream = + mapOf( + AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_music, + AudioStream(AudioManager.STREAM_VOICE_CALL) to R.string.stream_voice_call, + AudioStream(AudioManager.STREAM_RING) to R.string.stream_ring, + AudioStream(AudioManager.STREAM_NOTIFICATION) to R.string.stream_notification, + AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm, + ) + private val disabledTextByStream = + mapOf( + AudioStream(AudioManager.STREAM_NOTIFICATION) to + R.string.stream_notification_unavailable, + ) + + private var value = 0f + override val slider: StateFlow<SliderState> = + combine( + audioVolumeInteractor.getAudioStream(audioStream), + audioVolumeInteractor.canChangeVolume(audioStream), + ) { model, isEnabled -> + model.toState(value, isEnabled) + } + .stateIn(coroutineScope, SharingStarted.Eagerly, EmptyState) + + override fun onValueChangeFinished(state: SliderState, newValue: Float) { + val audioViewModel = state as? State + audioViewModel ?: return + coroutineScope.launch { + value = newValue + val volume = + volumeSliderInteractor.translateValueToVolume( + newValue, + audioViewModel.audioStreamModel.volumeRange + ) + audioVolumeInteractor.setVolume(audioStream, volume) + } + } + + private fun AudioStreamModel.toState(value: Float, isEnabled: Boolean): State { + return State( + value = + volumeSliderInteractor.processVolumeToValue( + volume, + volumeRange, + value, + isMuted, + ), + valueRange = volumeSliderInteractor.displayValueRange, + icon = getIcon(this), + label = labelsByStream[audioStream]?.let(context::getString) + ?: error("No label for the stream: $audioStream"), + disabledMessage = disabledTextByStream[audioStream]?.let(context::getString), + isEnabled = isEnabled, + audioStreamModel = this, + ) + } + + private fun getIcon(model: AudioStreamModel): Icon { + val isMutedOrNoVolume = model.isMuted || model.volume == model.minVolume + val iconRes = + if (isMutedOrNoVolume) { + mutedIconsByStream + } else { + iconsByStream + }[audioStream] + ?: error("No icon for the stream: $audioStream") + return Icon.Resource(iconRes, null) + } + + private val AudioStreamModel.volumeRange: IntRange + get() = minVolume..maxVolume + + private data class State( + override val value: Float, + override val valueRange: ClosedFloatingPointRange<Float>, + override val icon: Icon, + override val label: String, + override val disabledMessage: String?, + override val isEnabled: Boolean, + val audioStreamModel: AudioStreamModel, + ) : SliderState + + private data object EmptyState : SliderState { + override val value: Float = 0f + override val valueRange: ClosedFloatingPointRange<Float> = 0f..1f + override val icon: Icon? = null + override val label: String = "" + override val disabledMessage: String? = null + override val isEnabled: Boolean = true + } + + @AssistedFactory + interface Factory { + + fun create( + audioStream: FactoryAudioStreamWrapper, + coroutineScope: CoroutineScope, + ): AudioStreamSliderViewModel + } + + /** + * AudioStream is a value class that compiles into a primitive. This fail AssistedFactory build + * when using [AudioStream] directly because it expects another type. + */ + class FactoryAudioStreamWrapper(val audioStream: AudioStream) +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt new file mode 100644 index 000000000000..ae93826c0c17 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel + +import android.content.Context +import com.android.settingslib.volume.domain.model.RoutingSession +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.res.R +import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor +import com.android.systemui.volume.panel.component.volume.domain.interactor.CastVolumeInteractor +import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch + +class CastVolumeSliderViewModel +@AssistedInject +constructor( + @Assisted private val routingSession: RoutingSession, + @Assisted private val coroutineScope: CoroutineScope, + private val context: Context, + mediaOutputInteractor: MediaOutputInteractor, + private val volumeSliderInteractor: VolumeSliderInteractor, + private val castVolumeInteractor: CastVolumeInteractor, +) : SliderViewModel { + + private val volumeRange = 0..routingSession.routingSessionInfo.volumeMax + private val value = MutableStateFlow(0f) + + override val slider: StateFlow<SliderState> = + combine(value, mediaOutputInteractor.currentConnectedDevice) { value, _ -> + getCurrentState(value) + } + .stateIn(coroutineScope, SharingStarted.Eagerly, getCurrentState(value.value)) + + override fun onValueChangeFinished(state: SliderState, newValue: Float) { + coroutineScope.launch { + value.value = newValue + castVolumeInteractor.setVolume( + routingSession, + volumeSliderInteractor.translateValueToVolume(newValue, volumeRange), + ) + } + } + + private fun getCurrentState(value: Float): State { + return State( + value = + volumeSliderInteractor.processVolumeToValue( + volume = routingSession.routingSessionInfo.volume, + volumeRange = volumeRange, + currentValue = value, + isMuted = false, + ), + valueRange = volumeSliderInteractor.displayValueRange, + icon = Icon.Resource(R.drawable.ic_cast, null), + label = context.getString(R.string.media_device_cast), + isEnabled = true, + ) + } + + private data class State( + override val value: Float, + override val valueRange: ClosedFloatingPointRange<Float>, + override val icon: Icon, + override val label: String, + override val isEnabled: Boolean, + ) : SliderState { + override val disabledMessage: String? + get() = null + } + + @AssistedFactory + interface Factory { + + fun create( + routingSession: RoutingSession, + coroutineScope: CoroutineScope, + ): CastVolumeSliderViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt new file mode 100644 index 000000000000..6e9794b02143 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel + +import com.android.systemui.common.shared.model.Icon + +/** + * Models a state of a volume slider. + * + * @property disabledMessage is shown when [isEnabled] is false + */ +sealed interface SliderState { + val value: Float + val valueRange: ClosedFloatingPointRange<Float> + val icon: Icon? + val label: String + val disabledMessage: String? + val isEnabled: Boolean +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt new file mode 100644 index 000000000000..0c4b3222e34d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel + +import kotlinx.coroutines.flow.StateFlow + +/** Controls the behaviour of a volume slider. */ +interface SliderViewModel { + + val slider: StateFlow<SliderState> + + fun onValueChangeFinished(state: SliderState, newValue: Float) +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt new file mode 100644 index 000000000000..2824323775d3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.volume.ui.viewmodel + +import android.media.AudioManager +import com.android.settingslib.volume.shared.model.AudioStream +import com.android.systemui.volume.panel.component.volume.domain.interactor.CastVolumeInteractor +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel +import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel +import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.transformLatest + +/** + * Controls the behaviour of the whole audio + * [com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent]. + */ +@OptIn(ExperimentalCoroutinesApi::class) +@VolumePanelScope +class AudioVolumeComponentViewModel +@Inject +constructor( + @VolumePanelScope private val scope: CoroutineScope, + castVolumeInteractor: CastVolumeInteractor, + private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, + private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, +) { + + private val remoteSessionsViewModels: Flow<List<SliderViewModel>> = + castVolumeInteractor.remoteRoutingSessions.transformLatest { routingSessions -> + coroutineScope { + emit( + routingSessions.map { routingSession -> + castVolumeSliderViewModelFactory.create(routingSession, this) + } + ) + } + } + private val streamViewModels: Flow<List<SliderViewModel>> = + flowOf( + listOf( + AudioStream(AudioManager.STREAM_MUSIC), + AudioStream(AudioManager.STREAM_VOICE_CALL), + AudioStream(AudioManager.STREAM_RING), + AudioStream(AudioManager.STREAM_NOTIFICATION), + AudioStream(AudioManager.STREAM_ALARM), + ) + ) + .transformLatest { streams -> + coroutineScope { + emit( + streams.map { stream -> + streamSliderViewModelFactory.create( + AudioStreamSliderViewModel.FactoryAudioStreamWrapper(stream), + this, + ) + } + ) + } + } + + val sliderViewModels: StateFlow<List<SliderViewModel>> = + combine(remoteSessionsViewModels, streamViewModels) { + remoteSessionsViewModels, + streamViewModels -> + remoteSessionsViewModels + streamViewModels + } + .stateIn(scope, SharingStarted.Eagerly, emptyList()) +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt index df4972aeafea..f31ee865eaac 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt @@ -20,6 +20,7 @@ import com.android.systemui.volume.panel.component.anc.AncModule import com.android.systemui.volume.panel.component.bottombar.BottomBarModule import com.android.systemui.volume.panel.component.captioning.CaptioningModule import com.android.systemui.volume.panel.component.mediaoutput.MediaOutputModule +import com.android.systemui.volume.panel.component.volume.VolumeSlidersModule import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.domain.DomainModule @@ -48,6 +49,7 @@ import kotlinx.coroutines.CoroutineScope // Components modules BottomBarModule::class, AncModule::class, + VolumeSlidersModule::class, CaptioningModule::class, MediaOutputModule::class, ] diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt index 0d65c429eac6..57ea9972012f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt @@ -52,6 +52,7 @@ interface DomainModule { return setOf( VolumePanelComponents.ANC, VolumePanelComponents.CAPTIONING, + VolumePanelComponents.VOLUME_SLIDERS, VolumePanelComponents.MEDIA_OUTPUT, VolumePanelComponents.BOTTOM_BAR, ) diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelState.kt index 7f33a6bb70f9..f57e2931c9b3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelState.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelState.kt @@ -23,12 +23,12 @@ import android.content.res.Configuration.Orientation * State of the Volume Panel itself. * * @property orientation is current Volume Panel orientation - * @property isWideScreen is true when Volume Panel should use wide-screen layout and false the + * @property isLargeScreen is true when Volume Panel should use wide-screen layout and false the * otherwise */ data class VolumePanelState( @Orientation val orientation: Int, - val isWideScreen: Boolean, + val isLargeScreen: Boolean, val isVisible: Boolean, ) { init { diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt index 3c5b75cfb349..5ae827ff4e3d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt @@ -76,7 +76,7 @@ class VolumePanelViewModel( VolumePanelState( orientation = configuration.orientation, isVisible = isVisible, - isWideScreen = !resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog), + isLargeScreen = resources.getBoolean(R.bool.volume_panel_is_large_screen), ) } .stateIn( @@ -85,7 +85,7 @@ class VolumePanelViewModel( VolumePanelState( orientation = resources.configuration.orientation, isVisible = mutablePanelVisibility.value, - isWideScreen = !resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog) + isLargeScreen = resources.getBoolean(R.bool.volume_panel_is_large_screen) ), ) val componentsLayout: Flow<ComponentsLayout> = diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java index 139d190ae63c..65dede83f3d6 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java @@ -25,6 +25,7 @@ import static android.service.notification.NotificationListenerService.REASON_GR import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; +import static com.android.server.notification.Flags.screenshareNotificationHiding; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; @@ -69,6 +70,7 @@ import com.android.systemui.statusbar.notification.collection.render.Notificatio import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.wm.shell.bubbles.Bubble; import com.android.wm.shell.bubbles.BubbleEntry; @@ -102,6 +104,7 @@ public class BubblesManager { private final NotificationVisibilityProvider mVisibilityProvider; private final VisualInterruptionDecisionProvider mVisualInterruptionDecisionProvider; private final NotificationLockscreenUserManager mNotifUserManager; + private final SensitiveNotificationProtectionController mSensitiveNotifProtectionController; private final CommonNotifCollection mCommonNotifCollection; private final NotifPipeline mNotifPipeline; private final NotifPipelineFlags mNotifPipelineFlags; @@ -111,6 +114,7 @@ public class BubblesManager { // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline private final List<NotifCallback> mCallbacks = new ArrayList<>(); private final StatusBarWindowCallback mStatusBarWindowCallback; + private final Runnable mSensitiveStateChangedListener; private boolean mPanelExpanded; /** @@ -130,6 +134,7 @@ public class BubblesManager { VisualInterruptionDecisionProvider visualInterruptionDecisionProvider, ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, + SensitiveNotificationProtectionController sensitiveNotificationProtectionController, CommonNotifCollection notifCollection, NotifPipeline notifPipeline, SysUiState sysUiState, @@ -149,6 +154,7 @@ public class BubblesManager { visualInterruptionDecisionProvider, zenModeController, notifUserManager, + sensitiveNotificationProtectionController, notifCollection, notifPipeline, sysUiState, @@ -173,6 +179,7 @@ public class BubblesManager { VisualInterruptionDecisionProvider visualInterruptionDecisionProvider, ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, + SensitiveNotificationProtectionController sensitiveNotificationProtectionController, CommonNotifCollection notifCollection, NotifPipeline notifPipeline, SysUiState sysUiState, @@ -188,6 +195,7 @@ public class BubblesManager { mVisibilityProvider = visibilityProvider; mVisualInterruptionDecisionProvider = visualInterruptionDecisionProvider; mNotifUserManager = notifUserManager; + mSensitiveNotifProtectionController = sensitiveNotificationProtectionController; mCommonNotifCollection = notifCollection; mNotifPipeline = notifPipeline; mNotifPipelineFlags = notifPipelineFlags; @@ -251,6 +259,22 @@ public class BubblesManager { }; notificationShadeWindowController.registerCallback(mStatusBarWindowCallback); + mSensitiveStateChangedListener = new Runnable() { + @Override + public void run() { + if (!screenshareNotificationHiding()) { + return; + } + bubbles.onSensitiveNotificationProtectionStateChanged( + mSensitiveNotifProtectionController.isSensitiveStateActive()); + } + }; + + if (screenshareNotificationHiding()) { + mSensitiveNotifProtectionController + .registerSensitiveStateListener(mSensitiveStateChangedListener); + } + mSysuiProxy = new Bubbles.SysuiProxy() { @Override public void isNotificationPanelExpand(Consumer<Boolean> callback) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java index c2ed7d4a9d3c..976cd5bd21c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java @@ -21,6 +21,7 @@ import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTIO import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -89,6 +90,7 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { mMenuView = spy(new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance, mSecureSettings)); mMenuView.setTranslationY(halfScreenHeight); + doNothing().when(mMenuView).gotoEditScreen(); mMenuViewLayer = spy(new MenuViewLayer( mContext, stubWindowManager, mAccessibilityManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java index ce4db8febb6c..3862b0f5cf74 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java @@ -160,6 +160,7 @@ public class MenuViewLayerTest extends SysuiTestCase { new MenuView(mSpyContext, mMenuViewModel, menuViewAppearance, mSecureSettings)); // Ensure tests don't actually update metrics. doNothing().when(mMenuView).incrementTexMetric(any(), anyInt()); + doNothing().when(mMenuView).gotoEditScreen(); mMenuViewLayer = spy(new MenuViewLayer(mSpyContext, mStubWindowManager, mStubAccessibilityManager, mMenuViewModel, menuViewAppearance, mMenuView, diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java index 7c97f53d539d..1ce65258ef4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java @@ -21,6 +21,7 @@ import static android.app.UiModeManager.MODE_NIGHT_YES; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -80,6 +81,7 @@ public class MenuViewTest extends SysuiTestCase { mUiModeManager.setNightMode(MODE_NIGHT_YES); mSpyContext = spy(mContext); + doNothing().when(mSpyContext).startActivity(any()); final SecureSettings secureSettings = TestUtils.mockSecureSettings(); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, secureSettings); @@ -179,8 +181,6 @@ public class MenuViewTest extends SysuiTestCase { @Test @EnableFlags(Flags.FLAG_FLOATING_MENU_DRAG_TO_EDIT) public void gotoEditScreen_sendsIntent() { - // Notably, this shouldn't crash the settings app, - // because the button target args are configured. mMenuView.gotoEditScreen(); verify(mSpyContext).startActivity(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt index 9f24d5dfea79..f5e96c93271a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt @@ -237,6 +237,35 @@ class FacePropertyRepositoryImplTest : SysuiTestCase() { } } + @Test + fun providesTheCameraInfoOnCameraAvailableChange() { + testScope.runTest { + runCurrent() + collectLastValue(underTest.cameraInfo) + + verify(faceManager).addAuthenticatorsRegisteredCallback(callback.capture()) + callback.value.onAllAuthenticatorsRegistered( + listOf(createSensorProperties(1, SensorProperties.STRENGTH_STRONG)) + ) + runCurrent() + verify(cameraManager) + .registerAvailabilityCallback(any(Executor::class.java), cameraCallback.capture()) + + cameraCallback.value.onPhysicalCameraAvailable("0", PHYSICAL_CAMERA_ID_OUTER_FRONT) + runCurrent() + + val cameraInfo by collectLastValue(underTest.cameraInfo) + assertThat(cameraInfo) + .isEqualTo( + CameraInfo( + "0", + PHYSICAL_CAMERA_ID_OUTER_FRONT, + Point(OUTER_FRONT_SENSOR_LOCATION[0], OUTER_FRONT_SENSOR_LOCATION[1]) + ) + ) + } + } + private fun createSensorProperties(id: Int, strength: Int) = FaceSensorPropertiesInternal(id, strength, 0, emptyList(), 1, false, false, false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index ff68fe3df9e9..140849b8e257 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -241,19 +241,27 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa viewModel.showAuthenticated(testCase.authenticatedModality, 1_000L) - val confirmConstant by collectLastValue(viewModel.hapticsToPlay) - assertThat(confirmConstant) + val confirmHaptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(confirmHaptics?.hapticFeedbackConstant) .isEqualTo( if (expectConfirmation) HapticFeedbackConstants.NO_HAPTICS else HapticFeedbackConstants.CONFIRM ) + assertThat(confirmHaptics?.flag) + .isEqualTo( + if (expectConfirmation) null + else HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING + ) if (expectConfirmation) { viewModel.confirmAuthenticated() } - val confirmedConstant by collectLastValue(viewModel.hapticsToPlay) - assertThat(confirmedConstant).isEqualTo(HapticFeedbackConstants.CONFIRM) + val confirmedHaptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(confirmedHaptics?.hapticFeedbackConstant) + .isEqualTo(HapticFeedbackConstants.CONFIRM) + assertThat(confirmedHaptics?.flag) + .isEqualTo(HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) } @Test @@ -265,16 +273,21 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa viewModel.confirmAuthenticated() } - val currentConstant by collectLastValue(viewModel.hapticsToPlay) - assertThat(currentConstant).isEqualTo(HapticFeedbackConstants.CONFIRM) + val currentHaptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(currentHaptics?.hapticFeedbackConstant) + .isEqualTo(HapticFeedbackConstants.CONFIRM) + assertThat(currentHaptics?.flag) + .isEqualTo(HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) } @Test fun playErrorHaptic_SetsRejectConstant() = runGenericTest { viewModel.showTemporaryError("test", "messageAfterError", false) - val currentConstant by collectLastValue(viewModel.hapticsToPlay) - assertThat(currentConstant).isEqualTo(HapticFeedbackConstants.REJECT) + val currentHaptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(currentHaptics?.hapticFeedbackConstant).isEqualTo(HapticFeedbackConstants.REJECT) + assertThat(currentHaptics?.flag) + .isEqualTo(HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) } @Test @@ -800,8 +813,9 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa hapticFeedback = true, ) - val constant by collectLastValue(viewModel.hapticsToPlay) - assertThat(constant).isEqualTo(HapticFeedbackConstants.REJECT) + val haptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(haptics?.hapticFeedbackConstant).isEqualTo(HapticFeedbackConstants.REJECT) + assertThat(haptics?.flag).isEqualTo(HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) } @Test @@ -813,8 +827,8 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa hapticFeedback = false, ) - val constant by collectLastValue(viewModel.hapticsToPlay) - assertThat(constant).isEqualTo(HapticFeedbackConstants.NO_HAPTICS) + val haptics by collectLastValue(viewModel.hapticsToPlay) + assertThat(haptics?.hapticFeedbackConstant).isEqualTo(HapticFeedbackConstants.NO_HAPTICS) } private suspend fun TestScope.showTemporaryErrors( diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt index e30dd35d74c1..e1e9fcb2d059 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest import com.android.keyguard.keyguardUpdateMonitor import com.android.keyguard.trustManager import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.CameraInfo import com.android.systemui.biometrics.data.repository.FaceSensorInfo import com.android.systemui.biometrics.data.repository.facePropertyRepository import com.android.systemui.biometrics.shared.model.LockoutMode @@ -490,6 +491,47 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { verify(trustManager).clearAllBiometricRecognized(eq(BiometricSourceType.FACE), anyInt()) } + @Test + fun faceAuthIsRequestedWhenAuthIsRunningWhileCameraInfoChanged() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + faceAuthRepository.requestAuthenticate( + FaceAuthUiEvent.FACE_AUTH_UPDATED_KEYGUARD_VISIBILITY_CHANGED, + true + ) + facePropertyRepository.setCameraIno(CameraInfo("0", "1", null)) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value) + .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED, true)) + } + + @Test + fun faceAuthIsNotRequestedWhenNoAuthRunningWhileCameraInfoChanged() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + facePropertyRepository.setCameraIno(CameraInfo("0", "1", null)) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value).isNull() + } + + @Test + fun faceAuthIsNotRequestedWhenAuthIsRunningWhileCameraInfoIsNull() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + facePropertyRepository.setCameraIno(null) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value).isNull() + } + companion object { private const val primaryUserId = 1 private val primaryUser = UserInfo(primaryUserId, "test user", UserInfo.FLAG_PRIMARY) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt index 9df00d3682a4..b0d8de359cd7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt @@ -19,17 +19,23 @@ package com.android.systemui.keyguard.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type +import com.android.systemui.plugins.clocks.ClockConfig +import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.statusbar.policy.SplitShadeStateController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent @@ -38,6 +44,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -54,6 +61,8 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { @Mock private lateinit var splitShadeStateController: SplitShadeStateController @Mock private lateinit var keyguardBlueprintRepository: KeyguardBlueprintRepository + @Mock private lateinit var clockInteractor: KeyguardClockInteractor + @Mock private lateinit var clockController: ClockController @Before fun setup() { @@ -61,6 +70,8 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { testScope = TestScope(StandardTestDispatcher()) whenever(keyguardBlueprintRepository.configurationChange).thenReturn(configurationFlow) whenever(keyguardBlueprintRepository.refreshTransition).thenReturn(refreshTransition) + whenever(clockInteractor.currentClock).thenReturn(MutableStateFlow(clockController)) + clockInteractor.currentClock underTest = KeyguardBlueprintInteractor( @@ -68,6 +79,7 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { testScope.backgroundScope, mContext, splitShadeStateController, + clockInteractor, ) } @@ -102,6 +114,77 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { } @Test + fun composeLockscreenOff_DoesAppliesSplitShadeWeatherClockBlueprint() { + testScope.runTest { + mSetFlagsRule.disableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + whenever(clockController.config) + .thenReturn( + ClockConfig( + id = "DIGITAL_CLOCK_WEATHER", + name = "clock", + description = "clock", + ) + ) + whenever(splitShadeStateController.shouldUseSplitNotificationShade(any())) + .thenReturn(true) + + reset(keyguardBlueprintRepository) + configurationFlow.tryEmit(Unit) + runCurrent() + + verify(keyguardBlueprintRepository, never()) + .applyBlueprint(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID) + } + } + + @Test + fun testDoesAppliesSplitShadeWeatherClockBlueprint() { + testScope.runTest { + mSetFlagsRule.enableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + whenever(clockController.config) + .thenReturn( + ClockConfig( + id = "DIGITAL_CLOCK_WEATHER", + name = "clock", + description = "clock", + ) + ) + whenever(splitShadeStateController.shouldUseSplitNotificationShade(any())) + .thenReturn(true) + + reset(keyguardBlueprintRepository) + configurationFlow.tryEmit(Unit) + runCurrent() + + verify(keyguardBlueprintRepository) + .applyBlueprint(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID) + } + } + + @Test + fun testAppliesWeatherClockBlueprint() { + testScope.runTest { + mSetFlagsRule.enableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + whenever(clockController.config) + .thenReturn( + ClockConfig( + id = "DIGITAL_CLOCK_WEATHER", + name = "clock", + description = "clock", + ) + ) + whenever(splitShadeStateController.shouldUseSplitNotificationShade(any())) + .thenReturn(false) + + reset(keyguardBlueprintRepository) + configurationFlow.tryEmit(Unit) + runCurrent() + + verify(keyguardBlueprintRepository).applyBlueprint(WEATHER_CLOCK_BLUEPRINT_ID) + } + } + + @Test fun testRefreshBlueprint() { underTest.refreshBlueprint() verify(keyguardBlueprintRepository).refreshBlueprint() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index a5d577dceecb..69cd173f4253 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -129,7 +129,6 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { val glanceableHubTransitions = GlanceableHubTransitions( - scope = testScope, bgDispatcher = kosmos.testDispatcher, transitionInteractor = transitionInteractor, transitionRepository = transitionRepository, @@ -1097,6 +1096,41 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun primaryBouncerToGlanceableHubWhileDreaming() = + testScope.runTest { + // GIVEN a prior transition has run to PRIMARY_BOUNCER + bouncerRepository.setPrimaryShow(true) + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER) + + // GIVEN that we are dreaming and occluded + keyguardRepository.setDreaming(true) + keyguardRepository.setKeyguardOccluded(true) + + // GIVEN the device is idle on the glanceable hub + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + + // WHEN the primaryBouncer stops showing + bouncerRepository.setPrimaryShow(false) + runCurrent() + + // THEN a transition to LOCKSCREEN should occur + assertThat(transitionRepository) + .startedTransition( + ownerName = FromPrimaryBouncerTransitionInteractor::class.simpleName, + from = KeyguardState.PRIMARY_BOUNCER, + to = KeyguardState.GLANCEABLE_HUB, + animatorAssertion = { it.isNotNull() }, + ) + + coroutineContext.cancelChildren() + } + + @Test fun primaryBouncerToDreamingLockscreenHosted() = testScope.runTest { // GIVEN device dreaming with the lockscreen hosted dream and not dozing @@ -1777,26 +1811,40 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { @Test fun glanceableHubToDreaming() = testScope.runTest { - // GIVEN a device that is not dreaming or dozing - keyguardRepository.setDreamingWithOverlay(false) + // GIVEN that we are dreaming and not dozing + keyguardRepository.setDreaming(true) keyguardRepository.setDozeTransitionModel( DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH) ) runCurrent() // GIVEN a prior transition has run to GLANCEABLE_HUB - runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + runTransitionAndSetWakefulness(KeyguardState.DREAMING, KeyguardState.GLANCEABLE_HUB) + runCurrent() - // WHEN the device begins to dream - keyguardRepository.setDreamingWithOverlay(true) - advanceTimeBy(100L) + // WHEN a transition away from glanceable hub starts + val currentScene = CommunalSceneKey.Communal + val targetScene = CommunalSceneKey.Blank + + val transitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Transition( + fromScene = currentScene, + toScene = targetScene, + progress = flowOf(0f, 0.1f), + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + ) + communalInteractor.setTransitionState(transitionState) + runCurrent() assertThat(transitionRepository) .startedTransition( ownerName = FromGlanceableHubTransitionInteractor::class.simpleName, from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.DREAMING, - animatorAssertion = { it.isNotNull() }, + animatorAssertion = { it.isNull() }, // transition should be manually animated ) coroutineContext.cancelChildren() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt index 1205dceb49e9..711f90f043ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt @@ -23,7 +23,6 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest import com.android.systemui.Flags as AConfigFlags import com.android.systemui.SysuiTestCase -import com.android.systemui.keyguard.ui.viewmodel.AodAlphaViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController @@ -40,7 +39,6 @@ import org.mockito.MockitoAnnotations class DefaultIndicationAreaSectionTest : SysuiTestCase() { @Mock private lateinit var keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel - @Mock private lateinit var aodAlphaViewModel: AodAlphaViewModel @Mock private lateinit var indicationController: KeyguardIndicationController private lateinit var underTest: DefaultIndicationAreaSection @@ -52,7 +50,6 @@ class DefaultIndicationAreaSectionTest : SysuiTestCase() { DefaultIndicationAreaSection( context, keyguardIndicationAreaViewModel, - aodAlphaViewModel, indicationController, ) } 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 471029b17873..4a10d80430e9 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 @@ -54,6 +54,19 @@ class DozingToLockscreenTransitionViewModelTest : SysuiTestCase() { deviceEntryParentViewAlpha.forEach { assertThat(it).isEqualTo(1f) } } + @Test + fun deviceEntryBackgroundViewShows() = + testScope.runTest { + val backgroundViewAlpha by collectValues(underTest.deviceEntryBackgroundViewAlpha) + 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)) + backgroundViewAlpha.forEach { assertThat(it).isEqualTo(1f) } + } + private fun step( value: Float, state: TransitionState = TransitionState.RUNNING diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS new file mode 100644 index 000000000000..e6f218f85b1f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/src/com/android/systemui/media/OWNERS diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManagerTest.kt index 7d5305b84dfe..61bfdb548b4f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManagerTest.kt @@ -1476,7 +1476,7 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test - fun testOnMediaDataTimedOut_doesNotUpdateLastActiveTime() { + fun testOnMediaDataTimedOut_updatesLastActiveTime() { // GIVEN that the manager has a notification mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) @@ -1487,7 +1487,7 @@ class MediaDataManagerTest : SysuiTestCase() { val currentTime = clock.elapsedRealtime() mediaDataManager.setTimedOut(KEY, true, true) - // THEN the last active time is not changed + // THEN the last active time is changed verify(listener) .onMediaDataLoaded( eq(KEY), @@ -1497,11 +1497,11 @@ class MediaDataManagerTest : SysuiTestCase() { eq(0), eq(false) ) - assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) + assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) } @Test - fun testOnActiveMediaConverted_doesNotUpdateLastActiveTime() { + fun testOnActiveMediaConverted_updatesLastActiveTime() { // GIVEN that the manager has a notification with a resume action addNotificationAndLoad() val data = mediaDataCaptor.value @@ -1514,6 +1514,42 @@ class MediaDataManagerTest : SysuiTestCase() { val currentTime = clock.elapsedRealtime() mediaDataManager.onNotificationRemoved(KEY) + // THEN the last active time is changed + verify(listener) + .onMediaDataLoaded( + eq(PACKAGE_NAME), + eq(KEY), + capture(mediaDataCaptor), + eq(true), + eq(0), + eq(false) + ) + assertThat(mediaDataCaptor.value.resumption).isTrue() + assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) + + // Log as a conversion event, not as a new resume control + verify(logger).logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId)) + verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any()) + } + + @Test + fun testOnInactiveMediaConverted_doesNotUpdateLastActiveTime() { + // GIVEN that the manager has a notification with a resume action + addNotificationAndLoad() + val data = mediaDataCaptor.value + val instanceId = data.instanceId + assertThat(data.resumption).isFalse() + mediaDataManager.onMediaDataLoaded( + KEY, + null, + data.copy(resumeAction = Runnable {}, active = false) + ) + + // WHEN the notification is removed + clock.advanceTime(100) + val currentTime = clock.elapsedRealtime() + mediaDataManager.onNotificationRemoved(KEY) + // THEN the last active time is not changed verify(listener) .onMediaDataLoaded( diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt index 14fe18289401..7f3d79f7e288 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt @@ -27,12 +27,16 @@ import android.media.RoutingSessionInfo import android.media.session.MediaController import android.media.session.MediaController.PlaybackInfo import android.media.session.MediaSession +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.settingslib.bluetooth.LocalBluetoothProfileManager +import com.android.settingslib.flags.Flags import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.media.PhoneMediaDevice @@ -83,6 +87,7 @@ private const val NORMAL_APP_NAME = "NORMAL_APP_NAME" @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper public class MediaDeviceManagerTest : SysuiTestCase() { + @get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() private lateinit var manager: MediaDeviceManager @Mock private lateinit var controllerFactory: MediaControllerFactory @@ -668,7 +673,28 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test - fun onBroadcastStarted_currentMediaDeviceDataIsBroadcasting() { + fun onBroadcastStarted_flagOff_currentMediaDeviceDataIsBroadcasting() { + mSetFlagsRule.disableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + val broadcastCallback = setupBroadcastCallback() + setupLeAudioConfiguration(true) + setupBroadcastPackage(BROADCAST_APP_NAME) + broadcastCallback.onBroadcastStarted(1, 1) + + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val data = captureDeviceData(KEY) + assertThat(data.showBroadcastButton).isFalse() + assertThat(data.enabled).isTrue() + assertThat(data.name).isEqualTo(DEVICE_NAME) + } + + @Test + @EnableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + fun onBroadcastStarted_legacy_currentMediaDeviceDataIsBroadcasting() { val broadcastCallback = setupBroadcastCallback() setupLeAudioConfiguration(true) setupBroadcastPackage(BROADCAST_APP_NAME) @@ -686,7 +712,9 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test - fun onBroadcastStarted_currentMediaDeviceDataIsNotBroadcasting() { + @EnableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + fun onBroadcastStarted_legacy_currentMediaDeviceDataIsNotBroadcasting() { val broadcastCallback = setupBroadcastCallback() setupLeAudioConfiguration(true) setupBroadcastPackage(NORMAL_APP_NAME) @@ -703,6 +731,62 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test + @EnableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + fun onBroadcastStopped_legacy_bluetoothLeBroadcastIsDisabledAndBroadcastingButtonIsGone() { + val broadcastCallback = setupBroadcastCallback() + setupLeAudioConfiguration(false) + broadcastCallback.onBroadcastStopped(1, 1) + + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val data = captureDeviceData(KEY) + assertThat(data.showBroadcastButton).isFalse() + } + + @Test + @DisableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + fun onBroadcastStarted_currentMediaDeviceDataIsBroadcasting() { + val broadcastCallback = setupBroadcastCallback() + setupLeAudioConfiguration(true) + setupBroadcastPackage(BROADCAST_APP_NAME) + broadcastCallback.onBroadcastStarted(1, 1) + + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val data = captureDeviceData(KEY) + assertThat(data.showBroadcastButton).isFalse() + assertThat(data.enabled).isFalse() + assertThat(data.name).isEqualTo(context.getString(R.string.audio_sharing_description)) + } + + @Test + @DisableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + fun onBroadcastStarted_currentMediaDeviceDataIsNotBroadcasting() { + val broadcastCallback = setupBroadcastCallback() + setupLeAudioConfiguration(true) + setupBroadcastPackage(NORMAL_APP_NAME) + broadcastCallback.onBroadcastStarted(1, 1) + + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val data = captureDeviceData(KEY) + assertThat(data.showBroadcastButton).isFalse() + assertThat(data.enabled).isFalse() + assertThat(data.name).isEqualTo(context.getString(R.string.audio_sharing_description)) + } + + @Test + @DisableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) fun onBroadcastStopped_bluetoothLeBroadcastIsDisabledAndBroadcastingButtonIsGone() { val broadcastCallback = setupBroadcastCallback() setupLeAudioConfiguration(false) @@ -714,6 +798,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { val data = captureDeviceData(KEY) assertThat(data.showBroadcastButton).isFalse() + assertThat(data.name?.equals(context.getString(R.string.audio_sharing_description))) + .isFalse() } private fun captureCallback(): LocalMediaManager.DeviceCallback { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt index 2e7829d4ea7b..2f92afa39b52 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt @@ -1247,7 +1247,7 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test - @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(com.android.settingslib.flags.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) fun bindBroadcastButton() { initMediaViewHolderMocks() initDeviceMediaData(true, APP_NAME) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt index 85291b814b3c..45f49f01a43e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt @@ -24,8 +24,10 @@ import android.view.ViewGroup import android.widget.FrameLayout import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardViewController +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq import com.android.systemui.dreams.DreamOverlayStateController @@ -508,6 +510,10 @@ class MediaHierarchyManagerTest : SysuiTestCase() { @Test fun testCommunalLocation() = testScope.runTest { + mSetFlagsRule.enableFlags(Flags.FLAG_COMMUNAL_HUB) + kosmos.setCommunalAvailable(true) + runCurrent() + communalInteractor.onSceneChanged(CommunalSceneKey.Communal) runCurrent() verify(mediaCarouselController) @@ -533,6 +539,66 @@ class MediaHierarchyManagerTest : SysuiTestCase() { } @Test + fun testCommunalLocation_showsOverLockscreen() = + testScope.runTest { + mSetFlagsRule.enableFlags(Flags.FLAG_COMMUNAL_HUB) + kosmos.setCommunalAvailable(true) + runCurrent() + + // Device is on lock screen. + whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) + + // UMO goes to communal even over the lock screen. + communalInteractor.onSceneChanged(CommunalSceneKey.Communal) + runCurrent() + verify(mediaCarouselController) + .onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_COMMUNAL_HUB), + nullable(), + eq(false), + anyLong(), + anyLong() + ) + } + + @Test + fun testCommunalLocation_showsUntilQsExpands() = + testScope.runTest { + mSetFlagsRule.enableFlags(Flags.FLAG_COMMUNAL_HUB) + kosmos.setCommunalAvailable(true) + runCurrent() + + // Device is on lock screen. + whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) + + communalInteractor.onSceneChanged(CommunalSceneKey.Communal) + runCurrent() + verify(mediaCarouselController) + .onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_COMMUNAL_HUB), + nullable(), + eq(false), + anyLong(), + anyLong() + ) + clearInvocations(mediaCarouselController) + + // Start opening the shade. + mediaHierarchyManager.qsExpansion = 0.1f + runCurrent() + + // UMO goes to the shade instead. + verify(mediaCarouselController) + .onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_QS), + any(MediaHostState::class.java), + eq(false), + anyLong(), + anyLong() + ) + } + + @Test fun testQsExpandedChanged_noQqsMedia() { // When we are looking at QQS with active media whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java index e2cf87a6dd62..087988469a49 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java @@ -28,6 +28,7 @@ import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; +import com.android.settingslib.flags.Flags; import com.android.settingslib.media.MediaOutputConstants; import com.android.systemui.SysuiTestCase; @@ -84,7 +85,20 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { } @Test + public void launchMediaOutputBroadcastDialog_flagOff_broadcastDialogFactoryNotCalled() { + mSetFlagsRule.disableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING); + Intent intent = new Intent( + MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); + intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName()); + mMediaOutputDialogReceiver.onReceive(getContext(), intent); + + verify(mMockMediaOutputDialogFactory, never()).create(any(), anyBoolean(), any()); + verify(mMockMediaOutputBroadcastDialogFactory, never()).create(any(), anyBoolean(), any()); + } + + @Test public void launchMediaOutputBroadcastDialog_ExtraPackageName_BroadcastDialogFactoryCalled() { + mSetFlagsRule.enableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING); Intent intent = new Intent( MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName()); @@ -97,6 +111,7 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { @Test public void launchMediaOutputBroadcastDialog_WrongExtraKey_DialogBroadcastFactoryNotCalled() { + mSetFlagsRule.enableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING); Intent intent = new Intent( MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); intent.putExtra("Wrong Package Name Key", getContext().getPackageName()); @@ -108,6 +123,7 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { @Test public void launchMediaOutputBroadcastDialog_NoExtra_BroadcastDialogFactoryNotCalled() { + mSetFlagsRule.enableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING); Intent intent = new Intent( MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); mMediaOutputDialogReceiver.onReceive(getContext(), intent); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index d9ddc8e6b23b..84300da82a30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -50,6 +50,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.flags.Flags; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.SysuiTestCase; @@ -177,7 +178,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getStopButtonVisibility_remoteBLEDevice_returnVisible() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -189,7 +190,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getStopButtonVisibility_remoteNonBLEDevice_returnGone() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -210,7 +211,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_flagOnAndConnectBleDevice_returnsTrue() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -223,7 +224,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_flagOnAndNoBleDevice_returnsFalse() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -236,7 +237,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_notSupportBroadcastAndflagOn_returnsFalse() { FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); @@ -245,7 +246,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_flagOffAndConnectToBleDevice_returnsTrue() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -258,7 +259,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_flagOffAndNoBleDevice_returnsTrue() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -271,7 +272,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_noBleDeviceAndEnabledBroadcast_returnsTrue() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -284,7 +285,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void isBroadcastSupported_noBleDeviceAndDisabledBroadcast_returnsFalse() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -297,7 +298,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getBroadcastIconVisibility_isBroadcasting_returnVisible() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -309,7 +310,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getBroadcastIconVisibility_noBroadcasting_returnGone() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -321,7 +322,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getBroadcastIconVisibility_remoteNonLeDevice_returnGone() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); @@ -374,7 +375,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_LEGACY_LE_AUDIO_SHARING) + @RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING) public void getStopButtonText_supportsBroadcast_returnsBroadcastText() { String stopText = mContext.getText(R.string.media_output_broadcast).toString(); MediaDevice mMediaDevice = mock(MediaDevice.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS new file mode 100644 index 000000000000..100dd2e9cbb8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS new file mode 100644 index 000000000000..f87d93a24939 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt deleted file mode 100644 index e044eeca8303..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.mediaprojection.permission - -import android.app.AlertDialog -import android.media.projection.MediaProjectionConfig -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import android.view.WindowManager -import android.widget.Spinner -import android.widget.TextView -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags -import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger -import com.android.systemui.res.R -import com.android.systemui.statusbar.phone.AlertDialogWithDelegate -import com.android.systemui.statusbar.phone.SystemUIDialog -import com.android.systemui.util.mockito.mock -import junit.framework.Assert.assertEquals -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.`when` as whenever - -@SmallTest -@RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper(setAsMainLooper = true) -class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() { - - private lateinit var dialog: AlertDialog - - private val flags = mock<FeatureFlagsClassic>() - private val onStartRecordingClicked = mock<Runnable>() - private val mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>() - - private val mediaProjectionConfig: MediaProjectionConfig = - MediaProjectionConfig.createConfigForDefaultDisplay() - private val appName: String = "testApp" - private val hostUid: Int = 12345 - - private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app - private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen - private val resIdSingleAppDisabled = - R.string.media_projection_entry_app_permission_dialog_single_app_disabled - - @Before - fun setUp() { - whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true) - } - - @After - fun teardown() { - if (::dialog.isInitialized) { - dialog.dismiss() - } - } - - @Test - fun showDialog_forceShowPartialScreenShareFalse() { - // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and - // overrideDisableSingleAppOption = false - val overrideDisableSingleAppOption = false - setUpAndShowDialog(overrideDisableSingleAppOption) - - val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner) - val secondOptionText = - spinner.adapter - .getDropDownView(1, null, spinner) - .findViewById<TextView>(android.R.id.text2) - ?.text - - // check that the first option is full screen and enabled - assertEquals(context.getString(resIdFullScreen), spinner.selectedItem) - - // check that the second option is single app and disabled - assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionText) - } - - @Test - fun showDialog_forceShowPartialScreenShareTrue() { - // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and - // overrideDisableSingleAppOption = true - val overrideDisableSingleAppOption = true - setUpAndShowDialog(overrideDisableSingleAppOption) - - val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner) - val secondOptionText = - spinner.adapter - .getDropDownView(1, null, spinner) - .findViewById<TextView>(android.R.id.text1) - ?.text - - // check that the first option is single app and enabled - assertEquals(context.getString(resIdSingleApp), spinner.selectedItem) - - // check that the second option is full screen and enabled - assertEquals(context.getString(resIdFullScreen), secondOptionText) - } - - private fun setUpAndShowDialog(overrideDisableSingleAppOption: Boolean) { - val delegate = - MediaProjectionPermissionDialogDelegate( - context, - mediaProjectionConfig, - {}, - onStartRecordingClicked, - appName, - overrideDisableSingleAppOption, - hostUid, - mediaProjectionMetricsLogger - ) - - dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate) - SystemUIDialog.applyFlags(dialog) - SystemUIDialog.setDialogSize(dialog) - - dialog.window?.addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS - ) - - delegate.onCreate(dialog, savedInstanceState = null) - dialog.show() - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt new file mode 100644 index 000000000000..0c324706857f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt @@ -0,0 +1,73 @@ +/* + * 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.screenshot + +import android.content.Intent +import android.os.Process.myUserHandle +import android.platform.test.annotations.EnableFlags +import android.testing.AndroidTestingRunner +import android.testing.TestableContext +import com.android.systemui.Flags +import com.android.systemui.SysuiTestCase +import com.android.systemui.settings.DisplayTracker +import com.android.systemui.shared.system.ActivityManagerWrapper +import com.android.systemui.statusbar.phone.CentralSurfaces +import com.android.systemui.util.mockito.mock +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestCoroutineScheduler +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.verify + +@RunWith(AndroidTestingRunner::class) +class ActionIntentExecutorTest : SysuiTestCase() { + + private val scheduler = TestCoroutineScheduler() + private val mainDispatcher = StandardTestDispatcher(scheduler) + private val testScope = TestScope(mainDispatcher) + private val testableContext = TestableContext(mContext) + + private val activityManagerWrapper = mock<ActivityManagerWrapper>() + private val displayTracker = mock<DisplayTracker>() + private val keyguardController = mock<ScreenshotKeyguardController>() + + private val actionIntentExecutor = + ActionIntentExecutor( + testableContext, + activityManagerWrapper, + testScope, + mainDispatcher, + displayTracker, + keyguardController, + ) + + @Test + @EnableFlags(Flags.FLAG_SCREENSHOT_ACTION_DISMISS_SYSTEM_WINDOWS) + fun launchIntent_callsCloseSystemWindows() = + testScope.runTest { + val intent = Intent(Intent.ACTION_EDIT).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK } + val userHandle = myUserHandle() + + actionIntentExecutor.launchIntent(intent, null, userHandle, false) + scheduler.advanceUntilIdle() + + verify(activityManagerWrapper) + .closeSystemWindows(CentralSurfaces.SYSTEM_DIALOG_REASON_SCREENSHOT) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt index 091531e435e4..2f911fffe335 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt @@ -73,6 +73,17 @@ class ScreenshotSoundControllerTest : SysuiTestCase() { } @Test + fun playCameraSound_illegalStateException_doesNotThrow() = runTest { + whenever(mediaPlayer.start()).thenThrow(IllegalStateException()) + + val controller = createController() + controller.playCameraSound().await() + + verify(mediaPlayer).start() + verify(mediaPlayer).release() + } + + @Test fun playCameraSound_soundLoadingSuccessful_mediaPlayerReleases() = runTest { val controller = createController() diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt index 032ec7440923..774aa517672e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt @@ -371,7 +371,6 @@ class UserTrackerImplTest : SysuiTestCase() { val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java) verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString()) - captor.value.onBeforeUserSwitching(newID) captor.value.onUserSwitching(newID, userSwitchingReply) assertThat(callback.calledOnUserChanging).isEqualTo(0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt index b94e483088f2..31acd86f52f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt @@ -23,6 +23,7 @@ import android.testing.TestableLooper import android.view.View import android.view.ViewGroup import android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY +import androidx.test.filters.FlakyTest import androidx.test.filters.SmallTest import androidx.test.rule.ActivityTestRule import com.android.systemui.SysuiTestCase @@ -183,6 +184,7 @@ class BrightnessDialogTest : SysuiTestCase() { } @OptIn(FlowPreview::class) + @FlakyTest(bugId = 326186573) @Test fun testFinishOnQSExpanded() = runTest { val isQSExpanded = MutableStateFlow(false) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt index 1dc5f7dbf6fe..665fc750c742 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt @@ -26,17 +26,20 @@ import android.view.View import android.view.WindowManager import android.widget.FrameLayout import androidx.test.filters.SmallTest +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.compose.ComposeFacade import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.testKosmos @@ -45,6 +48,7 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch import kotlinx.coroutines.test.UnconfinedTestDispatcher import org.junit.After import org.junit.Assert.assertThrows @@ -114,6 +118,14 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { BOTTOM_SWIPE_REGION_WIDTH ) + // Make communal available so that communalInteractor.desiredScene accurately reflects + // scene changes instead of just returning Blank. + mSetFlagsRule.enableFlags(Flags.FLAG_COMMUNAL_HUB) + with(kosmos.testScope) { + launch { kosmos.setCommunalAvailable(true) } + testScheduler.runCurrent() + } + initAndAttachContainerView() } 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 23c33346e9e2..950a9dbc2ff3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java @@ -439,8 +439,13 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { ) ); SystemClock systemClock = new FakeSystemClock(); - mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, - mInteractionJankMonitor, mJavaAdapter, () -> mShadeInteractor); + mStatusBarStateController = new StatusBarStateControllerImpl( + mUiEventLogger, + mInteractionJankMonitor, + mJavaAdapter, + () -> mShadeInteractor, + () -> mKosmos.getDeviceUnlockedInteractor(), + () -> mKosmos.getSceneInteractor()); KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext); keyguardStatusView.setId(R.id.keyguard_status_view); @@ -603,9 +608,13 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { new NotificationWakeUpCoordinator( mDumpManager, mock(HeadsUpManager.class), - new StatusBarStateControllerImpl(new UiEventLoggerFake(), + new StatusBarStateControllerImpl( + new UiEventLoggerFake(), mInteractionJankMonitor, - mJavaAdapter, () -> mShadeInteractor), + mJavaAdapter, + () -> mShadeInteractor, + () -> mKosmos.getDeviceUnlockedInteractor(), + () -> mKosmos.getSceneInteractor()), mKeyguardBypassController, mDozeParameters, mScreenOffAnimationController, 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 61fee16f0431..3808d309b02b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -180,7 +180,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mTestScope.getBackgroundScope(), mKosmos.getFakeSceneContainerConfig(), mKosmos.getSceneDataSource()), - powerInteractor, mock(SceneLogger.class), mKosmos.getDeviceUnlockedInteractor()); 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 42342d500561..0b49a954e848 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java @@ -208,7 +208,6 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { mTestScope.getBackgroundScope(), mKosmos.getFakeSceneContainerConfig(), mKosmos.getSceneDataSource()), - powerInteractor, mock(SceneLogger.class), mKosmos.getDeviceUnlockedInteractor()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java index 460892af1154..660e8da72bf1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java @@ -49,6 +49,7 @@ import android.window.TransitionInfo; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.RemoteAnimationTargetCompat; import com.android.wm.shell.shared.TransitionUtil; import org.junit.Before; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt index 0b4de345e2d7..402d9aab66bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt @@ -18,12 +18,13 @@ package com.android.systemui.statusbar import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS +import com.android.systemui.res.R import com.android.systemui.statusbar.policy.FakeConfigurationController import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController +import com.android.systemui.util.mockito.mock import com.google.common.truth.Expect import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -43,13 +44,15 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() @Mock private lateinit var dumpManager: DumpManager - @Mock private lateinit var qS: QS + private var qS: QS? = null private lateinit var controller: LockscreenShadeQsTransitionController @Before fun setUp() { MockitoAnnotations.initMocks(this) + qS = mock() + setTransitionDistance(TRANSITION_DISTANCE) setTransitionDelay(TRANSITION_DELAY) setSquishTransitionDistance(SQUISH_TRANSITION_DISTANCE) @@ -220,7 +223,7 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { controller.dragDownAmount = rawDragAmount - verify(qS) + verify(qS!!) .setTransitionToFullShadeProgress( /* isTransitioningToFullShade= */ true, /* transitionFraction= */ controller.qsTransitionFraction, @@ -228,6 +231,15 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { ) } + @Test + fun nullQS_onDragAmountChanged_doesNotCrash() { + qS = null + + val rawDragAmount = 200f + + controller.dragDownAmount = rawDragAmount + } + private fun setTransitionDistance(value: Int) { overrideResource(R.dimen.lockscreen_shade_qs_transition_distance, value) configurationController.notifyConfigurationChanged() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 91701b17b5e6..86116a073d9e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -18,6 +18,7 @@ import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingOb import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.plugins.qs.QS import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.res.R import com.android.systemui.shade.ShadeLockscreenInteractor import com.android.systemui.shade.data.repository.FakeShadeRepository @@ -82,6 +83,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { private val testScope get() = testComponent.testScope + private val qsSceneAdapter = FakeQSSceneAdapter({ mock() }) + lateinit var row: ExpandableNotificationRow @Mock lateinit var centralSurfaces: CentralSurfaces @@ -189,6 +192,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { splitShadeStateController = ResourcesSplitShadeStateController(), shadeLockscreenInteractorLazy = {shadeLockscreenInteractor}, naturalScrollingSettingObserver = naturalScrollingSettingObserver, + lazyQSSceneAdapter = { qsSceneAdapter } ) transitionController.addCallback(transitionControllerCallback) @@ -567,6 +571,16 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f) } + @Test + fun nullQs_canDragDownFromAdapter() { + transitionController.qS = null + + qsSceneAdapter.isQsFullyCollapsed = true + assertTrue("Can't drag down on keyguard", transitionController.canDragDown()) + qsSceneAdapter.isQsFullyCollapsed = false + assertFalse("Can drag down when QS is expanded", transitionController.canDragDown()) + } + private fun enableSplitShade() { setSplitShadeEnabled(true) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt index 81d5c4d52b74..700fb1ec332c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt @@ -9,6 +9,7 @@ import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.FakeConfigurationController +import com.android.systemui.util.mockito.mock import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -31,7 +32,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { @Mock private lateinit var scrimController: ScrimController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController - @Mock private lateinit var qS: QS + private var qS: QS? = null @Mock private lateinit var nsslController: NotificationStackScrollLayoutController @Mock private lateinit var dumpManager: DumpManager @@ -40,6 +41,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + qS = mock() whenever(nsslController.height).thenReturn(1800) @@ -92,7 +94,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { setDragAmount(1000f) whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE) setDragAmount(999f) - reset(qS, scrimController, nsslController) + reset(qS!!, scrimController, nsslController) setDragAmount(998f) setDragAmount(997f) @@ -100,8 +102,15 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { verifyNoMoreOverScrollChanges() } + @Test + fun qsNull_applyOverscroll_doesNotCrash() { + qS = null + + setDragAmount(100f) + } + private fun verifyOverScrollPerformed() { - verify(qS).setOverScrollAmount(intThat { it > 0 }) + verify(qS!!).setOverScrollAmount(intThat { it > 0 }) verify(scrimController).setNotificationsOverScrollAmount(intThat { it > 0 }) verify(nsslController).setOverScrollAmount(intThat { it > 0 }) } @@ -109,7 +118,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { private fun verifyOverScrollResetToZero() { // Might be more than once as the animator might have multiple values close to zero that // round down to zero. - verify(qS, atLeast(1)).setOverScrollAmount(0) + verify(qS!!, atLeast(1)).setOverScrollAmount(0) verify(scrimController, atLeast(1)).setNotificationsOverScrollAmount(0) verify(nsslController, atLeast(1)).setOverScrollAmount(0) } 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 1396a430df61..fe16347fa298 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt @@ -14,20 +14,30 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.statusbar import android.animation.ObjectAnimator +import android.platform.test.annotations.DisableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase +import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor +import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository @@ -38,13 +48,13 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.fromLockscreenTransitionInteractor import com.android.systemui.keyguard.domain.interactor.fromPrimaryBouncerTransitionInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor -import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.power.data.repository.FakePowerRepository import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.LargeScreenHeaderHelper import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.shade.domain.interactor.ShadeInteractor @@ -56,8 +66,13 @@ import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.testKosmos +import com.android.systemui.util.kotlin.JavaAdapter import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -71,8 +86,8 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito import org.mockito.Mockito.mock import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @@ -81,7 +96,6 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val testDispatcher = kosmos.testDispatcher private lateinit var shadeInteractor: ShadeInteractor private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor private lateinit var fromPrimaryBouncerTransitionInteractor: @@ -91,7 +105,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { private val deviceEntryUdfpsInteractor = mock<DeviceEntryUdfpsInteractor>() private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>() - private lateinit var controller: StatusBarStateControllerImpl + private lateinit var underTest: StatusBarStateControllerImpl private lateinit var uiEventLogger: UiEventLoggerFake @Before @@ -101,13 +115,15 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { whenever(interactionJankMonitor.end(anyInt())).thenReturn(true) uiEventLogger = UiEventLoggerFake() - controller = + underTest = object : StatusBarStateControllerImpl( uiEventLogger, interactionJankMonitor, - mock(), - { shadeInteractor } + JavaAdapter(testScope.backgroundScope), + { shadeInteractor }, + { kosmos.deviceUnlockedInteractor }, + { kosmos.sceneInteractor }, ) { override fun createDarkAnimator(): ObjectAnimator { return mockDarkAnimator @@ -115,7 +131,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } val powerInteractor = - PowerInteractor(FakePowerRepository(), FalsingCollectorFake(), mock(), controller) + PowerInteractor(FakePowerRepository(), FalsingCollectorFake(), mock(), underTest) val keyguardRepository = FakeKeyguardRepository() val keyguardTransitionRepository = FakeKeyguardTransitionRepository() val featureFlags = FakeFeatureFlagsClassic() @@ -168,11 +184,12 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun testChangeState_logged() { TestableLooper.get(this).runWithLooper { - controller.state = StatusBarState.KEYGUARD - controller.state = StatusBarState.SHADE - controller.state = StatusBarState.SHADE_LOCKED + underTest.state = StatusBarState.KEYGUARD + underTest.state = StatusBarState.SHADE + underTest.state = StatusBarState.SHADE_LOCKED } val logs = uiEventLogger.logs @@ -186,90 +203,199 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { @Test fun testSetDozeAmountInternal_onlySetsOnce() { val listener = mock(StatusBarStateController.StateListener::class.java) - controller.addCallback(listener) + underTest.addCallback(listener) - controller.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */) - controller.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */) + underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */) + underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */) verify(listener).onDozeAmountChanged(eq(0.5f), anyFloat()) } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun testSetState_appliesState_sameStateButDifferentUpcomingState() { - controller.state = StatusBarState.SHADE - controller.setUpcomingState(StatusBarState.KEYGUARD) + underTest.state = StatusBarState.SHADE + underTest.setUpcomingState(StatusBarState.KEYGUARD) - assertEquals(controller.state, StatusBarState.SHADE) + assertEquals(underTest.state, StatusBarState.SHADE) // We should return true (state change was applied) despite going from SHADE to SHADE, since // the upcoming state was set to KEYGUARD. - assertTrue(controller.setState(StatusBarState.SHADE)) + assertTrue(underTest.setState(StatusBarState.SHADE)) } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun testSetState_appliesState_differentStateEqualToUpcomingState() { - controller.state = StatusBarState.SHADE - controller.setUpcomingState(StatusBarState.KEYGUARD) + underTest.state = StatusBarState.SHADE + underTest.setUpcomingState(StatusBarState.KEYGUARD) - assertEquals(controller.state, StatusBarState.SHADE) + assertEquals(underTest.state, StatusBarState.SHADE) // Make sure we apply a SHADE -> KEYGUARD state change when the upcoming state is KEYGUARD. - assertTrue(controller.setState(StatusBarState.KEYGUARD)) + assertTrue(underTest.setState(StatusBarState.KEYGUARD)) } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun testSetState_doesNotApplyState_currentAndUpcomingStatesSame() { - controller.state = StatusBarState.SHADE - controller.setUpcomingState(StatusBarState.SHADE) + underTest.state = StatusBarState.SHADE + underTest.setUpcomingState(StatusBarState.SHADE) - assertEquals(controller.state, StatusBarState.SHADE) + assertEquals(underTest.state, StatusBarState.SHADE) // We're going from SHADE -> SHADE, and the upcoming state is also SHADE, this should not do // anything. - assertFalse(controller.setState(StatusBarState.SHADE)) + assertFalse(underTest.setState(StatusBarState.SHADE)) // Double check that we can still force it to happen. - assertTrue(controller.setState(StatusBarState.SHADE, true /* force */)) + assertTrue(underTest.setState(StatusBarState.SHADE, true /* force */)) } @Test fun testSetDozeAmount_immediatelyChangesDozeAmount_lockscreenTransitionFromAod() { // Put controller in AOD state - controller.setAndInstrumentDozeAmount(null, 1f, false) + underTest.setAndInstrumentDozeAmount(null, 1f, false) // When waking from doze, CentralSurfaces#updateDozingState will update the dozing state // before the doze amount changes - controller.setIsDozing(false) + underTest.setIsDozing(false) // Animate the doze amount to 0f, as would normally happen - controller.setAndInstrumentDozeAmount(null, 0f, true) + underTest.setAndInstrumentDozeAmount(null, 0f, true) // Check that the doze amount is immediately set to a value slightly less than 1f. This is // to ensure that any scrim implementation changes its opacity immediately rather than // waiting an extra frame. Waiting an extra frame will cause a relayout (which is expensive) // and cause us to drop a frame during the LOCKSCREEN_TRANSITION_FROM_AOD CUJ. - assertEquals(0.99f, controller.dozeAmount, 0.009f) + assertEquals(0.99f, underTest.dozeAmount, 0.009f) } @Test fun testSetDreamState_invokesCallback() { val listener = mock(StatusBarStateController.StateListener::class.java) - controller.addCallback(listener) + underTest.addCallback(listener) - controller.setIsDreaming(true) + underTest.setIsDreaming(true) verify(listener).onDreamingChanged(true) Mockito.clearInvocations(listener) - controller.setIsDreaming(false) + underTest.setIsDreaming(false) verify(listener).onDreamingChanged(false) } @Test fun testSetDreamState_getterReturnsCurrentState() { - controller.setIsDreaming(true) - assertTrue(controller.isDreaming()) + underTest.setIsDreaming(true) + assertTrue(underTest.isDreaming()) - controller.setIsDreaming(false) - assertFalse(controller.isDreaming()) + underTest.setIsDreaming(false) + assertFalse(underTest.isDreaming()) } + + @Test + @EnableSceneContainer + fun start_hydratesStatusBarState_whileLocked() = + testScope.runTest { + var statusBarState = underTest.state + val listener = + object : StatusBarStateController.StateListener { + override fun onStateChanged(newState: Int) { + statusBarState = newState + } + } + underTest.addCallback(listener) + + val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password + ) + kosmos.fakeDeviceEntryRepository.setUnlocked(false) + runCurrent() + kosmos.sceneInteractor.changeScene( + toScene = SceneKey.Lockscreen, + loggingReason = "reason" + ) + runCurrent() + assertThat(kosmos.deviceUnlockedInteractor.isDeviceUnlocked.value).isFalse() + assertThat(currentScene).isEqualTo(SceneKey.Lockscreen) + + // Call start to begin hydrating based on the scene framework: + underTest.start() + + kosmos.sceneInteractor.changeScene(toScene = SceneKey.Bouncer, loggingReason = "reason") + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.Bouncer) + assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD) + + kosmos.sceneInteractor.changeScene(toScene = SceneKey.Shade, loggingReason = "reason") + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.Shade) + assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED) + + kosmos.sceneInteractor.changeScene( + toScene = SceneKey.QuickSettings, + loggingReason = "reason" + ) + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.QuickSettings) + assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED) + + kosmos.sceneInteractor.changeScene( + toScene = SceneKey.Communal, + loggingReason = "reason" + ) + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.Communal) + assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD) + + kosmos.sceneInteractor.changeScene( + toScene = SceneKey.Lockscreen, + loggingReason = "reason" + ) + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.Lockscreen) + assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD) + } + + @Test + @EnableSceneContainer + fun start_hydratesStatusBarState_whileUnlocked() = + testScope.runTest { + var statusBarState = underTest.state + val listener = + object : StatusBarStateController.StateListener { + override fun onStateChanged(newState: Int) { + statusBarState = newState + } + } + underTest.addCallback(listener) + + val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password + ) + kosmos.fakeDeviceEntryRepository.setUnlocked(true) + runCurrent() + kosmos.sceneInteractor.changeScene(toScene = SceneKey.Gone, loggingReason = "reason") + runCurrent() + assertThat(kosmos.deviceUnlockedInteractor.isDeviceUnlocked.value).isTrue() + assertThat(currentScene).isEqualTo(SceneKey.Gone) + + // Call start to begin hydrating based on the scene framework: + underTest.start() + + kosmos.sceneInteractor.changeScene(toScene = SceneKey.Shade, loggingReason = "reason") + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.Shade) + assertThat(statusBarState).isEqualTo(StatusBarState.SHADE) + + kosmos.sceneInteractor.changeScene( + toScene = SceneKey.QuickSettings, + loggingReason = "reason" + ) + runCurrent() + assertThat(currentScene).isEqualTo(SceneKey.QuickSettings) + assertThat(statusBarState).isEqualTo(StatusBarState.SHADE) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt new file mode 100644 index 000000000000..7daadb07f89a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.statusbar.notification.collection.coordinator + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder +import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder +import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener +import com.android.systemui.statusbar.notification.collection.render.NotifRowController +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.withArgCaptor +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.MockitoAnnotations.initMocks + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper +class RowAlertTimeCoordinatorTest : SysuiTestCase() { + private lateinit var coordinator: RowAlertTimeCoordinator + private lateinit var beforeFinalizeFilterListener: OnBeforeFinalizeFilterListener + private lateinit var afterRenderEntryListener: OnAfterRenderEntryListener + + @Mock private lateinit var pipeline: NotifPipeline + + @Before + fun setUp() { + initMocks(this) + coordinator = RowAlertTimeCoordinator() + coordinator.attach(pipeline) + beforeFinalizeFilterListener = withArgCaptor { + verify(pipeline).addOnBeforeFinalizeFilterListener(capture()) + } + afterRenderEntryListener = withArgCaptor { + verify(pipeline).addOnAfterRenderEntryListener(capture()) + } + } + + @Test + fun testSetLastAudiblyAlerted() { + val entry1 = NotificationEntryBuilder().setLastAudiblyAlertedMs(10).build() + val entry2 = NotificationEntryBuilder().setLastAudiblyAlertedMs(20).build() + val summary = NotificationEntryBuilder().setLastAudiblyAlertedMs(5).build() + val child1 = NotificationEntryBuilder().setLastAudiblyAlertedMs(0).build() + val child2 = NotificationEntryBuilder().setLastAudiblyAlertedMs(8).build() + val group = + GroupEntryBuilder() + .setKey("group") + .setSummary(summary) + .addChild(child1) + .addChild(child2) + .build() + + val entries = listOf(entry1, summary, child1, child2, entry2) + + beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(entry1, group, entry2)) + val actualTimesSet = + entries.associateWith { + val rowController = mock<NotifRowController>() + afterRenderEntryListener.onAfterRenderEntry(it, rowController) + withArgCaptor<Long> { + verify(rowController).setLastAudibleMs(capture()) + verifyNoMoreInteractions(rowController) + } + } + val expectedTimesSet = + mapOf( + entry1 to 10L, + entry2 to 20L, + summary to 8L, + child1 to 0L, + child2 to 8L, + ) + assertThat(actualTimesSet).containsExactlyEntriesIn(expectedTimesSet) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt index fa669fc222f5..a66f8ce1a92c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt @@ -76,7 +76,7 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { verify(pipeline).addOnAfterRenderEntryListener(capture()) } whenever(assistantFeedbackController.getFeedbackIcon(any())).thenReturn(FeedbackIcon(1, 2)) - entry1 = NotificationEntryBuilder().setSection(section1).setLastAudiblyAlertedMs(17).build() + entry1 = NotificationEntryBuilder().setSection(section1).build() entry2 = NotificationEntryBuilder().setSection(section2).build() } @@ -103,12 +103,6 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { } @Test - fun testSetLastAudiblyAlerted() { - afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) - verify(controller1).setLastAudibleMs(eq(17.toLong())) - } - - @Test fun testSetFeedbackIcon() { afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) verify(controller1).setFeedbackIcon(eq(FeedbackIcon(1, 2))) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt index 8b99811e3d5f..a12806b9cc99 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt @@ -167,6 +167,20 @@ class IconManagerTest : SysuiTestCase() { } @Test + fun testUpdateIcons_sensitiveImportantConversation() { + val entry = + notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false) + entry?.setSensitive(true, true) + entry?.channel?.isImportantConversation = true + entry?.let { iconManager.createIcons(it) } + // Updating the icons after creation shouldn't break anything + entry?.let { iconManager.updateIcons(it) } + assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc) + assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc) + assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc) + } + + @Test fun testUpdateIcons_sensitivityChange() { val entry = notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index 91a9da399ee8..995da8192f7b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -222,6 +222,26 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test + @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME) + fun resetViewStates_hunAnimatingAwayWhileDozing_yTranslationIsInset() { + whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true) + + ambientState.isDozing = true + + resetViewStates_hunYTranslationIs(stackScrollAlgorithm.mHeadsUpInset) + } + + @Test + @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME) + fun resetViewStates_hunAnimatingAwayWhileDozing_hasStackMargin_changesHunYTranslation() { + whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true) + + ambientState.isDozing = true + + resetViewStates_stackMargin_changesHunYTranslation() + } + + @Test fun resetViewStates_hunsOverlapping_bottomHunClipped() { val topHun = mockExpandableNotificationRow() val bottomHun = mockExpandableNotificationRow() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt index 759235655eca..933b5b519672 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt @@ -24,6 +24,7 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.server.notification.Flags import com.android.systemui.SysuiTestCase +import com.android.systemui.log.logcatLogBuffer import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.settings.FakeGlobalSettings import com.android.systemui.util.time.FakeSystemClock @@ -38,6 +39,8 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @DisableFlags(Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING) class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase() { + private val logger = SensitiveNotificationProtectionControllerLogger(logcatLogBuffer()) + @Mock private lateinit var handler: Handler @Mock private lateinit var activityManager: IActivityManager @Mock private lateinit var mediaProjectionManager: MediaProjectionManager @@ -54,7 +57,8 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase( mediaProjectionManager, activityManager, handler, - FakeExecutor(FakeSystemClock()) + FakeExecutor(FakeSystemClock()), + logger ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt index a2af38f77f41..4b4e315f5533 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt @@ -34,6 +34,7 @@ import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.server.notification.Flags import com.android.systemui.SysuiTestCase +import com.android.systemui.log.logcatLogBuffer import com.android.systemui.statusbar.RankingBuilder import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder @@ -63,6 +64,8 @@ import org.mockito.MockitoAnnotations @RunWithLooper @EnableFlags(Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING) class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { + private val logger = SensitiveNotificationProtectionControllerLogger(logcatLogBuffer()) + @Mock private lateinit var activityManager: IActivityManager @Mock private lateinit var mediaProjectionManager: MediaProjectionManager @Mock private lateinit var mediaProjectionInfo: MediaProjectionInfo @@ -93,7 +96,8 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { mediaProjectionManager, activityManager, mockExecutorHandler(executor), - executor + executor, + logger ) // Process pending work (getting global setting and list of exemptions) diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt index 203096affd5c..08b49f026523 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt @@ -166,4 +166,28 @@ class TurbulenceNoiseControllerTest : SysuiTestCase() { assertThat(config.color).isEqualTo(expectedColor) } } + + @Test + fun play_initializesShader() { + val expectedNoiseOffset = floatArrayOf(0.1f, 0.2f, 0.3f) + val config = + TurbulenceNoiseAnimationConfig( + noiseOffsetX = expectedNoiseOffset[0], + noiseOffsetY = expectedNoiseOffset[1], + noiseOffsetZ = expectedNoiseOffset[2] + ) + val turbulenceNoiseView = TurbulenceNoiseView(context, null) + val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView) + + fakeExecutor.execute { + turbulenceNoiseController.play(SIMPLEX_NOISE, config) + + assertThat(turbulenceNoiseView.noiseConfig).isNotNull() + val shader = turbulenceNoiseView.turbulenceNoiseShader!! + assertThat(shader).isNotNull() + assertThat(shader.noiseOffsetX).isEqualTo(expectedNoiseOffset[0]) + assertThat(shader.noiseOffsetY).isEqualTo(expectedNoiseOffset[1]) + assertThat(shader.noiseOffsetZ).isEqualTo(expectedNoiseOffset[2]) + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java index 766a5ce322bf..5d341207ef6a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java @@ -200,4 +200,25 @@ public class ObservableServiceConnectionTest extends SysuiTestCase { assertThat(connection.bind()).isFalse(); verify(mContext).unbindService(connection); } + + @Test + public void testUnbindDoesNotCallUnbindServiceWhenBindThrowsError() { + ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext, + mIntent, mUserTracker, mExecutor, mTransformer); + connection.addCallback(mCallback); + + when(mContext.bindServiceAsUser(eq(mIntent), eq(connection), anyInt(), + eq(UserHandle.of(MAIN_USER_ID)))) + .thenThrow(new SecurityException()); + + // Verify that bind returns false and we properly unbind. + assertThat(connection.bind()).isFalse(); + verify(mContext).unbindService(connection); + + clearInvocations(mContext); + + // Ensure unbind after the failed bind has no effect. + connection.unbind(); + verify(mContext, never()).unbindService(eq(connection)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 1a3cb87b3422..d2e03861b022 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -61,6 +61,7 @@ import android.widget.ImageButton; import android.widget.SeekBar; import androidx.test.core.view.MotionEventBuilder; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.internal.jank.InteractionJankMonitor; @@ -501,6 +502,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { } @Test + @FlakyTest(bugId = 326204750) public void dialogDestroy_removesPostureControllerCallback() { verify(mPostureController, never()).removeCallback(any()); mDialog.destroy(); @@ -799,8 +801,9 @@ public class VolumeDialogImplTest extends SysuiTestCase { Log.d(TAG, "teardown: entered"); setOrientation(mOriginalOrientation); Log.d(TAG, "teardown: after setOrientation"); - mAnimatorTestRule.advanceTimeBy(mLongestHideShowAnimationDuration); - Log.d(TAG, "teardown: after advanceTimeBy"); + // Unclear why we used to do this, and it seems to be a source of flakes + // mAnimatorTestRule.advanceTimeBy(mLongestHideShowAnimationDuration); + Log.d(TAG, "teardown: skipped advanceTimeBy"); mTestableLooper.moveTimeForward(mLongestHideShowAnimationDuration); Log.d(TAG, "teardown: after moveTimeForward"); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualLocationsServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualLocationsServiceTest.kt index 8c5df6efef33..d2387e83e3eb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualLocationsServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualLocationsServiceTest.kt @@ -12,6 +12,7 @@ import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.StandardTestDispatcher @@ -38,6 +39,7 @@ class WalletContextualLocationsServiceTest : SysuiTestCase() { private var featureFlags = FakeFeatureFlags() private lateinit var underTest: WalletContextualLocationsService private lateinit var testScope: TestScope + private lateinit var testDispatcher: CoroutineDispatcher private var listenerRegisteredCount: Int = 0 private val listener: IWalletCardsUpdatedListener.Stub = object : IWalletCardsUpdatedListener.Stub() { @@ -54,8 +56,8 @@ class WalletContextualLocationsServiceTest : SysuiTestCase() { doNothing().whenever(controller).setSuggestionCardIds(anySet()) if (Looper.myLooper() == null) Looper.prepare() - val testDispatcher = StandardTestDispatcher() - testScope = TestScope() + testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) featureFlags.set(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS, true) listenerRegisteredCount = 0 underTest = 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 d87df0af6ba9..a9308601a314 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -26,6 +26,7 @@ import static android.service.notification.NotificationListenerService.REASON_AP import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING; import static com.google.common.truth.Truth.assertThat; @@ -46,6 +47,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static kotlinx.coroutines.flow.FlowKt.emptyFlow; @@ -73,6 +75,8 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.service.dreams.IDreamManager; import android.service.notification.NotificationListenerService; import android.service.notification.ZenModeConfig; @@ -161,6 +165,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository; import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository; @@ -257,6 +262,8 @@ public class BubblesTest extends SysuiTestCase { private NotificationShadeWindowView mNotificationShadeWindowView; @Mock private AuthController mAuthController; + @Mock + private SensitiveNotificationProtectionController mSensitiveNotificationProtectionController; private SysUiState mSysUiState; private boolean mSysUiStateBubblesExpanded; @@ -272,6 +279,8 @@ public class BubblesTest extends SysuiTestCase { private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor; @Captor private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor; + @Captor + private ArgumentCaptor<Runnable> mSensitiveStateChangedListener; private BubblesManager mBubblesManager; private TestableBubbleController mBubbleController; @@ -415,7 +424,6 @@ public class BubblesTest extends SysuiTestCase { mTestScope.getBackgroundScope(), mKosmos.getFakeSceneContainerConfig(), mKosmos.getSceneDataSource()), - powerInteractor, mock(SceneLogger.class), mKosmos.getDeviceUnlockedInteractor()); @@ -595,6 +603,7 @@ public class BubblesTest extends SysuiTestCase { interruptionDecisionProvider, mZenModeController, mLockscreenUserManager, + mSensitiveNotificationProtectionController, mCommonNotifCollection, mNotifPipeline, mSysUiState, @@ -2204,6 +2213,33 @@ public class BubblesTest extends SysuiTestCase { assertThat(mBubbleController.getLayerView().isExpanded()).isFalse(); } + @DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Test + public void doesNotRegisterSensitiveStateListener() { + verifyZeroInteractions(mSensitiveNotificationProtectionController); + } + + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Test + public void registerSensitiveStateListener() { + verify(mSensitiveNotificationProtectionController).registerSensitiveStateListener(any()); + } + + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Test + public void onSensitiveNotificationProtectionStateChanged() { + verify(mSensitiveNotificationProtectionController, atLeastOnce()) + .registerSensitiveStateListener(mSensitiveStateChangedListener.capture()); + + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(true); + mSensitiveStateChangedListener.getValue().run(); + verify(mBubbleController).onSensitiveNotificationProtectionStateChanged(true); + + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + mSensitiveStateChangedListener.getValue().run(); + verify(mBubbleController).onSensitiveNotificationProtectionStateChanged(false); + } + /** Creates a bubble using the userId and package. */ private Bubble createBubble(int userId, String pkg) { final UserHandle userHandle = new UserHandle(userId); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/assist/data/repository/AssistRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/data/repository/AssistRepositoryKosmos.kt new file mode 100644 index 000000000000..96155ed1ec9f --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/data/repository/AssistRepositoryKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.assist.data.repository + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.assistRepository by Kosmos.Fixture { AssistRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/assist/domain/interactor/AssistInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/domain/interactor/AssistInteractorKosmos.kt new file mode 100644 index 000000000000..c3c11318b0cc --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/domain/interactor/AssistInteractorKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.assist.domain.interactor + +import com.android.systemui.assist.data.repository.assistRepository +import com.android.systemui.kosmos.Kosmos + +val Kosmos.assistInteractor by Kosmos.Fixture { AssistInteractor(assistRepository) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt index 77f501f550d7..68ef55573dc8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt @@ -33,6 +33,10 @@ class FakeFacePropertyRepository : FacePropertyRepository { override val sensorLocation: StateFlow<Point?> get() = faceSensorLocation + private val currentCameraInfo = MutableStateFlow<CameraInfo?>(null) + override val cameraInfo: StateFlow<CameraInfo?> + get() = currentCameraInfo + fun setLockoutMode(userId: Int, mode: LockoutMode) { lockoutModesForUser[userId] = mode } @@ -47,4 +51,8 @@ class FakeFacePropertyRepository : FacePropertyRepository { fun setSensorLocation(value: Point?) { faceSensorLocation.value = value } + + fun setCameraIno(value: CameraInfo?) { + currentCameraInfo.value = value + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt index ae7d87783b7c..9d508d23dca7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt @@ -38,11 +38,4 @@ class FakeCommunalRepository( override fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) { _transitionState.value = transitionState } - - private val _isCommunalHubShowing: MutableStateFlow<Boolean> = MutableStateFlow(false) - override val isCommunalHubShowing: Flow<Boolean> = _isCommunalHubShowing - - fun setIsCommunalHubShowing(isCommunalHubShowing: Boolean) { - _isCommunalHubShowing.value = isCommunalHubShowing - } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt index 566fc2529954..6ac702eb2446 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt @@ -29,6 +29,9 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.log.logcatLogBuffer +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags +import com.android.systemui.settings.userTracker import com.android.systemui.smartspace.data.repository.smartspaceRepository import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.mock @@ -44,9 +47,12 @@ val Kosmos.communalInteractor by Fixture { appWidgetHost = mock(), keyguardInteractor = keyguardInteractor, editWidgetsActivityStarter = editWidgetsActivityStarter, + userTracker = userTracker, logBuffer = logcatLogBuffer("CommunalInteractor"), tableLogBuffer = mock(), communalSettingsInteractor = communalSettingsInteractor, + sceneInteractor = sceneInteractor, + sceneContainerFlags = fakeSceneContainerFlags, ) } @@ -56,9 +62,11 @@ suspend fun Kosmos.setCommunalAvailable(available: Boolean) { fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, available) if (available) { fakeUserRepository.asMainUser() - with(fakeKeyguardRepository) { - setIsEncryptedOrLockdown(false) - setKeyguardShowing(true) - } + } else { + fakeUserRepository.asDefaultUser() + } + with(fakeKeyguardRepository) { + setIsEncryptedOrLockdown(!available) + setKeyguardShowing(available) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt index 00fdceda01d1..23f63e6e20a7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt @@ -16,7 +16,6 @@ package com.android.systemui.communal.domain.interactor -import com.android.systemui.communal.data.repository.communalRepository import com.android.systemui.communal.data.repository.communalTutorialRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.kosmos.Kosmos @@ -29,7 +28,6 @@ val Kosmos.communalTutorialInteractor by scope = applicationCoroutineScope, communalTutorialRepository = communalTutorialRepository, keyguardInteractor = keyguardInteractor, - communalRepository = communalRepository, communalInteractor = communalInteractor, communalSettingsInteractor = communalSettingsInteractor, tableLogBuffer = mock(), diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt index 55885bf58acc..5dd50731c58a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt @@ -19,13 +19,11 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher val Kosmos.glanceableHubTransitions by Kosmos.Fixture { GlanceableHubTransitions( - scope = applicationCoroutineScope, bgDispatcher = testDispatcher, transitionRepository = keyguardTransitionRepository, transitionInteractor = keyguardTransitionInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt index d9a3192ce821..8b0bba1320e4 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt @@ -29,5 +29,6 @@ val Kosmos.keyguardBlueprintInteractor by applicationScope = applicationCoroutineScope, context = applicationContext, splitShadeStateController = splitShadeStateController, + clockInteractor = keyguardClockInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..c6f07068aad4 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModelKosmos.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.alternateBouncerToDozingTransitionViewModel by Fixture { + AlternateBouncerToDozingTransitionViewModel( + deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..36ddc29b8914 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModelKosmos.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.dozingToGoneTransitionViewModel by Fixture { + DozingToGoneTransitionViewModel( + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelKosmos.kt index 400a0d87f041..de52d848e94b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModelKosmos.kt @@ -14,8 +14,6 @@ * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) - package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow @@ -23,6 +21,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import kotlinx.coroutines.ExperimentalCoroutinesApi +@ExperimentalCoroutinesApi val Kosmos.dozingToLockscreenTransitionViewModel by Fixture { DozingToLockscreenTransitionViewModel( animationFlow = keyguardTransitionAnimationFlow, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..dc6b26feac15 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.dozingToPrimaryBouncerTransitionViewModel by Fixture { + DozingToPrimaryBouncerTransitionViewModel( + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt index b37085957d7e..00741eb69c62 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt @@ -16,12 +16,14 @@ package com.android.systemui.keyguard.ui.viewmodel +import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos val Kosmos.dreamingToGlanceableHubTransitionViewModel by Kosmos.Fixture { DreamingToGlanceableHubTransitionViewModel( + configurationInteractor = configurationInteractor, animationFlow = keyguardTransitionAnimationFlow, ) } 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 index 8b5407cc7e17..5f70a2f06f2e 100644 --- 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 @@ -14,11 +14,8 @@ * 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 @@ -26,11 +23,11 @@ import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.util.mockito.mock import kotlinx.coroutines.ExperimentalCoroutinesApi +@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/GlanceableHubToDreamingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..1302f155d93b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.common.ui.domain.interactor.configurationInteractor +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos + +val Kosmos.glanceableHubToDreamingTransitionViewModel by + Kosmos.Fixture { + GlanceableHubToDreamingTransitionViewModel( + configurationInteractor = configurationInteractor, + animationFlow = keyguardTransitionAnimationFlow, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelKosmos.kt index 4daf46028979..b19d4e87e68c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModelKosmos.kt @@ -14,17 +14,18 @@ * 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.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import kotlinx.coroutines.ExperimentalCoroutinesApi +@ExperimentalCoroutinesApi val Kosmos.goneToDozingTransitionViewModel by Fixture { GoneToDozingTransitionViewModel( + deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, animationFlow = keyguardTransitionAnimationFlow, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..aa8e9a8c9a8c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelKosmos.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.lockscreenToDozingTransitionViewModel by Fixture { + LockscreenToDozingTransitionViewModel( + deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, + 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 index 1b2337fedf6a..17c3a14bd5e1 100644 --- 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 @@ -14,8 +14,6 @@ * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) - package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow @@ -23,6 +21,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import kotlinx.coroutines.ExperimentalCoroutinesApi +@ExperimentalCoroutinesApi val Kosmos.lockscreenToGoneTransitionViewModel by Fixture { LockscreenToGoneTransitionViewModel( animationFlow = keyguardTransitionAnimationFlow, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..d4e4b8c34807 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.primaryBouncerToDozingTransitionViewModel by Fixture { + PrimaryBouncerToDozingTransitionViewModel( + deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt index be559efc7946..7264f7a2bc95 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt @@ -17,8 +17,10 @@ package com.android.systemui.plugins.statusbar import com.android.internal.logging.uiEventLogger +import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.kosmos.Kosmos +import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.statusbar.StatusBarStateControllerImpl import com.android.systemui.util.mockito.mock @@ -29,7 +31,8 @@ var Kosmos.statusBarStateController by uiEventLogger, interactionJankMonitor, mock(), - ) { - shadeInteractor - } + { shadeInteractor }, + { deviceUnlockedInteractor }, + { sceneInteractor }, + ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt index b1581d1771fd..4d902fa35204 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt @@ -41,6 +41,8 @@ class FakeQSSceneAdapter( private val _navBarPadding = MutableStateFlow<Int>(0) val navBarPadding = _navBarPadding.asStateFlow() + override var isQsFullyCollapsed: Boolean = true + override suspend fun inflate(context: Context) { _view.value = inflateDelegate(context) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt new file mode 100644 index 000000000000..00ab0b57fab7 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.ui.adapter + +import android.view.View +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.fakeQSSceneAdapter by Kosmos.Fixture { FakeQSSceneAdapter({ mock<View>() }) } + +val Kosmos.qsSceneAdapter: QSSceneAdapter by Kosmos.Fixture { fakeQSSceneAdapter } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt index fc023758fdf6..ef7aa6308491 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt @@ -19,7 +19,6 @@ package com.android.systemui.scene.domain.interactor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope -import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.shared.logger.sceneLogger @@ -28,7 +27,6 @@ val Kosmos.sceneInteractor by SceneInteractor( applicationScope = applicationCoroutineScope, repository = sceneContainerRepository, - powerInteractor = powerInteractor, logger = sceneLogger, deviceUnlockedInteractor = deviceUnlockedInteractor, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryKosmos.kt new file mode 100644 index 000000000000..ecc3c9e27208 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeHeaderClockRepositoryKosmos.kt @@ -0,0 +1,23 @@ +/* + * 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.data.repository + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.policy.nextAlarmController + +var Kosmos.shadeHeaderClockRepository: ShadeHeaderClockRepository by + Kosmos.Fixture { ShadeHeaderClockRepository(nextAlarmController) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt new file mode 100644 index 000000000000..6fd7cf6edbe4 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.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.shade.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.plugins.activityStarter +import com.android.systemui.shade.data.repository.shadeHeaderClockRepository + +var Kosmos.shadeHeaderClockInteractor: ShadeHeaderClockInteractor by + Kosmos.Fixture { + ShadeHeaderClockInteractor( + repository = shadeHeaderClockRepository, + activityStarter = activityStarter, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt index e5072f1c9f1c..e4a3896378f6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt @@ -26,6 +26,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.media.controls.ui.controller.mediaHierarchyManager import com.android.systemui.plugins.activityStarter +import com.android.systemui.qs.ui.adapter.qsSceneAdapter import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor @@ -61,5 +62,6 @@ val Kosmos.lockscreenShadeTransitionController by Fixture { splitShadeStateController = splitShadeStateController, shadeLockscreenInteractorLazy = { shadeLockscreenInteractor }, naturalScrollingSettingObserver = naturalScrollingSettingObserver, + lazyQSSceneAdapter = { qsSceneAdapter } ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorKosmos.kt new file mode 100644 index 000000000000..0614309a3910 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorKosmos.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.domain.interactor + +import com.android.settingslib.statusbar.notification.data.repository.FakeNotificationsSoundPolicyRepository +import com.android.settingslib.statusbar.notification.domain.interactor.NotificationsSoundPolicyInteractor +import com.android.systemui.kosmos.Kosmos + +var Kosmos.notificationsSoundPolicyRepository by + Kosmos.Fixture { FakeNotificationsSoundPolicyRepository() } + +val Kosmos.notificationsSoundPolicyInteractor: NotificationsSoundPolicyInteractor by + Kosmos.Fixture { NotificationsSoundPolicyInteractor(notificationsSoundPolicyRepository) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt index 0c2b115a8af5..aa2c2a2e1ec3 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt @@ -2,30 +2,45 @@ package com.android.systemui.statusbar.policy class FakeDeviceProvisionedController : DeviceProvisionedController { @JvmField var deviceProvisioned = true + @JvmField var currentUser = 0 + + private val callbacks = mutableSetOf<DeviceProvisionedController.DeviceProvisionedListener>() + private val usersSetup = mutableSetOf<Int>() override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) { - TODO("Not yet implemented") + callbacks.add(listener) } override fun removeCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) { - TODO("Not yet implemented") + callbacks.remove(listener) } override fun isDeviceProvisioned() = deviceProvisioned + @Deprecated("Deprecated in Java") override fun getCurrentUser(): Int { - TODO("Not yet implemented") + return currentUser } override fun isUserSetup(user: Int): Boolean { - TODO("Not yet implemented") + return user in usersSetup } override fun isCurrentUserSetup(): Boolean { - TODO("Not yet implemented") + return currentUser in usersSetup } override fun isFrpActive(): Boolean { TODO("Not yet implemented") } + + fun setCurrentUser(userId: Int) { + currentUser = userId + callbacks.toSet().forEach { it.onUserSwitched() } + } + + fun setUserSetup(userId: Int) { + usersSetup.add(userId) + callbacks.toSet().forEach { it.onUserSetupChanged() } + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/NextAlarmControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/NextAlarmControllerKosmos.kt new file mode 100644 index 000000000000..860c3fa016ae --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/NextAlarmControllerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.nextAlarmController: NextAlarmController by + Kosmos.Fixture { mock<NextAlarmController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt index 931a59d30d7b..3e9ae4d2e354 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt @@ -119,6 +119,13 @@ class FakeUserRepository @Inject constructor() : UserRepository { yield() } + /** Resets the current user to the default of [DEFAULT_SELECTED_USER_INFO]. */ + suspend fun asDefaultUser(): UserInfo { + setUserInfos(listOf(DEFAULT_SELECTED_USER_INFO)) + setSelectedUserInfo(DEFAULT_SELECTED_USER_INFO) + return DEFAULT_SELECTED_USER_INFO + } + /** Makes the current user [MAIN_USER]. */ suspend fun asMainUser(): UserInfo { setUserInfos(listOf(MAIN_USER)) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt index fed3e171862d..a3ad2b87d5f5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt @@ -42,6 +42,7 @@ class FakeAudioRepository : AudioRepository { get() = mutableCommunicationDevice.asStateFlow() private val models: MutableMap<AudioStream, MutableStateFlow<AudioStreamModel>> = mutableMapOf() + private val lastAudibleVolumes: MutableMap<AudioStream, Int> = mutableMapOf() private fun getAudioStreamModelState( audioStream: AudioStream @@ -59,12 +60,9 @@ class FakeAudioRepository : AudioRepository { ) } - override suspend fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> = + override fun getAudioStream(audioStream: AudioStream): Flow<AudioStreamModel> = getAudioStreamModelState(audioStream).asStateFlow() - override suspend fun getCurrentAudioStream(audioStream: AudioStream): AudioStreamModel = - getAudioStreamModelState(audioStream).value - override suspend fun setVolume(audioStream: AudioStream, volume: Int) { getAudioStreamModelState(audioStream).update { it.copy(volume = volume) } } @@ -73,6 +71,9 @@ class FakeAudioRepository : AudioRepository { getAudioStreamModelState(audioStream).update { it.copy(isMuted = isMuted) } } + override suspend fun getLastAudibleVolume(audioStream: AudioStream): Int = + lastAudibleVolumes.getOrDefault(audioStream, 0) + fun setMode(newMode: Int) { mutableMode.value = newMode } @@ -88,4 +89,8 @@ class FakeAudioRepository : AudioRepository { fun setAudioStreamModel(model: AudioStreamModel) { getAudioStreamModelState(model.audioStream).update { model } } + + fun setLastAudibleVolume(audioStream: AudioStream, volume: Int) { + lastAudibleVolumes[audioStream] = volume + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeLocalMediaRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeLocalMediaRepository.kt index 7835fc89ea52..284bd55f15d7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeLocalMediaRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeLocalMediaRepository.kt @@ -27,20 +27,19 @@ class FakeLocalMediaRepository : LocalMediaRepository { private val volumeBySession: MutableMap<String?, Int> = mutableMapOf() - private val mutableMediaDevices = MutableStateFlow<Collection<MediaDevice>>(emptyList()) - override val mediaDevices: StateFlow<Collection<MediaDevice>> + private val mutableMediaDevices = MutableStateFlow<List<MediaDevice>>(emptyList()) + override val mediaDevices: StateFlow<List<MediaDevice>> get() = mutableMediaDevices.asStateFlow() private val mutableCurrentConnectedDevice = MutableStateFlow<MediaDevice?>(null) override val currentConnectedDevice: StateFlow<MediaDevice?> get() = mutableCurrentConnectedDevice.asStateFlow() - private val mutableRemoteRoutingSessions = - MutableStateFlow<Collection<RoutingSession>>(emptyList()) - override val remoteRoutingSessions: StateFlow<Collection<RoutingSession>> + private val mutableRemoteRoutingSessions = MutableStateFlow<List<RoutingSession>>(emptyList()) + override val remoteRoutingSessions: StateFlow<List<RoutingSession>> get() = mutableRemoteRoutingSessions.asStateFlow() - fun updateMediaDevices(devices: Collection<MediaDevice>) { + fun updateMediaDevices(devices: List<MediaDevice>) { mutableMediaDevices.value = devices } diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml index cccf3695a537..fc11ce08f8de 100644 --- a/packages/VpnDialogs/res/values-mr/strings.xml +++ b/packages/VpnDialogs/res/values-mr/strings.xml @@ -30,7 +30,7 @@ <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> हे पूर्ण वेळ कनेक्ट राहण्यासाठी सेट अप केलेले आहे, पण हे आता कनेक्ट होऊ शकत नाही. VPN पुन्हा कनेक्ट होईपर्यंत तुमच्याकडे कनेक्शन नसेल."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN सेटिंग्ज बदला"</string> - <string name="configure" msgid="4905518375574791375">"कॉंफिगर करा"</string> + <string name="configure" msgid="4905518375574791375">"कॉन्फिगर करा"</string> <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करा"</string> <string name="open_app" msgid="3717639178595958667">"अॅप उघडा"</string> <string name="dismiss" msgid="6192859333764711227">"डिसमिस करा"</string> diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index d8a94d8b8b59..e0fe88a1a167 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -1277,6 +1277,20 @@ public class CameraExtensionsProxyService extends Service { } @Override + public void onCaptureFailed(int captureSequenceId, int reason) { + if (Flags.concertMode()) { + if (mCaptureCallback != null) { + try { + mCaptureCallback.onCaptureProcessFailed(captureSequenceId, reason); + } catch (RemoteException e) { + Log.e(TAG, "Failed to notify capture failure due to remote " + + "exception!"); + } + } + } + } + + @Override public void onCaptureSequenceCompleted(int captureSequenceId) { if (mCaptureCallback != null) { try { diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index 53897e14ecd6..41a4a1ad1ccb 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -47,6 +47,7 @@ java_library { ], libs: [ "framework-minus-apex.ravenwood", + "ravenwood-junit", ], visibility: ["//visibility:private"], } diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java index b736a7662bd4..37ceac601e37 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java @@ -73,9 +73,9 @@ public class RavenwoodUtils { return; } } - throw new UnsatisfiedLinkError("Library " + libname + " no found in " + throw new UnsatisfiedLinkError("Library " + libname + " not found in " + "java.library.path: " + path); - } catch (Exception e) { + } catch (Throwable e) { dumpFiles(System.out); throw e; } @@ -96,6 +96,10 @@ public class RavenwoodUtils { listFiles(out, gparent, ""); } } + + var gparent = new File("../..").getCanonicalFile(); + out.println("# ../..=" + gparent); + listFiles(out, gparent, ""); } catch (Throwable th) { out.println("Error: " + th.toString()); th.printStackTrace(out); diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/ravenwood-annotation-allowed-classes.txt index 4a4c29030f3c..eb3c55cb4ff6 100644 --- a/ravenwood/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/ravenwood-annotation-allowed-classes.txt @@ -255,6 +255,7 @@ android.view.Display android.view.Display$HdrCapabilities android.view.Display$Mode android.view.DisplayInfo +android.view.inputmethod.InputBinding android.hardware.SerialManager android.hardware.SerialManagerInternal diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java index 5930a14cdec8..f301b9c46b0e 100644 --- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java +++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java @@ -22,6 +22,13 @@ import com.android.internal.os.RuntimeInit; import java.io.PrintStream; +/** + * Ravenwood "native substitution" class for {@link android.util.Log}. + * + * {@link android.util.Log} already uses the actual native code and doesn't use this class. + * In order to switch to this Java implementation, uncomment the @RavenwoodNativeSubstitutionClass + * annotation on {@link android.util.Log}. + */ public class Log_host { public static boolean isLoggable(String tag, @Level int level) { diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java index 1e120305fa2d..cc94090d9ec7 100644 --- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java +++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java @@ -15,8 +15,9 @@ */ package com.android.platform.test.ravenwood.runtimehelper; +import android.platform.test.ravenwood.RavenwoodUtils; + import java.io.File; -import java.io.PrintStream; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -27,8 +28,6 @@ import java.util.ArrayList; * load other JNI or do other set up here. */ public class ClassLoadHook { - private static PrintStream sOut = System.out; - /** * If true, we won't load `libandroid_runtime` * @@ -36,7 +35,7 @@ public class ClassLoadHook { * so we need a way to remove the dependency. */ private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv( - "HOSTTEST_SKIP_LOADING_LIBANDROID")); + "RAVENWOOD_SKIP_LOADING_LIBANDROID")); public static final String CORE_NATIVE_CLASSES = "core_native_classes"; public static final String ICU_DATA_PATH = "icu.data.path"; @@ -44,7 +43,7 @@ public class ClassLoadHook { public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes"; public static final String VALUE_N_A = "**n/a**"; - public static final String LIBANDROID_RUNTIME_NAME = "libandroid_runtime"; + public static final String LIBANDROID_RUNTIME_NAME = "android_runtime"; private static String sInitialDir = new File("").getAbsolutePath(); @@ -68,7 +67,7 @@ public class ClassLoadHook { } private static void log(String message) { - sOut.println("ClassLoadHook: " + message); + System.out.println("ClassLoadHook: " + message); } private static void log(String fmt, Object... args) { @@ -92,13 +91,6 @@ public class ClassLoadHook { } } - private static void loadJniLibrary(String name) { - final String path = sInitialDir + "/lib64/" + name + ".so"; - System.out.println("Loading " + path + " ..."); - System.load(path); - System.out.println("Done loading " + path); - } - private static boolean sLoadFrameworkNativeCodeCalled = false; /** @@ -115,7 +107,7 @@ public class ClassLoadHook { // libandroid_runtime uses Java's system properties to decide what JNI methods to set up. // Set up these properties for host-side tests. - if ("1".equals(System.getenv("HOSTTEST_DUMP_PROPERTIES"))) { + if ("1".equals(System.getenv("RAVENWOOD_DUMP_PROPERTIES"))) { log("Java system properties:"); dumpSystemProperties(); } @@ -141,7 +133,7 @@ public class ClassLoadHook { setProperty(ICU_DATA_PATH, VALUE_N_A); setProperty(KEYBOARD_PATHS, VALUE_N_A); - loadJniLibrary(LIBANDROID_RUNTIME_NAME); + RavenwoodUtils.loadJniLibrary(LIBANDROID_RUNTIME_NAME); } /** @@ -156,7 +148,7 @@ public class ClassLoadHook { }; /** - * @return if a given method is a native method or not. + * @return if a given class has any native method or not. */ private static boolean hasNativeMethod(Class<?> clazz) { for (var method : clazz.getDeclaredMethods()) { diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java index 67c2caa338a6..4a2f3da0eb06 100644 --- a/rs/java/android/renderscript/ScriptC.java +++ b/rs/java/android/renderscript/ScriptC.java @@ -101,7 +101,19 @@ public class ScriptC extends Script { setID(id); } - private static void throwExceptionIfSDKTooHigh() { + private static void throwExceptionIfScriptCUnsupported() { + // Checks that this device actually does have an ABI that supports ScriptC. + // + // For an explanation as to why `System.loadLibrary` is used, see discussion at + // https://android-review.googlesource.com/c/platform/frameworks/base/+/2957974/comment/2f908b80_a05292ee + try { + System.loadLibrary("RS"); + } catch (UnsatisfiedLinkError e) { + String s = "This device does not have an ABI that supports ScriptC."; + throw new UnsupportedOperationException(s); + } + + // Throw an exception if the target API is 35 or above String message = "ScriptC scripts are not supported when targeting an API Level >= 35. Please refer " + "to https://developer.android.com/guide/topics/renderscript/migration-guide " @@ -113,7 +125,7 @@ public class ScriptC extends Script { } private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) { - throwExceptionIfSDKTooHigh(); + throwExceptionIfScriptCUnsupported(); byte[] pgm; int pgmLength; InputStream is = resources.openRawResource(resourceID); @@ -150,7 +162,7 @@ public class ScriptC extends Script { private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) { // Log.v(TAG, "Create script for resource = " + resName); - throwExceptionIfSDKTooHigh(); + throwExceptionIfScriptCUnsupported(); return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length); } } diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig index d4f049e09ee2..a754ba547767 100644 --- a/services/accessibility/accessibility.aconfig +++ b/services/accessibility/accessibility.aconfig @@ -73,6 +73,16 @@ flag { } flag { + name: "handle_multi_device_input" + namespace: "accessibility" + description: "Select a single active device when a multi-device stream is received by AccessibilityInputFilter" + bug: "310014874" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "pinch_zoom_zero_min_span" namespace: "accessibility" description: "Whether to set min span of ScaleGestureDetector to zero." @@ -87,6 +97,16 @@ flag { } flag { + name: "reset_hover_event_timer_on_action_up" + namespace: "accessibility" + description: "Reset the timer for sending hover events on receiving ACTION_UP to guarantee the correct amount of time is available between taps." + bug: "326260351" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "scan_packages_without_lock" namespace: "accessibility" description: "Scans packages for accessibility service/activity info without holding the A11yMS lock" diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index abcd8e2a2d7e..54e545d6d73a 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -16,6 +16,8 @@ package com.android.server.accessibility; +import static android.view.InputDevice.SOURCE_CLASS_POINTER; +import static android.view.MotionEvent.ACTION_SCROLL; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; @@ -25,6 +27,7 @@ import android.annotation.NonNull; import android.content.Context; import android.graphics.Region; import android.os.PowerManager; +import android.os.SystemClock; import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; @@ -35,6 +38,8 @@ import android.view.InputEvent; import android.view.InputFilter; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.MotionEvent.PointerCoords; +import android.view.MotionEvent.PointerProperties; import android.view.accessibility.AccessibilityEvent; import com.android.server.LocalServices; @@ -203,6 +208,62 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo private EventStreamState mKeyboardStreamState; + /** + * The last MotionEvent emitted from the input device that's currently active. This is used to + * keep track of which input device is currently active, and also to generate the cancel event + * if a new device becomes active. + */ + private MotionEvent mLastActiveDeviceMotionEvent = null; + + private static MotionEvent cancelMotion(MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_CANCEL + || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT + || event.getActionMasked() == MotionEvent.ACTION_UP) { + throw new IllegalArgumentException("Can't cancel " + event); + } + final int action; + if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER + || event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) { + action = MotionEvent.ACTION_HOVER_EXIT; + } else { + action = MotionEvent.ACTION_CANCEL; + } + + final int pointerCount; + if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) { + pointerCount = event.getPointerCount() - 1; + } else { + pointerCount = event.getPointerCount(); + } + final PointerProperties[] properties = new PointerProperties[pointerCount]; + final PointerCoords[] coords = new PointerCoords[pointerCount]; + int newPointerIndex = 0; + for (int i = 0; i < event.getPointerCount(); i++) { + if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) { + if (event.getActionIndex() == i) { + // Skip the pointer that's going away + continue; + } + } + final PointerCoords c = new PointerCoords(); + c.x = event.getX(i); + c.y = event.getY(i); + coords[newPointerIndex] = c; + final PointerProperties p = new PointerProperties(); + p.id = event.getPointerId(i); + p.toolType = event.getToolType(i); + properties[newPointerIndex] = p; + newPointerIndex++; + } + + return MotionEvent.obtain(event.getDownTime(), SystemClock.uptimeMillis(), action, + pointerCount, properties, coords, + event.getMetaState(), event.getButtonState(), + event.getXPrecision(), event.getYPrecision(), event.getDeviceId(), + event.getEdgeFlags(), event.getSource(), event.getDisplayId(), event.getFlags(), + event.getClassification()); + } + AccessibilityInputFilter(Context context, AccessibilityManagerService service) { this(context, service, new SparseArray<>(0)); } @@ -260,6 +321,17 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo AccessibilityTrace.FLAGS_INPUT_FILTER, "event=" + event + ";policyFlags=" + policyFlags); } + if (Flags.handleMultiDeviceInput()) { + if (!shouldProcessMultiDeviceEvent(event, policyFlags)) { + // We are only allowing a single device to be active at a time. + return; + } + } + + onInputEventInternal(event, policyFlags); + } + + private void onInputEventInternal(InputEvent event, int policyFlags) { if (mEventHandler.size() == 0) { if (DEBUG) Slog.d(TAG, "No mEventHandler for event " + event); super.onInputEvent(event, policyFlags); @@ -353,8 +425,71 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } } + boolean shouldProcessMultiDeviceEvent(InputEvent event, int policyFlags) { + if (event instanceof MotionEvent motion) { + if (!motion.isFromSource(SOURCE_CLASS_POINTER) || motion.getAction() == ACTION_SCROLL) { + // Non-pointer events are focus-dispatched and don't require special logic. + // Scroll events are stand-alone and therefore can be considered to not be part of + // a stream. + return true; + } + // Only allow 1 device to be sending motion events at a time + // If the event is from an active device, let it through. + // If the event is not from an active device, only let it through if it starts a new + // gesture like ACTION_DOWN or ACTION_HOVER_ENTER + final boolean eventIsFromCurrentDevice = mLastActiveDeviceMotionEvent != null + && mLastActiveDeviceMotionEvent.getDeviceId() == motion.getDeviceId(); + final int actionMasked = motion.getActionMasked(); + switch (actionMasked) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_MOVE: { + if (mLastActiveDeviceMotionEvent != null + && mLastActiveDeviceMotionEvent.getDeviceId() != motion.getDeviceId()) { + // This is a new gesture from a new device. Cancel the existing state + // and let this through + MotionEvent canceled = cancelMotion(mLastActiveDeviceMotionEvent); + onInputEventInternal(canceled, policyFlags); + } + mLastActiveDeviceMotionEvent = MotionEvent.obtain(motion); + return true; + } + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: { + if (eventIsFromCurrentDevice) { + mLastActiveDeviceMotionEvent = MotionEvent.obtain(motion); + return true; + } else { + return false; + } + } + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_HOVER_EXIT: { + if (eventIsFromCurrentDevice) { + // This is the last event of the gesture from this device. + mLastActiveDeviceMotionEvent = null; + return true; + } else { + // Event is from another device + return false; + } + } + default: { + if (mLastActiveDeviceMotionEvent != null + && event.getDeviceId() != mLastActiveDeviceMotionEvent.getDeviceId()) { + // This is an event from another device, ignore it. + return false; + } + } + } + } + return true; + } + private void processMotionEvent(EventStreamState state, MotionEvent event, int policyFlags) { - if (!state.shouldProcessScroll() && event.getActionMasked() == MotionEvent.ACTION_SCROLL) { + if (!state.shouldProcessScroll() && event.getActionMasked() == ACTION_SCROLL) { super.onInputEvent(event, policyFlags); return; } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 46db624cf3c1..43c018cfeea3 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -3460,13 +3460,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub if (!mMagnificationController.supportWindowMagnification()) { return; } - final boolean connect = (userState.isShortcutMagnificationEnabledLocked() + + final boolean shortcutEnabled = (userState.isShortcutMagnificationEnabledLocked() || userState.isMagnificationSingleFingerTripleTapEnabledLocked() || (Flags.enableMagnificationMultipleFingerMultipleTapGesture() - && userState.isMagnificationTwoFingerTripleTapEnabledLocked())) - && (userState.getMagnificationCapabilitiesLocked() - != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) + && userState.isMagnificationTwoFingerTripleTapEnabledLocked())); + + final boolean createConnectionForCurrentCapability = + com.android.window.flags.Flags.magnificationAlwaysDrawFullscreenBorder() + || (userState.getMagnificationCapabilitiesLocked() + != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + + final boolean connect = (shortcutEnabled && createConnectionForCurrentCapability) || userHasMagnificationServicesLocked(userState); + getMagnificationConnectionManager().requestConnection(connect); } diff --git a/services/accessibility/java/com/android/server/accessibility/BrailleDisplayConnection.java b/services/accessibility/java/com/android/server/accessibility/BrailleDisplayConnection.java index 9b27dd347caf..40b6ff01965e 100644 --- a/services/accessibility/java/com/android/server/accessibility/BrailleDisplayConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/BrailleDisplayConnection.java @@ -232,9 +232,63 @@ class BrailleDisplayConnection extends IBrailleDisplayConnection.Stub { } /** Returns true if this descriptor includes usages for the Braille display usage page 0x41. */ - private static boolean isBrailleDisplay(byte[] descriptor) { - // TODO: b/316036493 - Check that descriptor includes 0x41 reports. - return true; + @VisibleForTesting + static boolean isBrailleDisplay(byte[] descriptor) { + boolean foundMatch = false; + for (int i = 0; i < descriptor.length; i++) { + // HID Spec "6.2.2.2 Short Items" defines that the report descriptor is a collection of + // items: each item is a collection of bytes where the first byte defines info about + // the type of item and the following 0, 1, 2, or 4 bytes are data bytes for that item. + // All items in the HID descriptor are expected to be Short Items. + final byte itemInfo = descriptor[i]; + if (!isHidItemShort(itemInfo)) { + Slog.w(LOG_TAG, "Item " + itemInfo + " declares unsupported long type"); + return false; + } + final int dataSize = getHidItemDataSize(itemInfo); + if (i + dataSize >= descriptor.length) { + Slog.w(LOG_TAG, "Item " + itemInfo + " specifies size past the remaining bytes"); + return false; + } + // The item we're looking for (usage page declaration) should have size 1. + if (dataSize == 1) { + final byte itemData = descriptor[i + 1]; + if (isHidItemBrailleDisplayUsagePage(itemInfo, itemData)) { + foundMatch = true; + } + } + // Move to the next item by skipping past all data bytes in this item. + i += dataSize; + } + return foundMatch; + } + + private static boolean isHidItemShort(byte itemInfo) { + // Info bits 7-4 describe the item type, and HID Spec "6.2.2.3 Long Items" says that long + // items always have type bits 1111. Otherwise, the item is a short item. + return (itemInfo & 0b1111_0000) != 0b1111_0000; + } + + private static int getHidItemDataSize(byte itemInfo) { + // HID Spec "6.2.2.2 Short Items" says that info bits 0-1 specify the optional data size: + // 0, 1, 2, or 4 bytes. + return switch (itemInfo & 0b0000_0011) { + case 0b00 -> 0; + case 0b01 -> 1; + case 0b10 -> 2; + default -> 4; + }; + } + + private static boolean isHidItemBrailleDisplayUsagePage(byte itemInfo, byte itemData) { + // From HID Spec "6.2.2.7 Global Items" + final byte usagePageType = 0b0000_0100; + // From HID Usage Tables version 1.2. + final byte brailleDisplayUsagePage = 0x41; + // HID Spec "6.2.2.2 Short Items" says item info bits 2-7 describe the type and + // function of the item. + final byte itemType = (byte) (itemInfo & 0b1111_1100); + return itemType == usagePageType && itemData == brailleDisplayUsagePage; } /** diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java index b6223c7b4b35..bf9202f1b266 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java @@ -106,11 +106,30 @@ class EventDispatcher { return; } } + final long downTime; if (action == MotionEvent.ACTION_DOWN) { - event.setDownTime(event.getEventTime()); + downTime = event.getEventTime(); } else { - event.setDownTime(mState.getLastInjectedDownEventTime()); + downTime = mState.getLastInjectedDownEventTime(); } + + // The only way to change device id of the motion event is by re-creating the whole thing + final PointerProperties[] properties = new PointerProperties[event.getPointerCount()]; + final PointerCoords[] coords = new PointerCoords[event.getPointerCount()]; + for (int i = 0; i < event.getPointerCount(); i++) { + final PointerCoords c = new PointerCoords(); + event.getPointerCoords(i, c); + coords[i] = c; + final PointerProperties p = new PointerProperties(); + event.getPointerProperties(i, p); + properties[i] = p; + } + event = MotionEvent.obtain(downTime, event.getEventTime(), event.getAction(), + event.getPointerCount(), properties, coords, + event.getMetaState(), event.getButtonState(), + event.getXPrecision(), event.getYPrecision(), rawEvent.getDeviceId(), + event.getEdgeFlags(), rawEvent.getSource(), event.getDisplayId(), event.getFlags(), + event.getClassification()); // If the user is long pressing but the long pressing pointer // was not exactly over the accessibility focused item we need // to remap the location of that pointer so the user does not diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index 3086ce1ceb40..4fc65bfeca58 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -852,6 +852,11 @@ public class TouchExplorer extends BaseEventStreamTransformation final int pointerIdBits = (1 << pointerId); if (mSendHoverEnterAndMoveDelayed.isPending()) { // If we have not delivered the enter schedule an exit. + if (Flags.resetHoverEventTimerOnActionUp()) { + // We cancel first to reset the time window so that the user has the full amount of + // time to do a multi tap. + mSendHoverEnterAndMoveDelayed.repost(); + } mSendHoverExitDelayed.post(event, rawEvent, pointerIdBits, policyFlags); } else { // The user is touch exploring so we send events for end. @@ -1554,6 +1559,14 @@ public class TouchExplorer extends BaseEventStreamTransformation } } + public void repost() { + // cancel without clearing + if (isPending()) { + mHandler.removeCallbacks(this); + mHandler.postDelayed(this, mDetermineUserIntentTimeout); + } + } + private boolean isPending() { return mHandler.hasCallbacks(this); } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java index e11c36a91830..bc143428e1ae 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java @@ -674,6 +674,23 @@ public class MagnificationConnectionManager implements } /** + * Notify Fullscreen magnification activation changes. + */ + public boolean onFullscreenMagnificationActivationChanged(int displayId, boolean activated) { + synchronized (mLock) { + waitForConnectionIfNeeded(); + if (mConnectionWrapper == null) { + Slog.w(TAG, + "onFullscreenMagnificationActivationChanged mConnectionWrapper is null. " + + "mConnectionState=" + connectionStateToString(mConnectionState)); + return false; + } + return mConnectionWrapper + .onFullscreenMagnificationActivationChanged(displayId, activated); + } + } + + /** * Calculates the number of fingers in the window. * * @param displayId The logical display id. @@ -1267,15 +1284,7 @@ public class MagnificationConnectionManager implements float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, MagnificationAnimationCallback animationCallback) { - // Wait for the connection with a timeout. - final long endMillis = SystemClock.uptimeMillis() + WAIT_CONNECTION_TIMEOUT_MILLIS; - while (mConnectionState == CONNECTING && (SystemClock.uptimeMillis() < endMillis)) { - try { - mLock.wait(endMillis - SystemClock.uptimeMillis()); - } catch (InterruptedException ie) { - /* ignore */ - } - } + waitForConnectionIfNeeded(); if (mConnectionWrapper == null) { Slog.w(TAG, "enableWindowMagnificationInternal mConnectionWrapper is null. " @@ -1317,4 +1326,16 @@ public class MagnificationConnectionManager implements return mConnectionWrapper != null && mConnectionWrapper.moveWindowMagnifierToPosition( displayId, positionX, positionY, animationCallback); } + + private void waitForConnectionIfNeeded() { + // Wait for the connection with a timeout. + final long endMillis = SystemClock.uptimeMillis() + WAIT_CONNECTION_TIMEOUT_MILLIS; + while (mConnectionState == CONNECTING && (SystemClock.uptimeMillis() < endMillis)) { + try { + mLock.wait(endMillis - SystemClock.uptimeMillis()); + } catch (InterruptedException ie) { + /* ignore */ + } + } + } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java index db5b3133169a..f6fb24f38a7a 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java @@ -58,6 +58,22 @@ class MagnificationConnectionWrapper { mConnection.asBinder().linkToDeath(deathRecipient, 0); } + boolean onFullscreenMagnificationActivationChanged(int displayId, boolean activated) { + if (mTrace.isA11yTracingEnabledForTypes(FLAGS_MAGNIFICATION_CONNECTION)) { + mTrace.logTrace(TAG + ".onFullscreenMagnificationActivationChanged", + FLAGS_MAGNIFICATION_CONNECTION); + } + try { + mConnection.onFullscreenMagnificationActivationChanged(displayId, activated); + } catch (RemoteException e) { + if (DBG) { + Slog.e(TAG, "Error calling onFullscreenMagnificationActivationChanged"); + } + return false; + } + return true; + } + boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, @Nullable MagnificationAnimationCallback callback) { diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index 52e123a5e70c..0d5fd1435ca0 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -50,6 +50,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.wm.WindowManagerInternal; +import com.android.window.flags.Flags; import java.util.concurrent.Executor; @@ -586,6 +587,11 @@ public class MagnificationController implements MagnificationConnectionManager.C @Override public void onFullScreenMagnificationActivationState(int displayId, boolean activated) { + if (Flags.magnificationAlwaysDrawFullscreenBorder()) { + getMagnificationConnectionManager() + .onFullscreenMagnificationActivationChanged(displayId, activated); + } + if (activated) { synchronized (mLock) { mFullScreenModeEnabledTimeArray.put(displayId, SystemClock.uptimeMillis()); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 5a3421799aae..c7b844b991c4 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -127,7 +127,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; -import android.os.OutcomeReceiver; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; @@ -194,6 +193,7 @@ import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import java.io.PrintWriter; +import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -2803,9 +2803,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int datasetIdx = AutofillManager.getDatasetIdFromAuthenticationId( authenticationId); + Dataset dataset = null; // Authenticated a dataset - reset view state regardless if we got a response or a dataset if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) { - final Dataset dataset = authenticatedResponse.getDatasets().get(datasetIdx); + dataset = authenticatedResponse.getDatasets().get(datasetIdx); if (dataset == null) { Slog.w(TAG, "no dataset with index " + datasetIdx + " on fill response"); mPresentationStatsEventLogger.maybeSetAuthenticationResult( @@ -2820,12 +2821,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mSessionFlags.mExpiredResponse = false; final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT); + final Serializable exception = data.getSerializable( + CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION); final Bundle newClientState = data.getBundle(AutofillManager.EXTRA_CLIENT_STATE); if (sDebug) { Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result + ", clientState=" + newClientState + ", authenticationId=" + authenticationId); } + if (Flags.autofillCredmanDevIntegration() && exception != null + && exception instanceof GetCredentialException) { + if (dataset != null && dataset.getFieldIds().size() == 1) { + if (sDebug) { + Slog.d(TAG, "setAuthenticationResultLocked(): result returns with" + + "Credential Manager Exception"); + } + AutofillId autofillId = dataset.getFieldIds().get(0); + sendCredentialManagerResponseToApp(/*response=*/ null, + (GetCredentialException) exception, autofillId); + } + return; + } + if (result instanceof FillResponse) { if (sDebug) { Slog.d(TAG, "setAuthenticationResultLocked(): received FillResponse from" @@ -2839,17 +2856,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (sDebug) { Slog.d(TAG, "Received GetCredentialResponse from authentication flow"); } - boolean isCredmanCallbackInvoked = false; - if (Flags.autofillCredmanIntegration()) { + if (Flags.autofillCredmanDevIntegration()) { GetCredentialResponse response = (GetCredentialResponse) result; - isCredmanCallbackInvoked = invokeCredentialManagerCallback(response); - } - - if (!isCredmanCallbackInvoked) { - Dataset dataset = getDatasetFromCredentialResponse( - (GetCredentialResponse) result); - if (dataset != null) { - autoFill(requestId, datasetIdx, dataset, false, UI_TYPE_UNKNOWN); + if (dataset != null && dataset.getFieldIds().size() == 1) { + AutofillId autofillId = dataset.getFieldIds().get(0); + if (sDebug) { + Slog.d(TAG, "Received GetCredentialResponse from authentication flow," + + "for autofillId: " + autofillId); + } + sendCredentialManagerResponseToApp(response, + /*exception=*/ null, autofillId); + } + } else if (Flags.autofillCredmanIntegration()) { + Dataset datasetFromCredentialResponse = getDatasetFromCredentialResponse( + (GetCredentialResponse) result); + if (datasetFromCredentialResponse != null) { + autoFill(requestId, datasetIdx, datasetFromCredentialResponse, + false, UI_TYPE_UNKNOWN); } } } else if (result instanceof Dataset) { @@ -2866,12 +2889,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (sDebug) Slog.d(TAG, "Updating client state from auth dataset"); mClientState = newClientState; } - Dataset dataset = getEffectiveDatasetForAuthentication((Dataset) result); + Dataset datasetFromResult = getEffectiveDatasetForAuthentication((Dataset) result); final Dataset oldDataset = authenticatedResponse.getDatasets().get(datasetIdx); if (!isAuthResultDatasetEphemeral(oldDataset, data)) { - authenticatedResponse.getDatasets().set(datasetIdx, dataset); + authenticatedResponse.getDatasets().set(datasetIdx, datasetFromResult); } - autoFill(requestId, datasetIdx, dataset, false, UI_TYPE_UNKNOWN); + autoFill(requestId, datasetIdx, datasetFromResult, false, UI_TYPE_UNKNOWN); } else { Slog.w(TAG, "invalid index (" + datasetIdx + ") for authentication id " + authenticationId); @@ -2892,49 +2915,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private boolean invokeCredentialManagerCallback(GetCredentialResponse response) { - synchronized (mLock) { - return invokeCredentialManagerCallbackLocked(response); - } - } - - @GuardedBy("mLock") - private boolean invokeCredentialManagerCallbackLocked(GetCredentialResponse response) { - AutofillId autofillId = response.getAutofillId(); - if (autofillId != null) { - OutcomeReceiver<GetCredentialResponse, - GetCredentialException> callback = - getCredmanCallbackFromContextsLocked(autofillId); - if (callback != null) { - Slog.w(TAG, "Propagating response to Credential Manager callback"); - callback.onResult(response); - return true; - } else { - Slog.w(TAG, "Received Credential Manager response but no callback found"); - } - } else { - Slog.w(TAG, "Received Credential Manager response but no autofillId found"); - } - return false; - } - - @GuardedBy("mLock") - @Nullable - private OutcomeReceiver<GetCredentialResponse, - GetCredentialException> getCredmanCallbackFromContextsLocked( - @NonNull AutofillId autofillId) { - final int numContexts = mContexts.size(); - for (int i = numContexts - 1; i >= 0; i--) { - final FillContext context = mContexts.get(i); - final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), - autofillId); - if (node != null) { - return node.getCredentialManagerCallback(); - } - } - return null; - } - private Dataset getDatasetFromCredentialResponse(GetCredentialResponse result) { if (result == null) { return null; @@ -5098,21 +5078,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } private void addCredentialManagerCallbackForDataset(Dataset dataset, int requestId) { + AutofillId autofillId = null; + if (dataset != null && dataset.getFieldIds().size() == 1) { + autofillId = dataset.getFieldIds().get(0); + } + final AutofillId finalAutofillId = autofillId; final ResultReceiver resultReceiver = new ResultReceiver(mHandler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == SUCCESS_CREDMAN_SELECTOR) { Slog.d(TAG, "onReceiveResult from Credential Manager bottom sheet"); - boolean isCredmanCallbackInvoked = false; GetCredentialResponse getCredentialResponse = resultData.getParcelable( CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, GetCredentialResponse.class); - isCredmanCallbackInvoked = - invokeCredentialManagerCallback(getCredentialResponse); - - if (!isCredmanCallbackInvoked) { + if (Flags.autofillCredmanDevIntegration()) { + sendCredentialManagerResponseToApp(getCredentialResponse, + /*exception=*/ null, finalAutofillId); + } else { Dataset datasetFromCredential = getDatasetFromCredentialResponse( getCredentialResponse); if (datasetFromCredential != null) { @@ -5128,6 +5112,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "Credman bottom sheet from pinned " + "entry failed with: + " + exception[0] + " , " + exception[1]); + sendCredentialManagerResponseToApp(/*response=*/ null, + new GetCredentialException(exception[0], exception[1]), + finalAutofillId); } } else { Slog.d(TAG, "Unknown resultCode from credential " @@ -6407,6 +6394,38 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + void sendCredentialManagerResponseToApp(@Nullable GetCredentialResponse response, + @Nullable GetCredentialException exception, @NonNull AutofillId viewId) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#sendCredentialManagerResponseToApp() rejected " + + "- session: " + id + " destroyed"); + return; + } + try { + final ViewState viewState = mViewStates.get(viewId); + if (mService.getMaster().getIsFillFieldsFromCurrentSessionOnly() + && viewState != null && viewState.id.getSessionId() != id) { + if (sVerbose) { + Slog.v(TAG, "Skipping sending credential response to view: " + + viewId + " as it isn't part of the current session: " + id); + } + } + if (exception != null) { + mClient.onGetCredentialException(id, viewId, exception.getType(), + exception.getMessage()); + } else if (response != null) { + mClient.onGetCredentialResponse(id, viewId, response); + } else { + Slog.w(TAG, "sendCredentialManagerResponseToApp called with null response" + + "and exception"); + } + } catch (RemoteException e) { + Slog.w(TAG, "Error sending credential response to activity: " + e); + } + } + } + void autoFillApp(Dataset dataset) { synchronized (mLock) { if (mDestroyed) { diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java index d580f3a7d7d8..78edb8ead7a0 100644 --- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java @@ -15,7 +15,7 @@ */ package com.android.server.autofill.ui; -import static android.service.autofill.FillRequest.FLAG_VIEW_REQUESTS_CREDMAN_SERVICE; +import static android.service.autofill.FillResponse.FLAG_CREDENTIAL_MANAGER_RESPONSE; import static com.android.server.autofill.Helper.paramsToString; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sFullScreenMode; @@ -215,7 +215,7 @@ final class FillUi { Slog.v(TAG, "overriding maximum visible datasets to " + mVisibleDatasetsMaxCount); } } else if (Flags.autofillCredmanIntegration() && ( - (response.getFlags() & FLAG_VIEW_REQUESTS_CREDMAN_SERVICE) != 0)) { + (response.getFlags() & FLAG_CREDENTIAL_MANAGER_RESPONSE) != 0)) { mVisibleDatasetsMaxCount = AUTOFILL_CREDMAN_MAX_VISIBLE_DATASETS; } else { diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java index c734680009c6..ffc80ee7d710 100644 --- a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java @@ -16,6 +16,8 @@ package com.android.server.autofill.ui; +import static android.service.autofill.FillResponse.FLAG_CREDENTIAL_MANAGER_RESPONSE; + import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; @@ -24,6 +26,7 @@ import android.annotation.UserIdInt; import android.content.IntentSender; import android.service.autofill.Dataset; import android.service.autofill.FillResponse; +import android.service.autofill.Flags; import android.service.autofill.InlinePresentation; import android.text.TextUtils; import android.util.Pair; @@ -141,10 +144,12 @@ public final class InlineFillUi { return new InlineFillUi(inlineFillUiInfo, inlineAuthentication, maxInputLengthForAutofill); } else if (response.getDatasets() != null) { + boolean ignoreHostSpec = Flags.autofillCredmanIntegration() && ( + (response.getFlags() & FLAG_CREDENTIAL_MANAGER_RESPONSE) != 0); SparseArray<Pair<Dataset, InlineSuggestion>> inlineSuggestions = InlineSuggestionFactory.createInlineSuggestions(inlineFillUiInfo, InlineSuggestionInfo.SOURCE_AUTOFILL, response.getDatasets(), - uiCallback); + uiCallback, ignoreHostSpec); return new InlineFillUi(inlineFillUiInfo, inlineSuggestions, maxInputLengthForAutofill); } @@ -160,7 +165,8 @@ public final class InlineFillUi { @NonNull InlineSuggestionUiCallback uiCallback) { SparseArray<Pair<Dataset, InlineSuggestion>> inlineSuggestions = InlineSuggestionFactory.createInlineSuggestions(inlineFillUiInfo, - InlineSuggestionInfo.SOURCE_PLATFORM, datasets, uiCallback); + InlineSuggestionInfo.SOURCE_PLATFORM, datasets, + uiCallback, /* ignoreHostSpec= */ false); return new InlineFillUi(inlineFillUiInfo, inlineSuggestions); } @@ -254,7 +260,7 @@ public final class InlineFillUi { if (!TextUtils.isEmpty(mFilterText) && mFilterText.length() > mMaxInputLengthForAutofill) { if (sVerbose) { Slog.v(TAG, "Not showing inline suggestion when user entered more than " - + mMaxInputLengthForAutofill + " characters"); + + mMaxInputLengthForAutofill + " characters"); } return new InlineSuggestionsResponse(inlineSuggestions); } diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java index 52109ba44917..d3b950112f91 100644 --- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java +++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java @@ -16,6 +16,7 @@ package com.android.server.autofill.ui; +import static android.service.autofill.FillResponse.FLAG_CREDENTIAL_MANAGER_RESPONSE; import static android.view.inputmethod.InlineSuggestionInfo.TYPE_SUGGESTION; import static com.android.server.autofill.Helper.sDebug; @@ -25,6 +26,7 @@ import android.annotation.Nullable; import android.content.IntentSender; import android.service.autofill.Dataset; import android.service.autofill.FillResponse; +import android.service.autofill.Flags; import android.service.autofill.InlinePresentation; import android.util.Pair; import android.util.Slog; @@ -47,11 +49,14 @@ final class InlineSuggestionFactory { @NonNull InlineFillUi.InlineSuggestionUiCallback uiCallback) { InlinePresentation inlineAuthentication = response.getInlinePresentation(); final int requestId = response.getRequestId(); + boolean ignoreHostSpec = Flags.autofillCredmanIntegration() && ( + (response.getFlags() & FLAG_CREDENTIAL_MANAGER_RESPONSE) != 0); return createInlineSuggestion(inlineFillUiInfo, InlineSuggestionInfo.SOURCE_AUTOFILL, InlineSuggestionInfo.TYPE_ACTION, () -> uiCallback.authenticate(requestId, AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED), - mergedInlinePresentation(inlineFillUiInfo.mInlineRequest, 0, inlineAuthentication), + mergedInlinePresentation(inlineFillUiInfo.mInlineRequest, 0, inlineAuthentication, + ignoreHostSpec), createInlineSuggestionTooltip(inlineFillUiInfo.mInlineRequest, inlineFillUiInfo, InlineSuggestionInfo.SOURCE_AUTOFILL, response.getInlineTooltipPresentation()), @@ -67,7 +72,7 @@ final class InlineSuggestionFactory { @NonNull InlineFillUi.InlineFillUiInfo inlineFillUiInfo, @NonNull @InlineSuggestionInfo.Source String suggestionSource, @NonNull List<Dataset> datasets, - @NonNull InlineFillUi.InlineSuggestionUiCallback uiCallback) { + @NonNull InlineFillUi.InlineSuggestionUiCallback uiCallback, boolean ignoreHostSpec) { if (sDebug) Slog.d(TAG, "createInlineSuggestions(source=" + suggestionSource + ") called"); final InlineSuggestionsRequest request = inlineFillUiInfo.mInlineRequest; @@ -107,7 +112,8 @@ final class InlineSuggestionFactory { InlineSuggestion inlineSuggestion = createInlineSuggestion( inlineFillUiInfo, suggestionSource, suggestionType, () -> uiCallback.autofill(dataset, index), - mergedInlinePresentation(request, datasetIndex, inlinePresentation), + mergedInlinePresentation(request, datasetIndex, inlinePresentation, + ignoreHostSpec), inlineSuggestionTooltip, uiCallback); response.append(datasetIndex, Pair.create(dataset, inlineSuggestion)); @@ -141,16 +147,18 @@ final class InlineSuggestionFactory { */ private static InlinePresentation mergedInlinePresentation( @NonNull InlineSuggestionsRequest request, - int index, @NonNull InlinePresentation inlinePresentation) { + int index, @NonNull InlinePresentation inlinePresentation, boolean ignoreHostSpec) { final List<InlinePresentationSpec> specs = request.getInlinePresentationSpecs(); if (specs.isEmpty()) { return inlinePresentation; } InlinePresentationSpec specFromHost = specs.get(Math.min(specs.size() - 1, index)); + InlinePresentationSpec specToUse = + ignoreHostSpec ? inlinePresentation.getInlinePresentationSpec() : specFromHost; InlinePresentationSpec mergedInlinePresentation = new InlinePresentationSpec.Builder( inlinePresentation.getInlinePresentationSpec().getMinSize(), inlinePresentation.getInlinePresentationSpec().getMaxSize()).setStyle( - specFromHost.getStyle()).build(); + specToUse.getStyle()).build(); return new InlinePresentation(inlinePresentation.getSlice(), mergedInlinePresentation, inlinePresentation.isPinned()); @@ -211,7 +219,7 @@ final class InlineSuggestionFactory { inlineFillUiInfo, tooltipInline, () -> { /* no operation */ }, uiCallback); final InlineSuggestionInfo tooltipInlineSuggestionInfo = new InlineSuggestionInfo( mergedSpec, suggestionSource, /* autofillHints */ null, TYPE_SUGGESTION, - /* pinned */ false, /* tooltip */ null); + /* pinned */ false, /* tooltip */ null); return new InlineSuggestion(tooltipInlineSuggestionInfo, tooltipContentProvider); } diff --git a/services/backup/flags.aconfig b/services/backup/flags.aconfig index 71f2b9e8e10b..e9f959f4b9eb 100644 --- a/services/backup/flags.aconfig +++ b/services/backup/flags.aconfig @@ -35,6 +35,15 @@ flag { } flag { + name: "enable_v_to_u_restore_for_system_components_in_allowlist" + namespace: "onboarding" + description: "Enables system components to opt in to support restore in V to U downgrade " + "scenario without opting in for restoreAnyVersion." + bug: "324233962" + is_fixed_read_only: true +} + +flag { name: "enable_increase_datatypes_for_agent_logging" namespace: "onboarding" description: "Increase the number of a supported datatypes that an agent can define for its " diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java index 9f0deea503cf..6e98e68601f6 100644 --- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java @@ -177,6 +177,10 @@ public class PackageManagerBackupAgent extends BackupAgent { return mHasMetadata; } + public int getSourceSdk() { + return mStoredSdkVersion; + } + public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { Slog.w(TAG, "getRestoredMetadata() before metadata read!"); diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java index d85dd879e21d..e666442af9c9 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -44,6 +44,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; +import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.ParcelFileDescriptor; @@ -51,6 +52,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.Settings; import android.util.EventLog; import android.util.Slog; @@ -82,6 +84,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; @@ -158,6 +161,12 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // When finished call listener private final OnTaskFinishedListener mListener; + // List of packages that support V-> U downgrade but do not have RestoreAnyVersion set to true. + private List<String> mVToUAllowlist; + + // List of packages that have RestoreAnyVersion set to true but do not support V-> U downgrade. + private List<String> mVToUDenylist; + // Key/value: bookkeeping about staged data and files for agent access private File mBackupDataName; private File mStageName; @@ -172,7 +181,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { @VisibleForTesting PerformUnifiedRestoreTask( UserBackupManagerService backupManagerService, - TransportConnection transportConnection) { + TransportConnection transportConnection, + String vToUAllowlist, String vToUDenyList) { mListener = null; mAgentTimeoutParameters = null; mOperationStorage = null; @@ -183,6 +193,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mBackupEligibilityRules = null; this.backupManagerService = backupManagerService; mBackupManagerMonitorEventSender = new BackupManagerMonitorEventSender(/* monitor= */ null); + mVToUAllowlist = createVToUList(vToUAllowlist); + mVToUDenylist = createVToUList(vToUDenyList); } // This task can assume that the wakelock is properly held for it and doesn't have to worry @@ -223,6 +235,18 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); mBackupEligibilityRules = backupEligibilityRules; + mVToUAllowlist = + createVToUList( + Settings.Secure.getStringForUser( + backupManagerService.getContext().getContentResolver(), + Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, + mUserId)); + mVToUDenylist = + createVToUList( + Settings.Secure.getStringForUser( + backupManagerService.getContext().getContentResolver(), + Settings.Secure.V_TO_U_RESTORE_DENYLIST, + mUserId)); if (targetPackage != null) { // Single package restore @@ -636,60 +660,29 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // Data is from a "newer" version of the app than we have currently // installed. If the app has not declared that it is prepared to // handle this case, we do not attempt the restore. - if ((mCurrentPackage.applicationInfo.flags - & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) - == 0) { - String message = - "Source version " - + metaInfo.versionCode - + " > installed version " - + mCurrentPackage.getLongVersionCode(); - Slog.w(TAG, "Package " + pkgName + ": " + message); - Bundle monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - null, - BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, - metaInfo.versionCode); - monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - monitoringExtras, - BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, - false); - monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); - mBackupManagerMonitorEventSender.monitorEvent( - BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, - mCurrentPackage, - BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, - monitoringExtras); - EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); - nextState = UnifiedRestoreState.RUNNING_QUEUE; - return; + if (mIsSystemRestore + && isVToUDowngrade(mPmAgent.getSourceSdk(), android.os.Build.VERSION.SDK_INT)) { + if (isPackageEligibleForVToURestore(mCurrentPackage)) { + Slog.i(TAG, "Package " + pkgName + + " is eligible for V to U downgrade scenario"); + } else { + String message = "Package not eligible for V to U downgrade scenario"; + Slog.i(TAG, pkgName + " : " + message); + EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); + nextState = UnifiedRestoreState.RUNNING_QUEUE; + return; + } } else { - if (DEBUG) { - Slog.v( - TAG, - "Source version " - + metaInfo.versionCode - + " > installed version " - + mCurrentPackage.getLongVersionCode() - + " but restoreAnyVersion"); + if ((mCurrentPackage.applicationInfo.flags + & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) + == 0) { + // Downgrade scenario with RestoreAnyVersion flag off + logDowngradeScenario(/* isRestoreAnyVersion */ false, metaInfo); + nextState = UnifiedRestoreState.RUNNING_QUEUE; + return; + } else { + logDowngradeScenario(/* isRestoreAnyVersion */ true, metaInfo); } - Bundle monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - null, - BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, - metaInfo.versionCode); - monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - monitoringExtras, - BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, - true); - monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); - mBackupManagerMonitorEventSender.monitorEvent( - BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, - mCurrentPackage, - BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, - monitoringExtras); } } @@ -1673,4 +1666,86 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { return mBackupManagerMonitorEventSender.putMonitoringExtra( extras, BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE, RESTORE); } + + // checks the sdk of the target/source device for a B&R operation. + // system components can opt in/out of V->U restore via allowlists. All other apps are + // not impacted + @SuppressWarnings("AndroidFrameworkCompatChange") + @VisibleForTesting + protected boolean isVToUDowngrade(int sourceSdk, int targetSdk) { + // We assume that if the source sdk is greater than U then the source is V. + return Flags.enableVToURestoreForSystemComponentsInAllowlist() + && (sourceSdk > Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + && (targetSdk == Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + } + + @VisibleForTesting + protected List<String> createVToUList(@Nullable String listString) { + // The allowlist/denylist is stored as a comma-separated list of package names + List<String> list = new ArrayList<>(); + if (listString != null) { + list = Arrays.asList(listString.split(",")); + } + return list; + } + + @VisibleForTesting + protected boolean isPackageEligibleForVToURestore(PackageInfo mCurrentPackage) { + // A package is eligible for V to U downgrade restore if either: + // - The package has restoreAnyVersion set to false and is part of the V to U allowlist + // (and not in the denylist) + // - The package has restoreAnyVersion set to true and is not part of the denylist + if (mVToUDenylist.contains(mCurrentPackage.packageName)){ + return false; + } else if ((mCurrentPackage.applicationInfo.flags + & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) + == 0) { + // package has restoreAnyVersion set to false + return mVToUAllowlist.contains(mCurrentPackage.packageName); + } else { + // package has restoreAnyVersion set to true and is nor in denylist + return true; + } + } + + private void logDowngradeScenario(boolean isRestoreAnyVersion, Metadata metaInfo) { + Bundle monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + null, + BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, + metaInfo.versionCode); + String message; + if (isRestoreAnyVersion) { + monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + monitoringExtras, + BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, + true); + message = "Source version " + + metaInfo.versionCode + + " > installed version " + + mCurrentPackage.getLongVersionCode() + + " but restoreAnyVersion"; + } else { + monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + monitoringExtras, + BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, + false); + message = "Source version " + + metaInfo.versionCode + + " > installed version " + + mCurrentPackage.getLongVersionCode(); + EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, mCurrentPackage.packageName, + message); + } + Slog.i(TAG, "Package " + mCurrentPackage.packageName + ": " + message); + monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); + mBackupManagerMonitorEventSender.monitorEvent( + BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, + mCurrentPackage, + BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, + monitoringExtras); + } + } diff --git a/services/companion/java/com/android/server/companion/AssociationRevokeProcessor.java b/services/companion/java/com/android/server/companion/AssociationRevokeProcessor.java new file mode 100644 index 000000000000..de6382e316df --- /dev/null +++ b/services/companion/java/com/android/server/companion/AssociationRevokeProcessor.java @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.companion; + +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; +import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; + +import static com.android.internal.util.CollectionUtils.any; +import static com.android.server.companion.MetricUtils.logRemoveAssociation; +import static com.android.server.companion.RolesUtils.removeRoleHolderForAssociation; +import static com.android.server.companion.CompanionDeviceManagerService.PerUserAssociationSet; + +import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.annotation.UserIdInt; +import android.app.ActivityManager; +import android.companion.AssociationInfo; +import android.content.Context; +import android.content.pm.PackageManagerInternal; +import android.os.Binder; +import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Log; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; +import com.android.server.companion.presence.CompanionDevicePresenceMonitor; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * A class response for Association removal. + */ +@SuppressLint("LongLogTag") +public class AssociationRevokeProcessor { + + private static final String TAG = "CDM_AssociationRevokeProcessor"; + private static final boolean DEBUG = false; + private final @NonNull Context mContext; + private final @NonNull CompanionDeviceManagerService mService; + private final @NonNull AssociationStoreImpl mAssociationStore; + private final @NonNull PackageManagerInternal mPackageManagerInternal; + private final @NonNull CompanionDevicePresenceMonitor mDevicePresenceMonitor; + private final @NonNull SystemDataTransferRequestStore mSystemDataTransferRequestStore; + private final @NonNull CompanionApplicationController mCompanionAppController; + private final OnPackageVisibilityChangeListener mOnPackageVisibilityChangeListener; + private final ActivityManager mActivityManager; + + /** + * A structure that consists of a set of revoked associations that pending for role holder + * removal per each user. + * + * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) + * @see #addToPendingRoleHolderRemoval(AssociationInfo) + * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) + * @see #getPendingRoleHolderRemovalAssociationsForUser(int) + */ + @GuardedBy("mRevokedAssociationsPendingRoleHolderRemoval") + private final PerUserAssociationSet mRevokedAssociationsPendingRoleHolderRemoval = + new PerUserAssociationSet(); + /** + * Contains uid-s of packages pending to be removed from the role holder list (after + * revocation of an association), which will happen one the package is no longer visible to the + * user. + * For quicker uid -> (userId, packageName) look-up this is not a {@code Set<Integer>} but + * a {@code Map<Integer, String>} which maps uid-s to packageName-s (userId-s can be derived + * from uid-s using {@link UserHandle#getUserId(int)}). + * + * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) + * @see #addToPendingRoleHolderRemoval(AssociationInfo) + * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) + */ + @GuardedBy("mRevokedAssociationsPendingRoleHolderRemoval") + private final Map<Integer, String> mUidsPendingRoleHolderRemoval = new HashMap<>(); + + AssociationRevokeProcessor(@NonNull CompanionDeviceManagerService service, + @NonNull AssociationStoreImpl associationStore, + @NonNull PackageManagerInternal packageManager, + @NonNull CompanionDevicePresenceMonitor devicePresenceMonitor, + @NonNull CompanionApplicationController applicationController, + @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore) { + mService = service; + mContext = service.getContext(); + mActivityManager = mContext.getSystemService(ActivityManager.class); + mAssociationStore = associationStore; + mPackageManagerInternal = packageManager; + mOnPackageVisibilityChangeListener = + new OnPackageVisibilityChangeListener(mActivityManager); + mDevicePresenceMonitor = devicePresenceMonitor; + mCompanionAppController = applicationController; + mSystemDataTransferRequestStore = systemDataTransferRequestStore; + } + + // TODO: also revoke notification access + void disassociateInternal(int associationId) { + final AssociationInfo association = mAssociationStore.getAssociationById(associationId); + final int userId = association.getUserId(); + final String packageName = association.getPackageName(); + final String deviceProfile = association.getDeviceProfile(); + + if (!maybeRemoveRoleHolderForAssociation(association)) { + // Need to remove the app from list of the role holders, but will have to do it later + // (the app is in foreground at the moment). + addToPendingRoleHolderRemoval(association); + } + + // Need to check if device still present now because CompanionDevicePresenceMonitor will + // remove current connected device after mAssociationStore.removeAssociation + final boolean wasPresent = mDevicePresenceMonitor.isDevicePresent(associationId); + + // Removing the association. + mAssociationStore.removeAssociation(associationId); + // Do not need to persistUserState since CompanionDeviceManagerService will get callback + // from #onAssociationChanged, and it will handle the persistUserState which including + // active and revoked association. + logRemoveAssociation(deviceProfile); + + // Remove all the system data transfer requests for the association. + mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId); + + if (!wasPresent || !association.isNotifyOnDeviceNearby()) return; + // The device was connected and the app was notified: check if we need to unbind the app + // now. + final boolean shouldStayBound = any( + mAssociationStore.getAssociationsForPackage(userId, packageName), + it -> it.isNotifyOnDeviceNearby() + && mDevicePresenceMonitor.isDevicePresent(it.getId())); + if (shouldStayBound) return; + mCompanionAppController.unbindCompanionApplication(userId, packageName); + } + + /** + * First, checks if the companion application should be removed from the list role holders when + * upon association's removal, i.e.: association's profile (matches the role) is not null, + * the application does not have other associations with the same profile, etc. + * + * <p> + * Then, if establishes that the application indeed has to be removed from the list of the role + * holders, checks if it could be done right now - + * {@link android.app.role.RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, java.util.concurrent.Executor, java.util.function.Consumer) RoleManager#removeRoleHolderAsUser()} + * will kill the application's process, which leads poor user experience if the application was + * in foreground when this happened, to avoid this CDMS delays invoking + * {@code RoleManager.removeRoleHolderAsUser()} until the app is no longer in foreground. + * + * @return {@code true} if the application does NOT need be removed from the list of the role + * holders OR if the application was successfully removed from the list of role holders. + * I.e.: from the role-management perspective the association is done with. + * {@code false} if the application needs to be removed from the list of role the role + * holders, BUT it CDMS would prefer to do it later. + * I.e.: application is in the foreground at the moment, but invoking + * {@code RoleManager.removeRoleHolderAsUser()} will kill the application's process, + * which would lead to the poor UX, hence need to try later. + */ + boolean maybeRemoveRoleHolderForAssociation(@NonNull AssociationInfo association) { + if (DEBUG) Log.d(TAG, "maybeRemoveRoleHolderForAssociation() association=" + association); + final String deviceProfile = association.getDeviceProfile(); + + if (deviceProfile == null) { + // No role was granted to for this association, there is nothing else we need to here. + return true; + } + // Do not need to remove the system role since it was pre-granted by the system. + if (deviceProfile.equals(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION)) { + return true; + } + + // Check if the applications is associated with another devices with the profile. If so, + // it should remain the role holder. + final int id = association.getId(); + final int userId = association.getUserId(); + final String packageName = association.getPackageName(); + final boolean roleStillInUse = any( + mAssociationStore.getAssociationsForPackage(userId, packageName), + it -> deviceProfile.equals(it.getDeviceProfile()) && id != it.getId()); + if (roleStillInUse) { + // Application should remain a role holder, there is nothing else we need to here. + return true; + } + + final int packageProcessImportance = getPackageProcessImportance(userId, packageName); + if (packageProcessImportance <= IMPORTANCE_VISIBLE) { + // Need to remove the app from the list of role holders, but the process is visible to + // the user at the moment, so we'll need to it later: log and return false. + Slog.i(TAG, "Cannot remove role holder for the removed association id=" + id + + " now - process is visible."); + return false; + } + + removeRoleHolderForAssociation(mContext, association); + return true; + } + + @SuppressLint("MissingPermission") + private int getPackageProcessImportance(@UserIdInt int userId, @NonNull String packageName) { + return Binder.withCleanCallingIdentity(() -> { + final int uid = + mPackageManagerInternal.getPackageUid(packageName, /* flags */0, userId); + return mActivityManager.getUidImportance(uid); + }); + } + + /** + * Set revoked flag for active association and add the revoked association and the uid into + * the caches. + * + * @see #mRevokedAssociationsPendingRoleHolderRemoval + * @see #mUidsPendingRoleHolderRemoval + * @see OnPackageVisibilityChangeListener + */ + void addToPendingRoleHolderRemoval(@NonNull AssociationInfo association) { + // First: set revoked flag + association = (new AssociationInfo.Builder(association)).setRevoked(true).build(); + final String packageName = association.getPackageName(); + final int userId = association.getUserId(); + final int uid = mPackageManagerInternal.getPackageUid(packageName, /* flags */0, userId); + // Second: add to the set. + synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { + mRevokedAssociationsPendingRoleHolderRemoval.forUser(association.getUserId()) + .add(association); + if (!mUidsPendingRoleHolderRemoval.containsKey(uid)) { + mUidsPendingRoleHolderRemoval.put(uid, packageName); + + if (mUidsPendingRoleHolderRemoval.size() == 1) { + // Just added first uid: start the listener + mOnPackageVisibilityChangeListener.startListening(); + } + } + } + } + + /** + * Remove the revoked association from the cache and also remove the uid from the map if + * there are other associations with the same package still pending for role holder removal. + * + * @see #mRevokedAssociationsPendingRoleHolderRemoval + * @see #mUidsPendingRoleHolderRemoval + * @see OnPackageVisibilityChangeListener + */ + private void removeFromPendingRoleHolderRemoval(@NonNull AssociationInfo association) { + final String packageName = association.getPackageName(); + final int userId = association.getUserId(); + final int uid = mPackageManagerInternal.getPackageUid(packageName, /* flags */ 0, userId); + + synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { + mRevokedAssociationsPendingRoleHolderRemoval.forUser(userId) + .remove(association); + + final boolean shouldKeepUidForRemoval = any( + getPendingRoleHolderRemovalAssociationsForUser(userId), + ai -> packageName.equals(ai.getPackageName())); + // Do not remove the uid from the map since other associations with + // the same packageName still pending for role holder removal. + if (!shouldKeepUidForRemoval) { + mUidsPendingRoleHolderRemoval.remove(uid); + } + + if (mUidsPendingRoleHolderRemoval.isEmpty()) { + // The set is empty now - can "turn off" the listener. + mOnPackageVisibilityChangeListener.stopListening(); + } + } + } + + /** + * @return a copy of the revoked associations set (safeguarding against + * {@code ConcurrentModificationException}-s). + */ + @NonNull Set<AssociationInfo> getPendingRoleHolderRemovalAssociationsForUser( + @UserIdInt int userId) { + synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { + // Return a copy. + return new ArraySet<>(mRevokedAssociationsPendingRoleHolderRemoval.forUser(userId)); + } + } + + private String getPackageNameByUid(int uid) { + synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { + return mUidsPendingRoleHolderRemoval.get(uid); + } + } + + /** + * An OnUidImportanceListener class which watches the importance of the packages. + * In this class, we ONLY interested in the importance of the running process is greater than + * {@link ActivityManager.RunningAppProcessInfo#IMPORTANCE_VISIBLE} for the uids have been added + * into the {@link #mUidsPendingRoleHolderRemoval}. Lastly remove the role holder for the + * revoked associations for the same packages. + * + * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) + * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) + * @see #getPendingRoleHolderRemovalAssociationsForUser(int) + */ + private class OnPackageVisibilityChangeListener implements + ActivityManager.OnUidImportanceListener { + final @NonNull ActivityManager mAm; + + OnPackageVisibilityChangeListener(@NonNull ActivityManager am) { + this.mAm = am; + } + + @SuppressLint("MissingPermission") + void startListening() { + Binder.withCleanCallingIdentity( + () -> mAm.addOnUidImportanceListener( + /* listener */ OnPackageVisibilityChangeListener.this, + ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE)); + } + + @SuppressLint("MissingPermission") + void stopListening() { + Binder.withCleanCallingIdentity( + () -> mAm.removeOnUidImportanceListener( + /* listener */ OnPackageVisibilityChangeListener.this)); + } + + @Override + public void onUidImportance(int uid, int importance) { + if (importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) { + // The lower the importance value the more "important" the process is. + // We are only interested when the process ceases to be visible. + return; + } + + final String packageName = getPackageNameByUid(uid); + if (packageName == null) { + // Not interested in this uid. + return; + } + + final int userId = UserHandle.getUserId(uid); + + boolean needToPersistStateForUser = false; + + for (AssociationInfo association : + getPendingRoleHolderRemovalAssociationsForUser(userId)) { + if (!packageName.equals(association.getPackageName())) continue; + + if (!maybeRemoveRoleHolderForAssociation(association)) { + // Did not remove the role holder, will have to try again later. + continue; + } + + removeFromPendingRoleHolderRemoval(association); + needToPersistStateForUser = true; + } + + if (needToPersistStateForUser) { + mService.postPersistUserState(userId); + } + } + } +} diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index ba1f51baa624..09c77939eb7b 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -22,7 +22,6 @@ import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES; import static android.Manifest.permission.MANAGE_COMPANION_DEVICES; import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE; import static android.Manifest.permission.USE_COMPANION_TRANSPORTS; -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; import static android.companion.DevicePresenceEvent.EVENT_BLE_APPEARED; import static android.companion.DevicePresenceEvent.EVENT_BLE_DISAPPEARED; @@ -39,7 +38,6 @@ import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.Preconditions.checkState; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.companion.AssociationStore.CHANGE_TYPE_UPDATED_ADDRESS_UNCHANGED; -import static com.android.server.companion.MetricUtils.logRemoveAssociation; import static com.android.server.companion.PackageUtils.isRestrictedSettingsAllowed; import static com.android.server.companion.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.PackageUtils.getPackageInfo; @@ -49,7 +47,6 @@ import static com.android.server.companion.PermissionsUtils.enforceCallerCanObse import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr; import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId; import static com.android.server.companion.PermissionsUtils.sanitizeWithCallerChecks; -import static com.android.server.companion.RolesUtils.removeRoleHolderForAssociation; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.DAYS; @@ -61,7 +58,6 @@ import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.app.ActivityManager; -import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.NotificationManager; @@ -149,7 +145,7 @@ public class CompanionDeviceManagerService extends SystemService { static final String TAG = "CDM_CompanionDeviceManagerService"; static final boolean DEBUG = false; - /** Range of Association IDs allocated for a user.*/ + /** Range of Association IDs allocated for a user. */ private static final int ASSOCIATIONS_IDS_PER_USER_RANGE = 100000; private static final long PAIR_WITHOUT_PROMPT_WINDOW_MS = 10 * 60 * 1000; // 10 min @@ -162,8 +158,6 @@ public class CompanionDeviceManagerService extends SystemService { private static final int MAX_CN_LENGTH = 500; private final ActivityManager mActivityManager; - private final OnPackageVisibilityChangeListener mOnPackageVisibilityChangeListener; - private PersistentDataStore mPersistentStore; private final PersistUserStateHandler mUserPersistenceHandler; @@ -175,6 +169,7 @@ public class CompanionDeviceManagerService extends SystemService { private CompanionDevicePresenceMonitor mDevicePresenceMonitor; private CompanionApplicationController mCompanionAppController; private CompanionTransportManager mTransportManager; + private AssociationRevokeProcessor mAssociationRevokeProcessor; private final ActivityTaskManagerInternal mAtmInternal; private final ActivityManagerInternal mAmInternal; @@ -193,33 +188,6 @@ public class CompanionDeviceManagerService extends SystemService { @GuardedBy("mPreviouslyUsedIds") private final SparseArray<Map<String, Set<Integer>>> mPreviouslyUsedIds = new SparseArray<>(); - /** - * A structure that consists of a set of revoked associations that pending for role holder - * removal per each user. - * - * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) - * @see #addToPendingRoleHolderRemoval(AssociationInfo) - * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) - * @see #getPendingRoleHolderRemovalAssociationsForUser(int) - */ - @GuardedBy("mRevokedAssociationsPendingRoleHolderRemoval") - private final PerUserAssociationSet mRevokedAssociationsPendingRoleHolderRemoval = - new PerUserAssociationSet(); - /** - * Contains uid-s of packages pending to be removed from the role holder list (after - * revocation of an association), which will happen one the package is no longer visible to the - * user. - * For quicker uid -> (userId, packageName) look-up this is not a {@code Set<Integer>} but - * a {@code Map<Integer, String>} which maps uid-s to packageName-s (userId-s can be derived - * from uid-s using {@link UserHandle#getUserId(int)}). - * - * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) - * @see #addToPendingRoleHolderRemoval(AssociationInfo) - * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) - */ - @GuardedBy("mRevokedAssociationsPendingRoleHolderRemoval") - private final Map<Integer, String> mUidsPendingRoleHolderRemoval = new HashMap<>(); - private final RemoteCallbackList<IOnAssociationsChangedListener> mListeners = new RemoteCallbackList<>(); @@ -243,8 +211,6 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationStore = new AssociationStoreImpl(); mSystemDataTransferRequestStore = new SystemDataTransferRequestStore(); - mOnPackageVisibilityChangeListener = - new OnPackageVisibilityChangeListener(mActivityManager); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mObservableUuidStore = new ObservableUuidStore(); } @@ -276,6 +242,9 @@ public class CompanionDeviceManagerService extends SystemService { mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); + mAssociationRevokeProcessor = new AssociationRevokeProcessor(this, mAssociationStore, + mPackageManagerInternal, mDevicePresenceMonitor, mCompanionAppController, + mSystemDataTransferRequestStore); // TODO(b/279663946): move context sync to a dedicated system service mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager); @@ -307,12 +276,13 @@ public class CompanionDeviceManagerService extends SystemService { mBackupRestoreProcessor.addToPendingAppInstall(association); } else if (!association.isRevoked()) { activeAssociations.add(association); - } else if (maybeRemoveRoleHolderForAssociation(association)) { + } else if (mAssociationRevokeProcessor.maybeRemoveRoleHolderForAssociation( + association)) { // Nothing more to do here, but we'll need to persist all the associations to the // disk afterwards. usersToPersistStateFor.add(association.getUserId()); } else { - addToPendingRoleHolderRemoval(association); + mAssociationRevokeProcessor.addToPendingRoleHolderRemoval(association); } } @@ -374,7 +344,7 @@ public class CompanionDeviceManagerService extends SystemService { final List<ParcelUuid> deviceUuids = ArrayUtils.isEmpty(bluetoothDeviceUuids) ? Collections.emptyList() : Arrays.asList(bluetoothDeviceUuids); - for (AssociationInfo ai: + for (AssociationInfo ai : mAssociationStore.getAssociationsByAddress(bluetoothDevice.getAddress())) { Slog.i(TAG, "onUserUnlocked, device id( " + ai.getId() + " ) is connected"); mDevicePresenceMonitor.onBluetoothCompanionDeviceConnected(ai.getId()); @@ -495,7 +465,7 @@ public class CompanionDeviceManagerService extends SystemService { final String packageName = uuid.getPackageName(); final int userId = uuid.getUserId(); - switch(event) { + switch (event) { case EVENT_BT_CONNECTED: if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) { mCompanionAppController.bindCompanionApplication( @@ -544,8 +514,8 @@ public class CompanionDeviceManagerService extends SystemService { /** * @return whether the package should be bound (i.e. at least one of the devices associated with - * the package is currently present OR the UUID to be observed by this package is - * currently present). + * the package is currently present OR the UUID to be observed by this package is + * currently present). */ private boolean shouldBindPackage(@UserIdInt int userId, @NonNull String packageName) { final List<AssociationInfo> packageAssociations = @@ -599,7 +569,8 @@ public class CompanionDeviceManagerService extends SystemService { allAssociations = new ArrayList<>( mAssociationStore.getAssociationsForUser(userId)); // ... and add the revoked (removed) association, that are yet to be permanently removed. - allAssociations.addAll(getPendingRoleHolderRemovalAssociationsForUser(userId)); + allAssociations.addAll( + mAssociationRevokeProcessor.getPendingRoleHolderRemovalAssociationsForUser(userId)); // ... and add the restored associations that are pending missing package installation. allAssociations.addAll(mBackupRestoreProcessor .getAssociationsPendingAppInstallForUser(userId)); @@ -654,7 +625,7 @@ public class CompanionDeviceManagerService extends SystemService { } // Clear role holders for (AssociationInfo association : associationsForPackage) { - maybeRemoveRoleHolderForAssociation(association); + mAssociationRevokeProcessor.maybeRemoveRoleHolderForAssociation(association); } // Clear the uuids to be observed. for (ObservableUuid uuid : uuidsTobeObserved) { @@ -712,7 +683,7 @@ public class CompanionDeviceManagerService extends SystemService { final int id = association.getId(); Slog.i(TAG, "Removing inactive self-managed association id=" + id); - disassociateInternal(id); + mAssociationRevokeProcessor.disassociateInternal(id); } } @@ -857,7 +828,7 @@ public class CompanionDeviceManagerService extends SystemService { final AssociationInfo association = getAssociationWithCallerChecks(userId, packageName, deviceMacAddress); - disassociateInternal(association.getId()); + mAssociationRevokeProcessor.disassociateInternal(association.getId()); } @Override @@ -866,7 +837,7 @@ public class CompanionDeviceManagerService extends SystemService { final AssociationInfo association = getAssociationWithCallerChecks(associationId); - disassociateInternal(association.getId()); + mAssociationRevokeProcessor.disassociateInternal(association.getId()); } @Override @@ -902,9 +873,9 @@ public class CompanionDeviceManagerService extends SystemService { } /** - * @deprecated Use - * {@link NotificationManager#isNotificationListenerAccessGranted(ComponentName)} instead. - */ + * @deprecated Use + * {@link NotificationManager#isNotificationListenerAccessGranted(ComponentName)} instead. + */ @Deprecated @Override public boolean hasNotificationAccess(ComponentName component) throws RemoteException { @@ -1300,7 +1271,7 @@ public class CompanionDeviceManagerService extends SystemService { return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, mAssociationRequestsProcessor, - mBackupRestoreProcessor) + mBackupRestoreProcessor, mAssociationRevokeProcessor) .exec(this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args); } @@ -1381,7 +1352,7 @@ public class CompanionDeviceManagerService extends SystemService { // another association by the time when it is activated from the package installation. final Set<AssociationInfo> pendingAssociations = mBackupRestoreProcessor .getAssociationsPendingAppInstallForUser(userId); - for (AssociationInfo it: pendingAssociations) { + for (AssociationInfo it : pendingAssociations) { usedIds.put(it.getId(), true); } @@ -1407,198 +1378,6 @@ public class CompanionDeviceManagerService extends SystemService { } } - // TODO: also revoke notification access - void disassociateInternal(int associationId) { - final AssociationInfo association = mAssociationStore.getAssociationById(associationId); - final int userId = association.getUserId(); - final String packageName = association.getPackageName(); - final String deviceProfile = association.getDeviceProfile(); - - if (!maybeRemoveRoleHolderForAssociation(association)) { - // Need to remove the app from list of the role holders, but will have to do it later - // (the app is in foreground at the moment). - addToPendingRoleHolderRemoval(association); - } - - // Need to check if device still present now because CompanionDevicePresenceMonitor will - // remove current connected device after mAssociationStore.removeAssociation - final boolean wasPresent = mDevicePresenceMonitor.isDevicePresent(associationId); - - // Removing the association. - mAssociationStore.removeAssociation(associationId); - // Do not need to persistUserState since CompanionDeviceManagerService will get callback - // from #onAssociationChanged, and it will handle the persistUserState which including - // active and revoked association. - logRemoveAssociation(deviceProfile); - - // Remove all the system data transfer requests for the association. - mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId); - - if (!wasPresent || !association.isNotifyOnDeviceNearby()) return; - // The device was connected and the app was notified: check if we need to unbind the app - // now. - final boolean shouldStayBound = any( - mAssociationStore.getAssociationsForPackage(userId, packageName), - it -> it.isNotifyOnDeviceNearby() - && mDevicePresenceMonitor.isDevicePresent(it.getId())); - if (shouldStayBound) return; - mCompanionAppController.unbindCompanionApplication(userId, packageName); - } - - /** - * First, checks if the companion application should be removed from the list role holders when - * upon association's removal, i.e.: association's profile (matches the role) is not null, - * the application does not have other associations with the same profile, etc. - * - * <p> - * Then, if establishes that the application indeed has to be removed from the list of the role - * holders, checks if it could be done right now - - * {@link android.app.role.RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, java.util.concurrent.Executor, java.util.function.Consumer) RoleManager#removeRoleHolderAsUser()} - * will kill the application's process, which leads poor user experience if the application was - * in foreground when this happened, to avoid this CDMS delays invoking - * {@code RoleManager.removeRoleHolderAsUser()} until the app is no longer in foreground. - * - * @return {@code true} if the application does NOT need be removed from the list of the role - * holders OR if the application was successfully removed from the list of role holders. - * I.e.: from the role-management perspective the association is done with. - * {@code false} if the application needs to be removed from the list of role the role - * holders, BUT it CDMS would prefer to do it later. - * I.e.: application is in the foreground at the moment, but invoking - * {@code RoleManager.removeRoleHolderAsUser()} will kill the application's process, - * which would lead to the poor UX, hence need to try later. - */ - - private boolean maybeRemoveRoleHolderForAssociation(@NonNull AssociationInfo association) { - if (DEBUG) Log.d(TAG, "maybeRemoveRoleHolderForAssociation() association=" + association); - - final String deviceProfile = association.getDeviceProfile(); - if (deviceProfile == null) { - // No role was granted to for this association, there is nothing else we need to here. - return true; - } - // Do not need to remove the system role since it was pre-granted by the system. - if (deviceProfile.equals(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION)) { - return true; - } - - // Check if the applications is associated with another devices with the profile. If so, - // it should remain the role holder. - final int id = association.getId(); - final int userId = association.getUserId(); - final String packageName = association.getPackageName(); - final boolean roleStillInUse = any( - mAssociationStore.getAssociationsForPackage(userId, packageName), - it -> deviceProfile.equals(it.getDeviceProfile()) && id != it.getId()); - if (roleStillInUse) { - // Application should remain a role holder, there is nothing else we need to here. - return true; - } - - final int packageProcessImportance = getPackageProcessImportance(userId, packageName); - if (packageProcessImportance <= IMPORTANCE_VISIBLE) { - // Need to remove the app from the list of role holders, but the process is visible to - // the user at the moment, so we'll need to it later: log and return false. - Slog.i(TAG, "Cannot remove role holder for the removed association id=" + id - + " now - process is visible."); - return false; - } - - removeRoleHolderForAssociation(getContext(), association); - return true; - } - - private int getPackageProcessImportance(@UserIdInt int userId, @NonNull String packageName) { - return Binder.withCleanCallingIdentity(() -> { - final int uid = - mPackageManagerInternal.getPackageUid(packageName, /* flags */0, userId); - return mActivityManager.getUidImportance(uid); - }); - } - - /** - * Set revoked flag for active association and add the revoked association and the uid into - * the caches. - * - * @see #mRevokedAssociationsPendingRoleHolderRemoval - * @see #mUidsPendingRoleHolderRemoval - * @see OnPackageVisibilityChangeListener - */ - private void addToPendingRoleHolderRemoval(@NonNull AssociationInfo association) { - // First: set revoked flag. - association = (new AssociationInfo.Builder(association)) - .setRevoked(true) - .build(); - - final String packageName = association.getPackageName(); - final int userId = association.getUserId(); - final int uid = mPackageManagerInternal.getPackageUid(packageName, /* flags */0, userId); - - // Second: add to the set. - synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { - mRevokedAssociationsPendingRoleHolderRemoval.forUser(association.getUserId()) - .add(association); - if (!mUidsPendingRoleHolderRemoval.containsKey(uid)) { - mUidsPendingRoleHolderRemoval.put(uid, packageName); - - if (mUidsPendingRoleHolderRemoval.size() == 1) { - // Just added first uid: start the listener - mOnPackageVisibilityChangeListener.startListening(); - } - } - } - } - - /** - * Remove the revoked association from the cache and also remove the uid from the map if - * there are other associations with the same package still pending for role holder removal. - * - * @see #mRevokedAssociationsPendingRoleHolderRemoval - * @see #mUidsPendingRoleHolderRemoval - * @see OnPackageVisibilityChangeListener - */ - private void removeFromPendingRoleHolderRemoval(@NonNull AssociationInfo association) { - final String packageName = association.getPackageName(); - final int userId = association.getUserId(); - final int uid = mPackageManagerInternal.getPackageUid(packageName, /* flags */0, userId); - - synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { - mRevokedAssociationsPendingRoleHolderRemoval.forUser(userId) - .remove(association); - - final boolean shouldKeepUidForRemoval = any( - getPendingRoleHolderRemovalAssociationsForUser(userId), - ai -> packageName.equals(ai.getPackageName())); - // Do not remove the uid from the map since other associations with - // the same packageName still pending for role holder removal. - if (!shouldKeepUidForRemoval) { - mUidsPendingRoleHolderRemoval.remove(uid); - } - - if (mUidsPendingRoleHolderRemoval.isEmpty()) { - // The set is empty now - can "turn off" the listener. - mOnPackageVisibilityChangeListener.stopListening(); - } - } - } - - /** - * @return a copy of the revoked associations set (safeguarding against - * {@code ConcurrentModificationException}-s). - */ - private @NonNull Set<AssociationInfo> getPendingRoleHolderRemovalAssociationsForUser( - @UserIdInt int userId) { - synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { - // Return a copy. - return new ArraySet<>(mRevokedAssociationsPendingRoleHolderRemoval.forUser(userId)); - } - } - - private String getPackageNameByUid(int uid) { - synchronized (mRevokedAssociationsPendingRoleHolderRemoval) { - return mUidsPendingRoleHolderRemoval.get(uid); - } - } - void updateSpecialAccessPermissionForAssociatedPackage(AssociationInfo association) { final PackageInfo packageInfo = getPackageInfo(getContext(), association.getUserId(), association.getPackageName()); @@ -1704,11 +1483,11 @@ public class CompanionDeviceManagerService extends SystemService { private final AssociationStore.OnChangeListener mAssociationStoreChangeListener = new AssociationStore.OnChangeListener() { - @Override - public void onAssociationChanged(int changeType, AssociationInfo association) { - onAssociationChangedInternal(changeType, association); - } - }; + @Override + public void onAssociationChanged(int changeType, AssociationInfo association) { + onAssociationChangedInternal(changeType, association); + } + }; private final CompanionDevicePresenceMonitor.Callback mDevicePresenceCallback = new CompanionDevicePresenceMonitor.Callback() { @@ -1731,7 +1510,7 @@ public class CompanionDeviceManagerService extends SystemService { public void onDevicePresenceEventByUuid(ObservableUuid uuid, int event) { onDevicePresenceEventByUuidInternal(uuid, event); } - }; + }; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override @@ -1887,73 +1666,8 @@ public class CompanionDeviceManagerService extends SystemService { } } - /** - * An OnUidImportanceListener class which watches the importance of the packages. - * In this class, we ONLY interested in the importance of the running process is greater than - * {@link RunningAppProcessInfo.IMPORTANCE_VISIBLE} for the uids have been added into the - * {@link mUidsPendingRoleHolderRemoval}. Lastly remove the role holder for the revoked - * associations for the same packages. - * - * @see #maybeRemoveRoleHolderForAssociation(AssociationInfo) - * @see #removeFromPendingRoleHolderRemoval(AssociationInfo) - * @see #getPendingRoleHolderRemovalAssociationsForUser(int) - */ - private class OnPackageVisibilityChangeListener implements - ActivityManager.OnUidImportanceListener { - final @NonNull ActivityManager mAm; - - OnPackageVisibilityChangeListener(@NonNull ActivityManager am) { - this.mAm = am; - } - - void startListening() { - Binder.withCleanCallingIdentity( - () -> mAm.addOnUidImportanceListener( - /* listener */ OnPackageVisibilityChangeListener.this, - RunningAppProcessInfo.IMPORTANCE_VISIBLE)); - } - - void stopListening() { - Binder.withCleanCallingIdentity( - () -> mAm.removeOnUidImportanceListener( - /* listener */ OnPackageVisibilityChangeListener.this)); - } - - @Override - public void onUidImportance(int uid, int importance) { - if (importance <= RunningAppProcessInfo.IMPORTANCE_VISIBLE) { - // The lower the importance value the more "important" the process is. - // We are only interested when the process ceases to be visible. - return; - } - - final String packageName = getPackageNameByUid(uid); - if (packageName == null) { - // Not interested in this uid. - return; - } - - final int userId = UserHandle.getUserId(uid); - - boolean needToPersistStateForUser = false; - - for (AssociationInfo association : - getPendingRoleHolderRemovalAssociationsForUser(userId)) { - if (!packageName.equals(association.getPackageName())) continue; - - if (!maybeRemoveRoleHolderForAssociation(association)) { - // Did not remove the role holder, will have to try again later. - continue; - } - - removeFromPendingRoleHolderRemoval(association); - needToPersistStateForUser = true; - } - - if (needToPersistStateForUser) { - mUserPersistenceHandler.postPersistUserState(userId); - } - } + void postPersistUserState(@UserIdInt int userId) { + mUserPersistenceHandler.postPersistUserState(userId); } static class PerUserAssociationSet extends PerUser<Set<AssociationInfo>> { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java index 5663434e2b6d..de4f2b60170f 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java @@ -45,6 +45,7 @@ class CompanionDeviceShellCommand extends ShellCommand { private static final String TAG = "CDM_CompanionDeviceShellCommand"; private final CompanionDeviceManagerService mService; + private final AssociationRevokeProcessor mRevokeProcessor; private final AssociationStoreImpl mAssociationStore; private final CompanionDevicePresenceMonitor mDevicePresenceMonitor; private final CompanionTransportManager mTransportManager; @@ -59,7 +60,8 @@ class CompanionDeviceShellCommand extends ShellCommand { CompanionTransportManager transportManager, SystemDataTransferProcessor systemDataTransferProcessor, AssociationRequestsProcessor associationRequestsProcessor, - BackupRestoreProcessor backupRestoreProcessor) { + BackupRestoreProcessor backupRestoreProcessor, + AssociationRevokeProcessor revokeProcessor) { mService = service; mAssociationStore = associationStore; mDevicePresenceMonitor = devicePresenceMonitor; @@ -67,6 +69,7 @@ class CompanionDeviceShellCommand extends ShellCommand { mSystemDataTransferProcessor = systemDataTransferProcessor; mAssociationRequestsProcessor = associationRequestsProcessor; mBackupRestoreProcessor = backupRestoreProcessor; + mRevokeProcessor = revokeProcessor; } @Override @@ -126,7 +129,7 @@ class CompanionDeviceShellCommand extends ShellCommand { final AssociationInfo association = mService.getAssociationWithCallerChecks(userId, packageName, address); if (association != null) { - mService.disassociateInternal(association.getId()); + mRevokeProcessor.disassociateInternal(association.getId()); } } break; @@ -138,7 +141,7 @@ class CompanionDeviceShellCommand extends ShellCommand { mAssociationStore.getAssociationsForPackage(userId, packageName); for (AssociationInfo association : userAssociations) { if (sanitizeWithCallerChecks(mService.getContext(), association) != null) { - mService.disassociateInternal(association.getId()); + mRevokeProcessor.disassociateInternal(association.getId()); } } } diff --git a/services/core/Android.bp b/services/core/Android.bp index 7940ca64b330..d1d7ee7ba0e4 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -41,16 +41,18 @@ java_library_static { genrule { name: "services.core.protologsrc", srcs: [ + ":protolog-impl", ":protolog-groups", ":services.core-sources-am-wm", ], tools: ["protologtool"], cmd: "$(location protologtool) transform-protolog-calls " + "--protolog-class com.android.internal.protolog.common.ProtoLog " + - "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " + - "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + "--loggroups-jar $(location :protolog-groups) " + + "--viewer-config-file-path /etc/core.protolog.pb " + + "--legacy-viewer-config-file-path /system/etc/protolog.conf.json.gz " + + "--legacy-output-file-path /data/misc/wmtrace/wm_log.winscope " + "--output-srcjar $(out) " + "$(locations :services.core-sources-am-wm)", out: ["services.core.protolog.srcjar"], @@ -67,12 +69,30 @@ genrule { "--protolog-class com.android.internal.protolog.common.ProtoLog " + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + "--loggroups-jar $(location :protolog-groups) " + - "--viewer-conf $(out) " + + "--viewer-config-type json " + + "--viewer-config $(out) " + "$(locations :services.core-sources-am-wm)", out: ["services.core.protolog.json"], } genrule { + name: "gen-core.protolog.pb", + srcs: [ + ":protolog-groups", + ":services.core-sources-am-wm", + ], + tools: ["protologtool"], + cmd: "$(location protologtool) generate-viewer-config " + + "--protolog-class com.android.internal.protolog.common.ProtoLog " + + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + + "--loggroups-jar $(location :protolog-groups) " + + "--viewer-config-type proto " + + "--viewer-config $(out) " + + "$(locations :services.core-sources-am-wm)", + out: ["core.protolog.pb"], +} + +genrule { name: "checked-protolog.json", srcs: [ ":generate-protolog.json", @@ -89,6 +109,22 @@ genrule { } genrule { + name: "checked-core.protolog.pb", + srcs: [ + ":gen-core.protolog.pb", + ":file-core.protolog.pb", + ], + cmd: "cp $(location :gen-core.protolog.pb) $(out) && " + + "{ ! (diff $(out) $(location :file-core.protolog.pb) | grep -q '^<') || " + + "{ echo -e '\\n\\n################################################################\\n#\\n" + + "# ERROR: ProtoLog viewer config is stale. To update it, run:\\n#\\n" + + "# cp $${ANDROID_BUILD_TOP}/$(location :gen-core.protolog.pb) " + + "$${ANDROID_BUILD_TOP}/$(location :file-core.protolog.pb)\\n#\\n" + + "################################################################\\n\\n' >&2 && false; } }", + out: ["core.protolog.pb"], +} + +genrule { name: "statslog-art-java-gen", tools: ["stats-log-api-gen"], cmd: "$(location stats-log-api-gen) --java $(out) --module art" + @@ -158,6 +194,7 @@ java_library_static { "default_television.xml", "gps_debug.conf", "protolog.conf.json.gz", + "core.protolog.pb", ], static_libs: [ @@ -269,3 +306,8 @@ prebuilt_etc { name: "protolog.conf.json.gz", src: ":services.core.json.gz", } + +prebuilt_etc { + name: "core.protolog.pb", + src: ":checked-core.protolog.pb", +} diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java index 81c9ee790d72..4aa5ce19b9b0 100644 --- a/services/core/java/com/android/server/IntentResolver.java +++ b/services/core/java/com/android/server/IntentResolver.java @@ -16,6 +16,8 @@ package com.android.server; +import static android.permission.flags.Flags.ignoreProcessText; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -353,6 +355,13 @@ public abstract class IntentResolver<F, R extends Object> { public List<R> queryIntentFromList(@NonNull Computer computer, Intent intent, String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut, int userId, long customFlags) { + if (Intent.ACTION_PROCESS_TEXT.equals(intent.getAction()) && ignoreProcessText()) { + // This is for an experiment about deprecating PROCESS_TEXT + // Note: SettingsProvider isn't ready early in boot and ACTION_PROCESS_TEXT isn't + // queried during boot so we are checking the action before the flag. + return Collections.emptyList(); + } + ArrayList<R> resultList = new ArrayList<R>(); final boolean debug = localLOGV || @@ -377,6 +386,13 @@ public abstract class IntentResolver<F, R extends Object> { protected final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId, long customFlags) { + if (Intent.ACTION_PROCESS_TEXT.equals(intent.getAction()) && ignoreProcessText()) { + // This is for an experiment about deprecating PROCESS_TEXT + // Note: SettingsProvider isn't ready early in boot and ACTION_PROCESS_TEXT isn't + // queried during boot so we are checking the action before the flag. + return Collections.emptyList(); + } + String scheme = intent.getScheme(); ArrayList<R> finalList = new ArrayList<R>(); diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java index 0904c47b61f2..7d8aad7ab490 100644 --- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java +++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java @@ -63,6 +63,9 @@ public final class SensitiveContentProtectionManagerService extends SystemServic @Nullable private MediaProjectionManager mProjectionManager; @Nullable private WindowManagerInternal mWindowManager; + // screen recorder packages exempted from screen share protection. + private ArraySet<String> mExemptedPackages = null; + final Object mSensitiveContentProtectionLock = new Object(); @GuardedBy("mSensitiveContentProtectionLock") @@ -76,7 +79,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic Trace.beginSection( "SensitiveContentProtectionManagerService.onProjectionStart"); try { - onProjectionStart(); + onProjectionStart(info); } finally { Trace.endSection(); } @@ -113,15 +116,25 @@ public final class SensitiveContentProtectionManagerService extends SystemServic if (DEBUG) Log.d(TAG, "onBootPhase - PHASE_BOOT_COMPLETED"); init(getContext().getSystemService(MediaProjectionManager.class), - LocalServices.getService(WindowManagerInternal.class)); + LocalServices.getService(WindowManagerInternal.class), + getExemptedPackages()); if (sensitiveContentAppProtection()) { publishBinderService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE, new SensitiveContentProtectionManagerServiceBinder()); } } + // These packages are exempted from screen share protection. + private ArraySet<String> getExemptedPackages() { + final ArraySet<String> exemptedPackages = + SystemConfig.getInstance().getBugreportWhitelistedPackages(); + // TODO(b/323361046) - Add sys ui recorder package. + return exemptedPackages; + } + @VisibleForTesting - void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager) { + void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager, + ArraySet<String> exemptedPackages) { if (DEBUG) Log.d(TAG, "init"); Objects.requireNonNull(projectionManager); @@ -129,6 +142,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic mProjectionManager = projectionManager; mWindowManager = windowManager; + mExemptedPackages = exemptedPackages; // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary // handler, delegate, and binder death recipient @@ -165,7 +179,11 @@ public final class SensitiveContentProtectionManagerService extends SystemServic } } - private void onProjectionStart() { + private void onProjectionStart(MediaProjectionInfo info) { + if (mExemptedPackages != null && mExemptedPackages.contains(info.getPackageName())) { + Log.w(TAG, info.getPackageName() + " is exempted from screen share protection."); + return; + } // TODO(b/324447419): move GlobalSettings lookup to background thread boolean disableScreenShareProtections = Settings.Global.getInt(getContext().getContentResolver(), diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2dd2f8fde797..e222878a5dd3 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18462,7 +18462,8 @@ public class ActivityManagerService extends IActivityManager.Stub (WindowProcessController) procsToKill.get(i); final ProcessRecord pr = (ProcessRecord) wpc.mOwner; if (ActivityManager.isProcStateBackground(pr.mState.getSetProcState()) - && pr.mReceivers.numberOfCurReceivers() == 0) { + && pr.mReceivers.numberOfCurReceivers() == 0 + && !pr.mState.hasStartedServices()) { pr.killLocked("remove task", ApplicationExitInfo.REASON_USER_REQUESTED, ApplicationExitInfo.SUBREASON_REMOVE_TASK, true); } else { diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 9568116288b5..31328ae83f71 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -3322,7 +3322,8 @@ public class OomAdjuster { reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); } if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0 - && ActivityManager.isProcStateBackground(state.getSetProcState())) { + && ActivityManager.isProcStateBackground(state.getSetProcState()) + && !state.hasStartedServices()) { app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED, ApplicationExitInfo.SUBREASON_REMOVE_TASK, true); success = false; diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java index 1412259abf89..2ef433cad8ce 100644 --- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java @@ -64,6 +64,9 @@ import com.android.server.wm.WindowProcessController; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -76,6 +79,9 @@ import java.util.concurrent.atomic.AtomicLong; * The error state of the process, such as if it's crashing/ANR etc. */ class ProcessErrorStateRecord { + private static final DateTimeFormatter DROPBOX_TIME_FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ"); + final ProcessRecord mApp; private final ActivityManagerService mService; @@ -444,6 +450,13 @@ class ProcessErrorStateRecord { info.append("ErrorId: ").append(errorId.toString()).append("\n"); } info.append("Frozen: ").append(mApp.mOptRecord.isFrozen()).append("\n"); + if (timeoutRecord != null && timeoutRecord.mEndUptimeMillis > 0) { + long millisSinceEndUptimeMs = anrTime - timeoutRecord.mEndUptimeMillis; + String formattedTime = DROPBOX_TIME_FORMATTER.format( + Instant.now().minusMillis(millisSinceEndUptimeMs) + .atZone(ZoneId.systemDefault())); + info.append("Timestamp: ").append(formattedTime).append("\n"); + } // Retrieve controller with max ANR delay from AnrControllers // Note that we retrieve the controller before dumping stacks because dumping stacks can diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 767f54d6a8c7..d1bda7991f45 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -120,11 +120,13 @@ public class SettingsToPropertiesMapper { static final String[] sDeviceConfigAconfigScopes = new String[] { "accessibility", "android_core_networking", + "android_stylus", "aoc", "app_widgets", "arc_next", "avic", "bluetooth", + "brownout_mitigation_audio", "build", "biometrics", "biometrics_framework", diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 082776ad6085..fb4976d3cef2 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -16,6 +16,7 @@ package com.android.server.display; +import static com.android.server.display.BrightnessMappingStrategy.INVALID_LUX; import static com.android.server.display.config.DisplayBrightnessMappingConfig.autoBrightnessModeToString; import android.annotation.IntDef; @@ -202,7 +203,7 @@ public class AutomaticBrightnessController { private float mScreenBrighteningThreshold; private float mScreenDarkeningThreshold; // The most recent light sample. - private float mLastObservedLux; + private float mLastObservedLux = INVALID_LUX; // The time of the most light recent sample. private long mLastObservedLuxTime; @@ -403,8 +404,8 @@ public class AutomaticBrightnessController { brightnessEvent.setFlags(brightnessEvent.getFlags() | (!mAmbientLuxValid ? BrightnessEvent.FLAG_INVALID_LUX : 0) | (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE - ? BrightnessEvent.FLAG_DOZE_SCALE : 0) - | (isInIdleMode() ? BrightnessEvent.FLAG_IDLE_CURVE : 0)); + ? BrightnessEvent.FLAG_DOZE_SCALE : 0)); + brightnessEvent.setAutoBrightnessMode(getMode()); } if (!mAmbientLuxValid) { @@ -420,6 +421,35 @@ public class AutomaticBrightnessController { return mRawScreenAutoBrightness; } + /** + * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when + * entering doze - we disable the light sensor, invalidate the lux, but we still need to set + * the initial brightness in doze mode. + */ + public float getAutomaticScreenBrightnessBasedOnLastObservedLux( + BrightnessEvent brightnessEvent) { + if (mLastObservedLux == INVALID_LUX) { + return PowerManager.BRIGHTNESS_INVALID_FLOAT; + } + + float brightness = mCurrentBrightnessMapper.getBrightness(mLastObservedLux, + mForegroundAppPackageName, mForegroundAppCategory); + if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) { + brightness *= mDozeScaleFactor; + } + + if (brightnessEvent != null) { + brightnessEvent.setLux(mLastObservedLux); + brightnessEvent.setRecommendedBrightness(brightness); + brightnessEvent.setFlags(brightnessEvent.getFlags() + | (mLastObservedLux == INVALID_LUX ? BrightnessEvent.FLAG_INVALID_LUX : 0) + | (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE + ? BrightnessEvent.FLAG_DOZE_SCALE : 0)); + brightnessEvent.setAutoBrightnessMode(getMode()); + } + return brightness; + } + public boolean hasValidAmbientLux() { return mAmbientLuxValid; } @@ -539,7 +569,7 @@ public class AutomaticBrightnessController { } private boolean setScreenBrightnessByUser(float lux, float brightness) { - if (lux == BrightnessMappingStrategy.INVALID_LUX || Float.isNaN(brightness)) { + if (lux == INVALID_LUX || Float.isNaN(brightness)) { return false; } mCurrentBrightnessMapper.addUserDataPoint(lux, brightness); @@ -564,6 +594,15 @@ public class AutomaticBrightnessController { return false; } + /** + * @return The auto-brightness mode of the current mapping strategy. Different modes use + * different brightness curves. + */ + @AutomaticBrightnessController.AutomaticBrightnessMode + public int getMode() { + return mCurrentBrightnessMapper.getMode(); + } + public boolean isInIdleMode() { return mCurrentBrightnessMapper.getMode() == AUTO_BRIGHTNESS_MODE_IDLE; } @@ -1236,12 +1275,12 @@ public class AutomaticBrightnessController { // light. // The anchor determines what were the light levels when the user has set their preference, // and we use a relative threshold to determine when to revert to the OEM curve. - private float mAnchor = BrightnessMappingStrategy.INVALID_LUX; + private float mAnchor = INVALID_LUX; private float mBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; private boolean mIsValid = false; private void reset() { - mAnchor = BrightnessMappingStrategy.INVALID_LUX; + mAnchor = INVALID_LUX; mBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; mIsValid = false; } @@ -1265,7 +1304,7 @@ public class AutomaticBrightnessController { private boolean maybeReset(float currentLux) { // If the short term model was invalidated and the change is drastic enough, reset it. // Otherwise, we revalidate it. - if (!mIsValid && mAnchor != BrightnessMappingStrategy.INVALID_LUX) { + if (!mIsValid && mAnchor != INVALID_LUX) { if (mCurrentBrightnessMapper.shouldResetShortTermModel(currentLux, mAnchor)) { resetShortTermModel(); } else { diff --git a/services/core/java/com/android/server/display/BrightnessThrottler.java b/services/core/java/com/android/server/display/BrightnessThrottler.java index bba5ba35dbc7..631e7518b746 100644 --- a/services/core/java/com/android/server/display/BrightnessThrottler.java +++ b/services/core/java/com/android/server/display/BrightnessThrottler.java @@ -37,9 +37,11 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; +import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.utils.DebugUtils; import com.android.server.display.utils.DeviceConfigParsingUtils; +import com.android.server.display.utils.SensorUtils; import java.io.PrintWriter; import java.util.HashMap; @@ -79,7 +81,7 @@ class BrightnessThrottler { // Maps the throttling ID to the data. Sourced from DisplayDeviceConfig. @NonNull - private HashMap<String, ThermalBrightnessThrottlingData> mDdcThermalThrottlingDataMap; + private Map<String, ThermalBrightnessThrottlingData> mDdcThermalThrottlingDataMap; // Current throttling data being used. // Null if we do not support throttling. @@ -97,6 +99,10 @@ class BrightnessThrottler { // The brightness throttling configuration that should be used. private String mThermalBrightnessThrottlingDataId; + // Temperature Sensor to be monitored for throttling. + @NonNull + private SensorData mTempSensor; + // This is a collection of brightness throttling data that has been written as overrides from // the DeviceConfig. This will always take priority over the display device config data. // We need to store the data for every display device, so we do not need to update this each @@ -121,17 +127,19 @@ class BrightnessThrottler { BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, - @NonNull HashMap<String, ThermalBrightnessThrottlingData> - thermalBrightnessThrottlingDataMap) { - this(new Injector(), handler, handler, throttlingChangeCallback, - uniqueDisplayId, throttlingDataId, thermalBrightnessThrottlingDataMap); + @NonNull DisplayDeviceConfig displayDeviceConfig) { + this(new Injector(), handler, handler, throttlingChangeCallback, uniqueDisplayId, + throttlingDataId, + displayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), + displayDeviceConfig.getTempSensor()); } @VisibleForTesting BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler, Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, - @NonNull HashMap<String, ThermalBrightnessThrottlingData> - thermalBrightnessThrottlingDataMap) { + @NonNull Map<String, ThermalBrightnessThrottlingData> + thermalBrightnessThrottlingDataMap, + @NonNull SensorData tempSensor) { mInjector = injector; mHandler = handler; @@ -147,7 +155,7 @@ class BrightnessThrottler { mDdcThermalThrottlingDataMap = thermalBrightnessThrottlingDataMap; loadThermalBrightnessThrottlingDataFromDeviceConfig(); loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(mDdcThermalThrottlingDataMap, - mThermalBrightnessThrottlingDataId, mUniqueDisplayId); + tempSensor, mThermalBrightnessThrottlingDataId, mUniqueDisplayId); } boolean deviceSupportsThrottling() { @@ -180,12 +188,14 @@ class BrightnessThrottler { } void loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( - HashMap<String, ThermalBrightnessThrottlingData> ddcThrottlingDataMap, + Map<String, ThermalBrightnessThrottlingData> ddcThrottlingDataMap, + SensorData tempSensor, String brightnessThrottlingDataId, String uniqueDisplayId) { mDdcThermalThrottlingDataMap = ddcThrottlingDataMap; mThermalBrightnessThrottlingDataId = brightnessThrottlingDataId; mUniqueDisplayId = uniqueDisplayId; + mTempSensor = tempSensor; resetThermalThrottlingData(); } @@ -310,7 +320,7 @@ class BrightnessThrottler { } if (deviceSupportsThrottling()) { - mSkinThermalStatusObserver.startObserving(); + mSkinThermalStatusObserver.startObserving(mTempSensor); } } @@ -357,6 +367,7 @@ class BrightnessThrottler { private final class SkinThermalStatusObserver extends IThermalEventListener.Stub { private final Injector mInjector; private final Handler mHandler; + private SensorData mObserverTempSensor; private IThermalService mThermalService; private boolean mStarted; @@ -371,28 +382,51 @@ class BrightnessThrottler { if (DEBUG) { Slog.d(TAG, "New thermal throttling status = " + temp.getStatus()); } + + if (mObserverTempSensor.name != null + && !mObserverTempSensor.name.equals(temp.getName())) { + Slog.i(TAG, "Skipping thermal throttling notification as monitored sensor: " + + mObserverTempSensor.name + + " != notified sensor: " + + temp.getName()); + return; + } mHandler.post(() -> { final @Temperature.ThrottlingStatus int status = temp.getStatus(); thermalStatusChanged(status); }); } - void startObserving() { - if (mStarted) { + void startObserving(SensorData tempSensor) { + if (!mStarted || mObserverTempSensor == null) { + mObserverTempSensor = tempSensor; + registerThermalListener(); + return; + } + + String curType = mObserverTempSensor.type; + mObserverTempSensor = tempSensor; + if (curType.equals(tempSensor.type)) { if (DEBUG) { Slog.d(TAG, "Thermal status observer already started"); } return; } + stopObserving(); + registerThermalListener(); + } + + void registerThermalListener() { mThermalService = mInjector.getThermalService(); if (mThermalService == null) { Slog.e(TAG, "Could not observe thermal status. Service not available"); return; } + int temperatureType = SensorUtils.getSensorTemperatureType(mObserverTempSensor); try { // We get a callback immediately upon registering so there's no need to query // for the current value. - mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN); + mThermalService.registerThermalEventListenerWithType(this, temperatureType); mStarted = true; } catch (RemoteException e) { Slog.e(TAG, "Failed to register thermal status listener", e); @@ -418,6 +452,7 @@ class BrightnessThrottler { void dump(PrintWriter writer) { writer.println(" SkinThermalStatusObserver:"); writer.println(" mStarted: " + mStarted); + writer.println(" mObserverTempSensor: " + mObserverTempSensor); if (mThermalService != null) { writer.println(" ThermalService available"); } else { diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index d1374a5ab9dc..9b2dcc53f456 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -384,6 +384,10 @@ import javax.xml.datatype.DatatypeConfigurationException; * </point> * </supportedModes> * </proxSensor> + * <tempSensor> + * <type>DISPLAY</type> + * <name>VIRTUAL-SKIN-DISPLAY</name> + * </tempSensor> * * <ambientLightHorizonLong>10001</ambientLightHorizonLong> * <ambientLightHorizonShort>2001</ambientLightHorizonShort> @@ -625,6 +629,12 @@ public class DisplayDeviceConfig { @Nullable private SensorData mProximitySensor; + // The details of the temperature sensor associated with this display. + // Throttling will be based on thermal status of this sensor. + // For empty values default back to sensor of TYPE_SKIN. + @NonNull + private SensorData mTempSensor; + private final List<RefreshRateLimitation> mRefreshRateLimitations = new ArrayList<>(2 /*initialCapacity*/); @@ -821,10 +831,10 @@ public class DisplayDeviceConfig { private String mLowBlockingZoneThermalMapId = null; private String mHighBlockingZoneThermalMapId = null; - private final HashMap<String, ThermalBrightnessThrottlingData> + private final Map<String, ThermalBrightnessThrottlingData> mThermalBrightnessThrottlingDataMapByThrottlingId = new HashMap<>(); - private final HashMap<String, PowerThrottlingData> + private final Map<String, PowerThrottlingData> mPowerThrottlingDataMapByThrottlingId = new HashMap<>(); private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>> @@ -1489,6 +1499,13 @@ public class DisplayDeviceConfig { return mProximitySensor; } + /** + * @return temperature sensor data associated with the display. + */ + public SensorData getTempSensor() { + return mTempSensor; + } + boolean isAutoBrightnessAvailable() { return mAutoBrightnessAvailable; } @@ -1539,7 +1556,7 @@ public class DisplayDeviceConfig { /** * @return brightness throttling configuration data for this display, for each throttling id. */ - public HashMap<String, ThermalBrightnessThrottlingData> + public Map<String, ThermalBrightnessThrottlingData> getThermalBrightnessThrottlingDataMapByThrottlingId() { return mThermalBrightnessThrottlingDataMapByThrottlingId; } @@ -1558,7 +1575,7 @@ public class DisplayDeviceConfig { /** * @return power throttling configuration data for this display, for each throttling id. **/ - public HashMap<String, PowerThrottlingData> + public Map<String, PowerThrottlingData> getPowerThrottlingDataMapByThrottlingId() { return mPowerThrottlingDataMapByThrottlingId; } @@ -1871,6 +1888,7 @@ public class DisplayDeviceConfig { + "mAmbientLightSensor=" + mAmbientLightSensor + ", mScreenOffBrightnessSensor=" + mScreenOffBrightnessSensor + ", mProximitySensor=" + mProximitySensor + + ", mTempSensor=" + mTempSensor + ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray()) + ", mDensityMapping= " + mDensityMapping + ", mAutoBrightnessBrighteningLightDebounce= " @@ -1972,6 +1990,7 @@ public class DisplayDeviceConfig { mContext.getResources()); mScreenOffBrightnessSensor = SensorData.loadScreenOffBrightnessSensorConfig(config); mProximitySensor = SensorData.loadProxSensorConfig(config); + mTempSensor = SensorData.loadTempSensorConfig(mFlags, config); loadAmbientHorizonFromDdc(config); loadBrightnessChangeThresholds(config); loadAutoBrightnessConfigValues(config); @@ -1999,6 +2018,7 @@ public class DisplayDeviceConfig { loadBrightnessRampsFromConfigXml(); mAmbientLightSensor = SensorData.loadAmbientLightSensorConfig(mContext.getResources()); mProximitySensor = SensorData.loadSensorUnspecifiedConfig(); + mTempSensor = SensorData.loadTempSensorUnspecifiedConfig(); loadBrightnessChangeThresholdsFromXml(); loadAutoBrightnessConfigsFromConfigXml(); loadAutoBrightnessAvailableFromConfigXml(); @@ -2026,6 +2046,7 @@ public class DisplayDeviceConfig { setSimpleMappingStrategyValues(); mAmbientLightSensor = SensorData.loadAmbientLightSensorConfig(mContext.getResources()); mProximitySensor = SensorData.loadSensorUnspecifiedConfig(); + mTempSensor = SensorData.loadTempSensorUnspecifiedConfig(); loadAutoBrightnessAvailableFromConfigXml(); } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index d5863a73a0c3..dbe85ea0fa04 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; + import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE; @@ -37,7 +39,6 @@ import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.BrightnessInfo; -import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayOffloadSession; import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; @@ -861,6 +862,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId; mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( config.getThermalBrightnessThrottlingDataMapByThrottlingId(), + config.getTempSensor(), mThermalBrightnessThrottlingDataId, mUniqueDisplayId); } @@ -923,6 +925,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig); mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), + mDisplayDeviceConfig.getTempSensor(), mThermalBrightnessThrottlingDataId, mUniqueDisplayId); } @@ -1376,7 +1379,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Switch to doze auto-brightness mode if needed if (mFlags.areAutoBrightnessModesEnabled() && mAutomaticBrightnessController != null && !mAutomaticBrightnessController.isInIdleMode()) { - setAutomaticScreenBrightnessMode(Display.isDozeState(state) + mAutomaticBrightnessController.switchMode(mPowerRequest.policy == POLICY_DOZE ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT); } @@ -1464,6 +1467,22 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false); } + // If there's an offload session and auto-brightness is on, we need to set the initial doze + // brightness using the doze auto-brightness curve before the offload session starts + // controlling the brightness. + if (Float.isNaN(brightnessState) && mFlags.areAutoBrightnessModesEnabled() + && mFlags.isDisplayOffloadEnabled() + && mPowerRequest.policy == POLICY_DOZE + && mDisplayOffloadSession != null + && mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) { + rawBrightnessState = mAutomaticBrightnessController + .getAutomaticScreenBrightnessBasedOnLastObservedLux(mTempBrightnessEvent); + if (BrightnessUtils.isValidBrightnessValue(rawBrightnessState)) { + brightnessState = clampScreenBrightness(rawBrightnessState); + mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_INITIAL); + } + } + // Use default brightness when dozing unless overridden. if ((Float.isNaN(brightnessState)) && Display.isDozeState(state)) { @@ -1616,7 +1635,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // if doze or suspend state is requested, we want to finish brightnes animation fast // to allow state animation to start - if (mPowerRequest.policy == DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE + if (mPowerRequest.policy == POLICY_DOZE && (mPowerRequest.dozeScreenState == Display.STATE_UNKNOWN // dozing || mPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND || mPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND)) { @@ -1704,6 +1723,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mTempBrightnessEvent.setTime(System.currentTimeMillis()); mTempBrightnessEvent.setBrightness(brightnessState); mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId); + mTempBrightnessEvent.setDisplayState(state); mTempBrightnessEvent.setReason(mBrightnessReason); mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax()); mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode()); @@ -1996,7 +2016,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call postBrightnessChangeRunnable(); }, mUniqueDisplayId, mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId, - ddConfig.getThermalBrightnessThrottlingDataMapByThrottlingId()); + ddConfig); } private void blockScreenOn() { @@ -2877,7 +2897,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0, (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0, (flags & BrightnessEvent.FLAG_USER_SET) > 0, - (flags & BrightnessEvent.FLAG_IDLE_CURVE) > 0, + event.getAutoBrightnessMode() == AUTO_BRIGHTNESS_MODE_IDLE, (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0); } } diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java index d4d1bae78a33..5423b74711a2 100644 --- a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java +++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java @@ -16,11 +16,16 @@ package com.android.server.display.brightness; +import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; +import static com.android.server.display.config.DisplayBrightnessMappingConfig.autoBrightnessModeToString; + import android.hardware.display.BrightnessInfo; import android.os.PowerManager; import android.os.SystemClock; +import android.view.Display; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.AutomaticBrightnessController; import java.text.SimpleDateFormat; import java.util.Date; @@ -33,7 +38,6 @@ public final class BrightnessEvent { public static final int FLAG_INVALID_LUX = 0x2; public static final int FLAG_DOZE_SCALE = 0x4; public static final int FLAG_USER_SET = 0x8; - public static final int FLAG_IDLE_CURVE = 0x10; public static final int FLAG_LOW_POWER_MODE = 0x20; private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); @@ -41,6 +45,7 @@ public final class BrightnessEvent { private BrightnessReason mReason = new BrightnessReason(); private int mDisplayId; private String mPhysicalDisplayId; + private int mDisplayState; private long mTime; private float mLux; private float mPreThresholdLux; @@ -58,6 +63,8 @@ public final class BrightnessEvent { private int mAdjustmentFlags; private boolean mAutomaticBrightnessEnabled; private String mDisplayBrightnessStrategyName; + @AutomaticBrightnessController.AutomaticBrightnessMode + private int mAutoBrightnessMode; public BrightnessEvent(BrightnessEvent that) { copyFrom(that); @@ -77,6 +84,7 @@ public final class BrightnessEvent { mReason.set(that.getReason()); mDisplayId = that.getDisplayId(); mPhysicalDisplayId = that.getPhysicalDisplayId(); + mDisplayState = that.mDisplayState; mTime = that.getTime(); // Lux values mLux = that.getLux(); @@ -98,6 +106,7 @@ public final class BrightnessEvent { // Auto-brightness setting mAutomaticBrightnessEnabled = that.isAutomaticBrightnessEnabled(); mDisplayBrightnessStrategyName = that.getDisplayBrightnessStrategyName(); + mAutoBrightnessMode = that.mAutoBrightnessMode; } /** @@ -107,6 +116,7 @@ public final class BrightnessEvent { mReason = new BrightnessReason(); mTime = SystemClock.uptimeMillis(); mPhysicalDisplayId = ""; + mDisplayState = Display.STATE_UNKNOWN; // Lux values mLux = 0; mPreThresholdLux = 0; @@ -127,6 +137,7 @@ public final class BrightnessEvent { // Auto-brightness setting mAutomaticBrightnessEnabled = true; mDisplayBrightnessStrategyName = ""; + mAutoBrightnessMode = AUTO_BRIGHTNESS_MODE_DEFAULT; } /** @@ -143,6 +154,7 @@ public final class BrightnessEvent { return mReason.equals(that.mReason) && mDisplayId == that.mDisplayId && mPhysicalDisplayId.equals(that.mPhysicalDisplayId) + && mDisplayState == that.mDisplayState && Float.floatToRawIntBits(mLux) == Float.floatToRawIntBits(that.mLux) && Float.floatToRawIntBits(mPreThresholdLux) == Float.floatToRawIntBits(that.mPreThresholdLux) @@ -163,7 +175,8 @@ public final class BrightnessEvent { && mFlags == that.mFlags && mAdjustmentFlags == that.mAdjustmentFlags && mAutomaticBrightnessEnabled == that.mAutomaticBrightnessEnabled - && mDisplayBrightnessStrategyName.equals(that.mDisplayBrightnessStrategyName); + && mDisplayBrightnessStrategyName.equals(that.mDisplayBrightnessStrategyName) + && mAutoBrightnessMode == that.mAutoBrightnessMode; } /** @@ -177,6 +190,7 @@ public final class BrightnessEvent { + "BrightnessEvent: " + "disp=" + mDisplayId + ", physDisp=" + mPhysicalDisplayId + + ", displayState=" + Display.stateToString(mDisplayState) + ", brt=" + mBrightness + ((mFlags & FLAG_USER_SET) != 0 ? "(user_set)" : "") + ", initBrt=" + mInitialBrightness + ", rcmdBrt=" + mRecommendedBrightness @@ -192,7 +206,8 @@ public final class BrightnessEvent { + ", flags=" + flagsToString() + ", reason=" + mReason.toString(mAdjustmentFlags) + ", autoBrightness=" + mAutomaticBrightnessEnabled - + ", strategy=" + mDisplayBrightnessStrategyName; + + ", strategy=" + mDisplayBrightnessStrategyName + + ", autoBrightnessMode=" + autoBrightnessModeToString(mAutoBrightnessMode); } @Override @@ -232,6 +247,10 @@ public final class BrightnessEvent { this.mPhysicalDisplayId = mPhysicalDisplayId; } + public void setDisplayState(int state) { + mDisplayState = state; + } + public float getLux() { return mLux; } @@ -374,6 +393,16 @@ public final class BrightnessEvent { this.mAutomaticBrightnessEnabled = mAutomaticBrightnessEnabled; } + @AutomaticBrightnessController.AutomaticBrightnessMode + public int getAutoBrightnessMode() { + return mAutoBrightnessMode; + } + + public void setAutoBrightnessMode( + @AutomaticBrightnessController.AutomaticBrightnessMode int mode) { + mAutoBrightnessMode = mode; + } + /** * A utility to stringify flags from a BrightnessEvent * @return Stringified flags from BrightnessEvent @@ -384,7 +413,6 @@ public final class BrightnessEvent { + ((mFlags & FLAG_RBC) != 0 ? "rbc " : "") + ((mFlags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "") + ((mFlags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "") - + ((mFlags & FLAG_IDLE_CURVE) != 0 ? "idle_curve " : "") + ((mFlags & FLAG_LOW_POWER_MODE) != 0 ? "low_power_mode " : ""); } } diff --git a/services/core/java/com/android/server/display/brightness/BrightnessReason.java b/services/core/java/com/android/server/display/brightness/BrightnessReason.java index bc443a8167ab..fc95d15ae6f4 100644 --- a/services/core/java/com/android/server/display/brightness/BrightnessReason.java +++ b/services/core/java/com/android/server/display/brightness/BrightnessReason.java @@ -40,7 +40,8 @@ public final class BrightnessReason { public static final int REASON_SCREEN_OFF_BRIGHTNESS_SENSOR = 9; public static final int REASON_FOLLOWER = 10; public static final int REASON_OFFLOAD = 11; - public static final int REASON_MAX = REASON_OFFLOAD; + public static final int REASON_DOZE_INITIAL = 12; + public static final int REASON_MAX = REASON_DOZE_INITIAL; public static final int MODIFIER_DIMMED = 0x1; public static final int MODIFIER_LOW_POWER = 0x2; @@ -207,6 +208,8 @@ public final class BrightnessReason { return "follower"; case REASON_OFFLOAD: return "offload"; + case REASON_DOZE_INITIAL: + return "doze_initial"; default: return Integer.toString(reason); } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index bc5fcb449c95..18e8fab54e3e 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -38,6 +38,7 @@ import com.android.server.display.DisplayDeviceConfig.PowerThrottlingConfigData; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingData; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; import com.android.server.display.brightness.BrightnessReason; +import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.feature.DisplayManagerFlags; @@ -336,5 +337,10 @@ public class BrightnessClamperController { public float getBrightnessWearBedtimeModeCap() { return mDisplayDeviceConfig.getBrightnessCapForWearBedtimeMode(); } + + @NonNull + public SensorData getTempSensor() { + return mDisplayDeviceConfig.getTempSensor(); + } } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java index 944a8a65693b..449825831182 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java @@ -35,8 +35,10 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; +import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.utils.DeviceConfigParsingUtils; +import com.android.server.display.utils.SensorUtils; import java.io.PrintWriter; import java.util.List; @@ -49,9 +51,8 @@ class BrightnessThermalClamper extends BrightnessClamper<BrightnessThermalClamper.ThermalData> { private static final String TAG = "BrightnessThermalClamper"; - - @Nullable - private final IThermalService mThermalService; + @NonNull + private final ThermalStatusObserver mThermalStatusObserver; @NonNull private final DeviceConfigParameterProvider mConfigParameterProvider; // data from DeviceConfig, for all displays, for all dataSets @@ -66,7 +67,6 @@ class BrightnessThermalClamper extends // otherwise mDataFromDeviceConfig @Nullable private ThermalBrightnessThrottlingData mThermalThrottlingDataActive = null; - private boolean mStarted = false; @Nullable private String mUniqueDisplayId = null; @Nullable @@ -74,14 +74,6 @@ class BrightnessThermalClamper extends @Temperature.ThrottlingStatus private int mThrottlingStatus = Temperature.THROTTLING_NONE; - private final IThermalEventListener mThermalEventListener = new IThermalEventListener.Stub() { - @Override - public void notifyThrottling(Temperature temperature) { - @Temperature.ThrottlingStatus int status = temperature.getStatus(); - mHandler.post(() -> thermalStatusChanged(status)); - } - }; - private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> { try { int status = DeviceConfigParsingUtils.parseThermalStatus(key); @@ -105,12 +97,11 @@ class BrightnessThermalClamper extends BrightnessThermalClamper(Injector injector, Handler handler, ClamperChangeListener listener, ThermalData thermalData) { super(handler, listener); - mThermalService = injector.getThermalService(); mConfigParameterProvider = injector.getDeviceConfigParameterProvider(); + mThermalStatusObserver = new ThermalStatusObserver(injector, handler); mHandler.post(() -> { setDisplayData(thermalData); loadOverrideData(); - start(); }); } @@ -139,32 +130,19 @@ class BrightnessThermalClamper extends @Override void stop() { - if (!mStarted) { - return; - } - try { - mThermalService.unregisterThermalEventListener(mThermalEventListener); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to unregister thermal status listener", e); - } - mStarted = false; + mThermalStatusObserver.stopObserving(); } @Override void dump(PrintWriter writer) { writer.println("BrightnessThermalClamper:"); - writer.println(" mStarted: " + mStarted); - if (mThermalService != null) { - writer.println(" ThermalService available"); - } else { - writer.println(" ThermalService not available"); - } writer.println(" mThrottlingStatus: " + mThrottlingStatus); writer.println(" mUniqueDisplayId: " + mUniqueDisplayId); writer.println(" mDataId: " + mDataId); writer.println(" mDataOverride: " + mThermalThrottlingDataOverride); writer.println(" mDataFromDeviceConfig: " + mThermalThrottlingDataFromDeviceConfig); writer.println(" mDataActive: " + mThermalThrottlingDataActive); + mThermalStatusObserver.dump(writer); super.dump(writer); } @@ -193,6 +171,7 @@ class BrightnessThermalClamper extends Slog.wtf(TAG, "Thermal throttling data is missing for thermalThrottlingDataId=" + mDataId); } + mThermalStatusObserver.registerSensor(data.getTempSensor()); } private void recalculateBrightnessCap() { @@ -226,19 +205,91 @@ class BrightnessThermalClamper extends } } - private void start() { - if (mThermalService == null) { - Slog.e(TAG, "Could not observe thermal status. Service not available"); - return; + + private final class ThermalStatusObserver extends IThermalEventListener.Stub { + private final Injector mInjector; + private final Handler mHandler; + private IThermalService mThermalService; + private boolean mStarted; + private SensorData mObserverTempSensor; + + ThermalStatusObserver(Injector injector, Handler handler) { + mInjector = injector; + mHandler = handler; + mStarted = false; } - try { - // We get a callback immediately upon registering so there's no need to query - // for the current value. - mThermalService.registerThermalEventListenerWithType(mThermalEventListener, - Temperature.TYPE_SKIN); - mStarted = true; - } catch (RemoteException e) { - Slog.e(TAG, "Failed to register thermal status listener", e); + + void registerSensor(SensorData tempSensor) { + if (!mStarted || mObserverTempSensor == null) { + mObserverTempSensor = tempSensor; + registerThermalListener(); + return; + } + + String curType = mObserverTempSensor.type; + mObserverTempSensor = tempSensor; + if (curType.equals(tempSensor.type)) { + Slog.d(TAG, "Thermal status observer already started"); + return; + } + stopObserving(); + registerThermalListener(); + } + + void registerThermalListener() { + mThermalService = mInjector.getThermalService(); + if (mThermalService == null) { + Slog.e(TAG, "Could not observe thermal status. Service not available"); + return; + } + int temperatureType = SensorUtils.getSensorTemperatureType(mObserverTempSensor); + try { + // We get a callback immediately upon registering so there's no need to query + // for the current value. + mThermalService.registerThermalEventListenerWithType(this, temperatureType); + mStarted = true; + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register thermal status listener", e); + } + } + + @Override + public void notifyThrottling(Temperature temp) { + Slog.d(TAG, "New thermal throttling status = " + temp.getStatus()); + if (mObserverTempSensor.name != null + && !mObserverTempSensor.name.equals(temp.getName())) { + Slog.i(TAG, "Skipping thermal throttling notification as monitored sensor: " + + mObserverTempSensor.name + + " != notified sensor: " + + temp.getName()); + return; + } + @Temperature.ThrottlingStatus int status = temp.getStatus(); + mHandler.post(() -> thermalStatusChanged(status)); + } + + void stopObserving() { + if (!mStarted) { + return; + } + try { + mThermalService.unregisterThermalEventListener(this); + mStarted = false; + } catch (RemoteException e) { + Slog.e(TAG, "Failed to unregister thermal status listener", e); + } + mThermalService = null; + } + + void dump(PrintWriter writer) { + writer.println(" ThermalStatusObserver:"); + writer.println(" mStarted: " + mStarted); + writer.println(" mObserverTempSensor: " + mObserverTempSensor); + if (mThermalService != null) { + writer.println(" ThermalService available"); + } else { + writer.println(" ThermalService not available"); + } } } @@ -251,6 +302,9 @@ class BrightnessThermalClamper extends @Nullable ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData(); + + @NonNull + SensorData getTempSensor(); } @VisibleForTesting diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java index 3e6e09da9753..8eaecef6e562 100644 --- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java @@ -267,6 +267,23 @@ public class AutomaticBrightnessStrategy { } /** + * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when + * entering doze - we disable the light sensor, invalidate the lux, but we still need to set + * the initial brightness in doze mode. + * @param brightnessEvent Event object to populate with details about why the specific + * brightness was chosen. + */ + public float getAutomaticScreenBrightnessBasedOnLastObservedLux( + BrightnessEvent brightnessEvent) { + float brightness = (mAutomaticBrightnessController != null) + ? mAutomaticBrightnessController + .getAutomaticScreenBrightnessBasedOnLastObservedLux(brightnessEvent) + : PowerManager.BRIGHTNESS_INVALID_FLOAT; + adjustAutomaticBrightnessStateIfValid(brightness); + return brightness; + } + + /** * Gets the auto-brightness adjustment flag change reason */ public int getAutoBrightnessAdjustmentReasonsFlags() { diff --git a/services/core/java/com/android/server/display/config/SensorData.java b/services/core/java/com/android/server/display/config/SensorData.java index 3bb35bf7c49f..8e716f8380b6 100644 --- a/services/core/java/com/android/server/display/config/SensorData.java +++ b/services/core/java/com/android/server/display/config/SensorData.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.feature.DisplayManagerFlags; import java.util.ArrayList; import java.util.Collections; @@ -32,6 +33,9 @@ import java.util.List; */ public class SensorData { + public static final String TEMPERATURE_TYPE_DISPLAY = "DISPLAY"; + public static final String TEMPERATURE_TYPE_SKIN = "SKIN"; + @Nullable public final String type; @Nullable @@ -143,6 +147,32 @@ public class SensorData { } /** + * Loads temperature sensor data for no config case. (Type: SKIN, Name: null) + */ + public static SensorData loadTempSensorUnspecifiedConfig() { + return new SensorData(TEMPERATURE_TYPE_SKIN, null); + } + + /** + * Loads temperature sensor data from given display config. + * If empty or null config given default to (Type: SKIN, Name: null) + */ + public static SensorData loadTempSensorConfig(DisplayManagerFlags flags, + DisplayConfiguration config) { + SensorDetails sensorDetails = config.getTempSensor(); + if (!flags.isSensorBasedBrightnessThrottlingEnabled() || sensorDetails == null) { + return new SensorData(TEMPERATURE_TYPE_SKIN, null); + } + String name = sensorDetails.getName(); + String type = sensorDetails.getType(); + if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) { + type = TEMPERATURE_TYPE_SKIN; + name = null; + } + return new SensorData(type, name); + } + + /** * Loads sensor unspecified config, this means system should use default sensor. * See also {@link com.android.server.display.utils.SensorUtils} */ 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 1ae255933f66..516d4b1d4125 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -121,6 +121,11 @@ public class DisplayManagerFlags { Flags::refreshRateVotingTelemetry ); + private final FlagState mSensorBasedBrightnessThrottling = new FlagState( + Flags.FLAG_SENSOR_BASED_BRIGHTNESS_THROTTLING, + Flags::sensorBasedBrightnessThrottling + ); + /** * @return {@code true} if 'port' is allowed in display layout configuration file. */ @@ -247,6 +252,10 @@ public class DisplayManagerFlags { return mRefreshRateVotingTelemetry.isEnabled(); } + public boolean isSensorBasedBrightnessThrottlingEnabled() { + return mSensorBasedBrightnessThrottling.isEnabled(); + } + /** * dumps all flagstates * @param pw printWriter @@ -270,6 +279,7 @@ public class DisplayManagerFlags { pw.println(" " + mAutoBrightnessModesFlagState); pw.println(" " + mFastHdrTransitions); pw.println(" " + mRefreshRateVotingTelemetry); + pw.println(" " + mSensorBasedBrightnessThrottling); } 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 c2f52b5ad8a0..63ab3a95822f 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 @@ -184,3 +184,11 @@ flag { bug: "310029108" is_fixed_read_only: true } + +flag { + name: "sensor_based_brightness_throttling" + namespace: "display_manager" + description: "Feature flag for enabling brightness throttling using sensor from config." + bug: "294900859" + is_fixed_read_only: true +} diff --git a/services/core/java/com/android/server/display/utils/SensorUtils.java b/services/core/java/com/android/server/display/utils/SensorUtils.java index 8b9fe1083187..c63473a4b3d7 100644 --- a/services/core/java/com/android/server/display/utils/SensorUtils.java +++ b/services/core/java/com/android/server/display/utils/SensorUtils.java @@ -16,9 +16,11 @@ package com.android.server.display.utils; +import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.os.Temperature; import android.text.TextUtils; import com.android.server.display.config.SensorData; @@ -70,4 +72,17 @@ public class SensorUtils { return null; } + /** + * Convert string temperature type to its corresponding integer value. + */ + public static int getSensorTemperatureType(@NonNull SensorData tempSensor) { + if (tempSensor.type.equalsIgnoreCase(SensorData.TEMPERATURE_TYPE_DISPLAY)) { + return Temperature.TYPE_DISPLAY; + } else if (tempSensor.type.equalsIgnoreCase(SensorData.TEMPERATURE_TYPE_SKIN)) { + return Temperature.TYPE_SKIN; + } + throw new IllegalArgumentException( + "tempSensor doesn't support type: " + tempSensor.type); + } + } diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 7b18fb6a7c35..a79e7715f064 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -38,7 +38,6 @@ import android.graphics.PointF; import android.hardware.SensorPrivacyManager; import android.hardware.SensorPrivacyManager.Sensors; import android.hardware.SensorPrivacyManagerInternal; -import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayViewport; import android.hardware.input.HostUsiVersion; @@ -322,6 +321,9 @@ public class InputManagerService extends IInputManager.Stub // Manages Keyboard modifier keys remapping private final KeyRemapper mKeyRemapper; + // Manages loading PointerIcons + private final PointerIconCache mPointerIconCache; + // Maximum number of milliseconds to wait for input event injection. private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; @@ -408,44 +410,6 @@ public class InputManagerService extends IInputManager.Stub private boolean mShowKeyPresses = false; private boolean mShowRotaryInput = false; - @GuardedBy("mLoadedPointerIconsByDisplayAndType") - final SparseArray<SparseArray<PointerIcon>> mLoadedPointerIconsByDisplayAndType = - new SparseArray<>(); - @GuardedBy("mLoadedPointerIconsByDisplayAndType") - boolean mUseLargePointerIcons = false; - @GuardedBy("mLoadedPointerIconsByDisplayAndType") - final SparseArray<Context> mDisplayContexts = new SparseArray<>(); - - final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { - @Override - public void onDisplayAdded(int displayId) { - - } - - @Override - public void onDisplayRemoved(int displayId) { - synchronized (mLoadedPointerIconsByDisplayAndType) { - mLoadedPointerIconsByDisplayAndType.remove(displayId); - mDisplayContexts.remove(displayId); - } - } - - @Override - public void onDisplayChanged(int displayId) { - synchronized (mLoadedPointerIconsByDisplayAndType) { - // The display density could have changed, so force all cached pointer icons to be - // reloaded for the display. - var iconsByType = mLoadedPointerIconsByDisplayAndType.get(displayId); - if (iconsByType == null) { - return; - } - iconsByType.clear(); - mDisplayContexts.remove(displayId); - } - mNative.reloadPointerIcons(); - } - }; - /** Point of injection for test dependencies. */ @VisibleForTesting static class Injector { @@ -504,6 +468,7 @@ public class InputManagerService extends IInputManager.Stub : new KeyboardBacklightControllerInterface() {}; mStickyModifierStateController = new StickyModifierStateController(); mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper()); + mPointerIconCache = new PointerIconCache(mContext, mNative); mUseDevInputEventForAudioJack = mContext.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); @@ -613,14 +578,11 @@ public class InputManagerService extends IInputManager.Stub mWiredAccessoryCallbacks.systemReady(); } - Objects.requireNonNull( - mContext.getSystemService(DisplayManager.class)).registerDisplayListener( - mDisplayListener, mHandler); - mKeyboardLayoutManager.systemRunning(); mBatteryController.systemRunning(); mKeyboardBacklightController.systemRunning(); mKeyRemapper.systemRunning(); + mPointerIconCache.systemRunning(); } private void reloadDeviceAliases() { @@ -2374,8 +2336,8 @@ public class InputManagerService extends IInputManager.Stub synchronized (mLidSwitchLock) { /* Test if blocked by lid switch lock. */ } synchronized (mInputMonitors) { /* Test if blocked by input monitor lock. */ } synchronized (mAdditionalDisplayInputPropertiesLock) { /* Test if blocked by props lock */ } - synchronized (mLoadedPointerIconsByDisplayAndType) { /* Test if blocked by pointer lock */} mBatteryController.monitor(); + mPointerIconCache.monitor(); mNative.monitor(); } @@ -2769,21 +2731,7 @@ public class InputManagerService extends IInputManager.Stub // Native callback. @SuppressWarnings("unused") private @NonNull PointerIcon getLoadedPointerIcon(int displayId, int type) { - synchronized (mLoadedPointerIconsByDisplayAndType) { - SparseArray<PointerIcon> iconsByType = mLoadedPointerIconsByDisplayAndType.get( - displayId); - if (iconsByType == null) { - iconsByType = new SparseArray<>(); - mLoadedPointerIconsByDisplayAndType.put(displayId, iconsByType); - } - PointerIcon icon = iconsByType.get(type); - if (icon == null) { - icon = PointerIcon.getLoadedSystemIcon(getContextForDisplay(displayId), type, - mUseLargePointerIcons); - iconsByType.put(type, icon); - } - return Objects.requireNonNull(icon); - } + return mPointerIconCache.getLoadedPointerIcon(displayId, type); } // Native callback. @@ -2796,33 +2744,6 @@ public class InputManagerService extends IInputManager.Stub return sc.mNativeObject; } - @GuardedBy("mLoadedPointerIconsByDisplayAndType") - @NonNull - private Context getContextForDisplay(int displayId) { - if (displayId == Display.INVALID_DISPLAY) { - // Fallback to using the default context. - return mContext; - } - if (displayId == mContext.getDisplay().getDisplayId()) { - return mContext; - } - - Context displayContext = mDisplayContexts.get(displayId); - if (displayContext == null) { - final DisplayManager displayManager = Objects.requireNonNull( - mContext.getSystemService(DisplayManager.class)); - final Display display = displayManager.getDisplay(displayId); - if (display == null) { - // Fallback to using the default context. - return mContext; - } - - displayContext = mContext.createDisplayContext(display); - mDisplayContexts.put(displayId, displayContext); - } - return displayContext; - } - // Native callback. @SuppressWarnings("unused") private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag, @@ -3628,15 +3549,7 @@ public class InputManagerService extends IInputManager.Stub } void setUseLargePointerIcons(boolean useLargeIcons) { - synchronized (mLoadedPointerIconsByDisplayAndType) { - if (mUseLargePointerIcons == useLargeIcons) { - return; - } - mUseLargePointerIcons = useLargeIcons; - // Clear all cached icons on all displays. - mLoadedPointerIconsByDisplayAndType.clear(); - } - mNative.reloadPointerIcons(); + mPointerIconCache.setUseLargePointerIcons(useLargeIcons); } interface KeyboardBacklightControllerInterface { diff --git a/services/core/java/com/android/server/input/PointerIconCache.java b/services/core/java/com/android/server/input/PointerIconCache.java new file mode 100644 index 000000000000..233b865c69a6 --- /dev/null +++ b/services/core/java/com/android/server/input/PointerIconCache.java @@ -0,0 +1,207 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.input; + +import android.annotation.NonNull; +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.util.Slog; +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.PointerIcon; + +import com.android.internal.annotations.GuardedBy; +import com.android.server.UiThread; + +import java.util.Objects; + +/** + * A thread-safe component of {@link InputManagerService} responsible for caching loaded + * {@link PointerIcon}s and triggering reloading of the icons. + */ +final class PointerIconCache { + private static final String TAG = PointerIconCache.class.getSimpleName(); + + private final Context mContext; + + // Do not hold the lock when calling into native code. + private final NativeInputManagerService mNative; + + // We use the UI thread for loading pointer icons. + private final Handler mUiThreadHandler = UiThread.getHandler(); + + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private final SparseArray<SparseArray<PointerIcon>> mLoadedPointerIconsByDisplayAndType = + new SparseArray<>(); + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private boolean mUseLargePointerIcons = false; + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private final SparseArray<Context> mDisplayContexts = new SparseArray<>(); + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private final SparseIntArray mDisplayDensities = new SparseIntArray(); + + private final DisplayManager.DisplayListener mDisplayListener = + new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + updateDisplayDensityLocked(displayId); + } + } + + @Override + public void onDisplayRemoved(int displayId) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + mLoadedPointerIconsByDisplayAndType.remove(displayId); + mDisplayContexts.remove(displayId); + mDisplayDensities.delete(displayId); + } + } + + @Override + public void onDisplayChanged(int displayId) { + handleDisplayChanged(displayId); + } + }; + + /* package */ PointerIconCache(Context context, NativeInputManagerService nativeService) { + mContext = context; + mNative = nativeService; + } + + public void systemRunning() { + final DisplayManager displayManager = Objects.requireNonNull( + mContext.getSystemService(DisplayManager.class)); + displayManager.registerDisplayListener(mDisplayListener, mUiThreadHandler); + final Display[] displays = displayManager.getDisplays(); + for (int i = 0; i < displays.length; i++) { + mDisplayListener.onDisplayAdded(displays[i].getDisplayId()); + } + } + + public void monitor() { + synchronized (mLoadedPointerIconsByDisplayAndType) { /* Test if blocked by lock */} + } + + /** Set whether the large pointer icons should be used for accessibility. */ + public void setUseLargePointerIcons(boolean useLargeIcons) { + mUiThreadHandler.post(() -> handleSetUseLargePointerIcons(useLargeIcons)); + } + + /** + * Get a loaded system pointer icon. This will fetch the icon from the cache, or load it if + * it isn't already cached. + */ + public @NonNull PointerIcon getLoadedPointerIcon(int displayId, int type) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + SparseArray<PointerIcon> iconsByType = mLoadedPointerIconsByDisplayAndType.get( + displayId); + if (iconsByType == null) { + iconsByType = new SparseArray<>(); + mLoadedPointerIconsByDisplayAndType.put(displayId, iconsByType); + } + PointerIcon icon = iconsByType.get(type); + if (icon == null) { + icon = PointerIcon.getLoadedSystemIcon(getContextForDisplayLocked(displayId), type, + mUseLargePointerIcons); + iconsByType.put(type, icon); + } + return Objects.requireNonNull(icon); + } + } + + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private @NonNull Context getContextForDisplayLocked(int displayId) { + if (displayId == Display.INVALID_DISPLAY) { + // Fallback to using the default context. + return mContext; + } + if (displayId == mContext.getDisplay().getDisplayId()) { + return mContext; + } + + Context displayContext = mDisplayContexts.get(displayId); + if (displayContext == null) { + final DisplayManager displayManager = Objects.requireNonNull( + mContext.getSystemService(DisplayManager.class)); + final Display display = displayManager.getDisplay(displayId); + if (display == null) { + // Fallback to using the default context. + return mContext; + } + + displayContext = mContext.createDisplayContext(display); + mDisplayContexts.put(displayId, displayContext); + } + return displayContext; + } + + @android.annotation.UiThread + private void handleDisplayChanged(int displayId) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + if (!updateDisplayDensityLocked(displayId)) { + return; + } + // The display density changed, so force all cached pointer icons to be + // reloaded for the display. + Slog.i(TAG, "Reloading pointer icons due to density change on display: " + displayId); + var iconsByType = mLoadedPointerIconsByDisplayAndType.get(displayId); + if (iconsByType == null) { + return; + } + iconsByType.clear(); + mDisplayContexts.remove(displayId); + } + mNative.reloadPointerIcons(); + } + + @android.annotation.UiThread + private void handleSetUseLargePointerIcons(boolean useLargeIcons) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + if (mUseLargePointerIcons == useLargeIcons) { + return; + } + mUseLargePointerIcons = useLargeIcons; + // Clear all cached icons on all displays. + mLoadedPointerIconsByDisplayAndType.clear(); + } + mNative.reloadPointerIcons(); + } + + // Updates the cached display density for the given displayId, and returns true if + // the cached density changed. + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + private boolean updateDisplayDensityLocked(int displayId) { + final DisplayManager displayManager = Objects.requireNonNull( + mContext.getSystemService(DisplayManager.class)); + final Display display = displayManager.getDisplay(displayId); + if (display == null) { + return false; + } + DisplayInfo info = new DisplayInfo(); + display.getDisplayInfo(info); + final int oldDensity = mDisplayDensities.get(displayId, 0 /* default */); + if (oldDensity == info.logicalDensityDpi) { + return false; + } + mDisplayDensities.put(displayId, info.logicalDensityDpi); + return true; + } +} diff --git a/services/core/java/com/android/server/input/debug/FocusEventDebugView.java b/services/core/java/com/android/server/input/debug/FocusEventDebugView.java index 3ffd2e1dec71..b30f5ecb2dd5 100644 --- a/services/core/java/com/android/server/input/debug/FocusEventDebugView.java +++ b/services/core/java/com/android/server/input/debug/FocusEventDebugView.java @@ -313,7 +313,7 @@ public class FocusEventDebugView extends RelativeLayout { case KeyEvent.KEYCODE_FORWARD_DEL: return "\u2326"; case KeyEvent.KEYCODE_ESCAPE: - return "ESC"; + return "esc"; case KeyEvent.KEYCODE_DPAD_UP: return "\u2191"; case KeyEvent.KEYCODE_DPAD_DOWN: @@ -330,6 +330,14 @@ public class FocusEventDebugView extends RelativeLayout { return "\u2198"; case KeyEvent.KEYCODE_DPAD_DOWN_LEFT: return "\u2199"; + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + return "\u23ef"; + case KeyEvent.KEYCODE_HOME: + return "\u25ef"; + case KeyEvent.KEYCODE_BACK: + return "\u25c1"; + case KeyEvent.KEYCODE_RECENT_APPS: + return "\u25a1"; default: break; } diff --git a/services/core/java/com/android/server/inputmethod/ClientController.java b/services/core/java/com/android/server/inputmethod/ClientController.java index 86f4db959409..0381a317de5f 100644 --- a/services/core/java/com/android/server/inputmethod/ClientController.java +++ b/services/core/java/com/android/server/inputmethod/ClientController.java @@ -33,36 +33,10 @@ import java.util.List; import java.util.function.Consumer; /** - * Store and manage {@link InputMethodManagerService} clients. This class was designed to be a - * singleton in {@link InputMethodManagerService} since it stores information about all clients, - * still the current client will be defined per display. - * - * <p> - * As part of the re-architecture plan (described in go/imms-rearchitecture-plan), the following - * fields and methods will be moved out from IMMS and placed here: - * <ul> - * <li>mClients (ArrayMap of ClientState indexed by IBinder)</li> - * </ul> - * <p> - * Nested Classes (to move from IMMS): - * <ul> - * <li>ClientDeathRecipient</li> - * <li>ClientState<</li> - * </ul> - * <p> - * Methods to rewrite and/or extract from IMMS and move here: - * <ul> - * <li>addClient</li> - * <li>removeClient</li> - * <li>verifyClientAndPackageMatch</li> - * <li>setImeTraceEnabledForAllClients (make it reactive)</li> - * </ul> + * Store and manage {@link InputMethodManagerService} clients. */ -// TODO(b/314150112): Update the Javadoc above, by removing the re-architecture steps, once this -// class is finalized final class ClientController { - // TODO(b/314150112): Make this field private when breaking the cycle with IMMS. @GuardedBy("ImfLock.class") private final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>(); diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java index 84a59b4d28e4..7251ac42c582 100644 --- a/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java +++ b/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java @@ -43,6 +43,9 @@ import com.android.internal.inputmethod.InputBindResult; * the given {@link Handler} thread if {@link IInputMethodClient} is not a proxy object. Be careful * about its call ordering characteristics.</p> */ +// TODO(b/322895594) Mark this class to be host side test compatible once enabling fw/services in +// Ravenwood (mark this class with @RavenwoodKeepWholeClass and #create with @RavenwoodReplace, +// so Ravenwood can properly swap create method during test execution). final class IInputMethodClientInvoker { private static final String TAG = InputMethodManagerService.TAG; private static final boolean DEBUG = InputMethodManagerService.DEBUG; @@ -64,6 +67,16 @@ final class IInputMethodClientInvoker { return new IInputMethodClientInvoker(inputMethodClient, isProxy, isProxy ? null : handler); } + @AnyThread + @Nullable + static IInputMethodClientInvoker create$ravenwood( + @Nullable IInputMethodClient inputMethodClient, @NonNull Handler handler) { + if (inputMethodClient == null) { + return null; + } + return new IInputMethodClientInvoker(inputMethodClient, true, null); + } + private IInputMethodClientInvoker(@NonNull IInputMethodClient target, boolean isProxy, @Nullable Handler handler) { mTarget = target; diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 76956c88695d..307b70a89634 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -2193,7 +2193,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } } - // TODO(b/314150112): Move this method to InputMethodBindingController + // TODO(b/325515685): Move this method to InputMethodBindingController /** * Hide the IME if the removed user is the current user. */ diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index 75be0684c8f4..a608049cd677 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -463,11 +463,13 @@ public class LocationManagerService extends ILocationManager.Stub implements com.android.internal.R.bool.config_useGnssHardwareProvider); AbstractLocationProvider gnssProvider = null; if (!useGnssHardwareProvider) { + // TODO: Create a separate config_enableGnssLocationOverlay config resource + // if we want to selectively enable a GNSS overlay but disable a fused overlay. gnssProvider = ProxyLocationProvider.create( mContext, GPS_PROVIDER, ACTION_GNSS_PROVIDER, - com.android.internal.R.bool.config_useGnssHardwareProvider, + com.android.internal.R.bool.config_enableFusedLocationOverlay, com.android.internal.R.string.config_gnssLocationProviderPackageName); } if (gnssProvider == null) { diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index ecb4fcca5eef..40e538b02728 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -1618,6 +1618,17 @@ public class LocationProviderManager extends */ @SuppressLint("AndroidFrameworkRequiresPermission") public boolean isVisibleToCaller() { + // Anything sharing the system's UID can view all providers + if (Binder.getCallingUid() == Process.SYSTEM_UID) { + return true; + } + + // If an app mocked this provider, anybody can access it (the goal is + // to behave as if this provider didn't naturally exist). + if (mProvider.isMock()) { + return true; + } + for (String permission : mRequiredPermissions) { if (mContext.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) { return false; diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java index db70ce281eb5..a110e5637f82 100644 --- a/services/core/java/com/android/server/media/MediaSession2Record.java +++ b/services/core/java/com/android/server/media/MediaSession2Record.java @@ -40,6 +40,7 @@ public class MediaSession2Record implements MediaSessionRecordImpl { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Object mLock = new Object(); + private final int mUniqueId; @GuardedBy("mLock") private final Session2Token mSessionToken; @GuardedBy("mLock") @@ -63,11 +64,13 @@ public class MediaSession2Record implements MediaSessionRecordImpl { MediaSessionService service, Looper handlerLooper, int pid, - int policies) { + int policies, + int uniqueId) { // The lock is required to prevent `Controller2Callback` from using partially initialized // `MediaSession2Record.this`. synchronized (mLock) { mSessionToken = sessionToken; + mUniqueId = uniqueId; mService = service; mHandlerExecutor = new HandlerExecutor(new Handler(handlerLooper)); mController = new MediaController2.Builder(service.getContext(), sessionToken) @@ -98,6 +101,13 @@ public class MediaSession2Record implements MediaSessionRecordImpl { } @Override + public int getUniqueId() { + synchronized (mLock) { + return mUniqueId; + } + } + + @Override public String getPackageName() { return mSessionToken.getPackageName(); } @@ -200,6 +210,7 @@ public class MediaSession2Record implements MediaSessionRecordImpl { @Override public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "uniqueId=" + mUniqueId); pw.println(prefix + "token=" + mSessionToken); pw.println(prefix + "controller=" + mController); @@ -209,8 +220,7 @@ public class MediaSession2Record implements MediaSessionRecordImpl { @Override public String toString() { - // TODO(jaewan): Also add getId(). - return getPackageName() + " (userId=" + getUserId() + ")"; + return getPackageName() + "/" + mUniqueId + " (userId=" + getUserId() + ")"; } private class Controller2Callback extends MediaController2.ControllerCallback { diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 53f780e4d19e..15527041d8eb 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -173,6 +173,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR private final int mUserId; private final String mPackageName; private final String mTag; + private final int mUniqueId; private final Bundle mSessionInfo; private final ControllerStub mController; private final MediaSession.Token mSessionToken; @@ -223,15 +224,25 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR private int mPolicies; - public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName, - ISessionCallback cb, String tag, Bundle sessionInfo, - MediaSessionService service, Looper handlerLooper, int policies) + public MediaSessionRecord( + int ownerPid, + int ownerUid, + int userId, + String ownerPackageName, + ISessionCallback cb, + String tag, + int uniqueId, + Bundle sessionInfo, + MediaSessionService service, + Looper handlerLooper, + int policies) throws RemoteException { mOwnerPid = ownerPid; mOwnerUid = ownerUid; mUserId = userId; mPackageName = ownerPackageName; mTag = tag; + mUniqueId = uniqueId; mSessionInfo = sessionInfo; mController = new ControllerStub(); mSessionToken = new MediaSession.Token(ownerUid, mController); @@ -292,6 +303,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR } /** + * Get the unique id of this session record. + * + * @return a unique id of this session record. + */ + @Override + public int getUniqueId() { + return mUniqueId; + } + + /** * Get the info for this session. * * @return Info that identifies this session. @@ -703,7 +724,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR @Override public String toString() { - return mPackageName + "/" + mTag + " (userId=" + mUserId + ")"; + return mPackageName + "/" + mTag + "/" + mUniqueId + " (userId=" + mUserId + ")"; } @Override diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java index 99c8ea93936e..e53a2dbe8101 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java +++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java @@ -32,6 +32,13 @@ import java.io.PrintWriter; public interface MediaSessionRecordImpl extends AutoCloseable { /** + * Get the unique id of this session record. + * + * @return a unique id of this session record. + */ + int getUniqueId(); + + /** * Get the info for this session. * * @return Info that identifies this session. diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 757b26c45ab1..9e98a5809650 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -106,6 +106,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; /** * System implementation of MediaSessionManager @@ -155,6 +156,8 @@ public class MediaSessionService extends SystemService implements Monitor { /* Maps uid with all user engaging session tokens associated to it */ private final SparseArray<Set<MediaSession.Token>> mUserEngagingSessions = new SparseArray<>(); + private final AtomicInteger mNextMediaSessionRecordId = new AtomicInteger(1); + // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile) // It's always not null after the MediaSessionService is started. private FullUserRecord mCurrentFullUserRecord; @@ -193,7 +196,8 @@ public class MediaSessionService extends SystemService implements Monitor { MediaSessionService.this, mRecordThread.getLooper(), pid, - /* policies= */ 0); + /* policies= */ 0, + /* uniqueId= */ mNextMediaSessionRecordId.getAndIncrement()); synchronized (mLock) { FullUserRecord user = getFullUserRecordLocked(record.getUserId()); if (user != null) { @@ -794,9 +798,19 @@ public class MediaSessionService extends SystemService implements Monitor { final MediaSessionRecord session; try { - session = new MediaSessionRecord(callerPid, callerUid, userId, - callerPackageName, cb, tag, sessionInfo, this, - mRecordThread.getLooper(), policies); + session = + new MediaSessionRecord( + callerPid, + callerUid, + userId, + callerPackageName, + cb, + tag, + /* uniqueId= */ mNextMediaSessionRecordId.getAndIncrement(), + sessionInfo, + this, + mRecordThread.getLooper(), + policies); } catch (RemoteException e) { throw new RuntimeException("Media Session owner died prematurely.", e); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index b5c51af47009..582058d21256 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -340,6 +340,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { static final String TAG = NetworkPolicyLogger.TAG; private static final boolean LOGD = NetworkPolicyLogger.LOGD; private static final boolean LOGV = NetworkPolicyLogger.LOGV; + // TODO: b/304347838 - Remove once the feature is in staging. + private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false; /** * No opportunistic quota could be calculated from user data plan or data settings. @@ -727,7 +729,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Map of uid -> UidStateCallbackInfo objects holding the data received from * {@link IUidObserver#onUidStateChanged(int, int, long, int)} callbacks. In order to avoid * creating a new object for every callback received, we hold onto the object created for each - * uid and reuse it. + * uid and reuse it until the uid stays alive. * * Note that the lock used for accessing this object should not be used for anything else and we * should not be acquiring new locks or doing any heavy work while this lock is held since this @@ -800,6 +802,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { Clock.systemUTC()); } + @VisibleForTesting + UidState getUidStateForTest(int uid) { + synchronized (mUidRulesFirstLock) { + return mUidState.get(uid); + } + } + static class Dependencies { final Context mContext; final NetworkStatsManager mNetworkStatsManager; @@ -1061,7 +1070,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // The flag is boot-stable. - mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove(); + mBackgroundNetworkRestricted = ALWAYS_RESTRICT_BACKGROUND_NETWORK + && Flags.networkBlockedForTopSleepingAndAbove(); if (mBackgroundNetworkRestricted) { // Firewall rules and UidBlockedState will get updated in // updateRulesForGlobalChangeAL below. @@ -1254,6 +1264,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @Override public void onUidGone(int uid, boolean disabled) { + synchronized (mUidStateCallbackInfos) { + mUidStateCallbackInfos.remove(uid); + } + // TODO: b/327058756 - Remove any pending UID_MSG_STATE_CHANGED on the handler. mUidEventHandler.obtainMessage(UID_MSG_GONE, uid, 0).sendToTarget(); } }; @@ -5915,7 +5929,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { void handleUidGone(int uid) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidGone"); try { - boolean updated; + final boolean updated; synchronized (mUidRulesFirstLock) { updated = removeUidStateUL(uid); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 7455fe0043f8..3a7ac0bd659d 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1355,7 +1355,8 @@ public class NotificationManagerService extends SystemService { nv.recycle(); reportUserInteraction(r); mAssistants.notifyAssistantActionClicked(r, action, generatedByAssistant); - // Notifications that have been interacted with don't need to be lifetime extended. + // Notifications that have been interacted with should no longer be lifetime + // extended. if (lifetimeExtensionRefactor()) { r.getSbn().getNotification().flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; } @@ -1524,9 +1525,32 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationDirectReplied(String key) { exitIdle(); + String packageName = null; + final int packageImportance; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { + packageName = r.getSbn().getPackageName(); + } + } + if (lifetimeExtensionRefactor() && packageName != null) { + packageImportance = getPackageImportanceWithIdentity(packageName); + } else { + packageImportance = IMPORTANCE_NONE; + } + synchronized (mNotificationLock) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r != null) { + // If the notification is already marked as lifetime extended before we record + // the new direct reply, there must have been a previous lifetime extension + // event, and the app has already cancelled the notification, or does not + // respond to direct replies with updates. So we need to update System UI + // immediately. + if (lifetimeExtensionRefactor()) { + maybeNotifySystemUiListenerLifetimeExtendedLocked(r, + r.getSbn().getPackageName(), packageImportance); + } + r.recordDirectReplied(); mMetricsLogger.write(r.getLogMaker() .setCategory(MetricsEvent.NOTIFICATION_DIRECT_REPLY_ACTION) @@ -1557,10 +1581,31 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationSmartReplySent(String key, int replyIndex, CharSequence reply, int notificationLocation, boolean modifiedBeforeSending) { - + String packageName = null; + final int packageImportance; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { + packageName = r.getSbn().getPackageName(); + } + } + if (lifetimeExtensionRefactor() && packageName != null) { + packageImportance = getPackageImportanceWithIdentity(packageName); + } else { + packageImportance = IMPORTANCE_NONE; + } + synchronized (mNotificationLock) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r != null) { + // If the notification is already marked as lifetime extended before we record + // the new direct reply, there must have been a previous lifetime extension + // event, and the app has already cancelled the notification, or does not + // respond to direct replies with updates. So we need to update System UI + // immediately. + if (lifetimeExtensionRefactor()) { + maybeNotifySystemUiListenerLifetimeExtendedLocked(r, + r.getSbn().getPackageName(), packageImportance); + } r.recordSmartReplied(); LogMaker logMaker = r.getLogMaker() .setCategory(MetricsEvent.SMART_REPLY_ACTION) @@ -7735,7 +7780,7 @@ public class NotificationManagerService extends SystemService { notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED; - // Apps should not create notifications that are lifetime extended. + // Apps cannot post notifications that are lifetime extended. if (lifetimeExtensionRefactor()) { notification.flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; } @@ -8161,7 +8206,7 @@ public class NotificationManagerService extends SystemService { try { return mTelecomManager.isInManagedCall() || mTelecomManager.isInSelfManagedCall(pkg, - UserHandle.getUserHandleForUid(uid), /* hasCrossUserAccess */ true); + /* hasCrossUserAccess */ true); } catch (IllegalStateException ise) { // Telecom is not ready (this is likely early boot), so there are no calls. return false; @@ -12005,8 +12050,10 @@ public class NotificationManagerService extends SystemService { @Override public void onServiceAdded(ManagedServiceInfo info) { if (lifetimeExtensionRefactor()) { - // Only System or System UI can call registerSystemService, so if the caller is not - // system, we know it's system UI. + // Generally, only System or System UI should have the permissions to call + // registerSystemService. + // isCallerSystemorPhone tells us whether the caller is System. Then, if it's not + // the system, we know it's system UI. info.isSystemUi = !isCallerSystemOrPhone(); } final INotificationListener listener = (INotificationListener) info.service; diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 912b06631994..6857869e3776 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -1285,8 +1285,8 @@ public class ZenModeHelper { */ private static void updateZenDeviceEffects(ZenRule zenRule, @Nullable ZenDeviceEffects newEffects, boolean isFromApp, boolean updateBitmask) { + // Same as with ZenPolicy, supplying null effects means keeping the previous ones. if (newEffects == null) { - zenRule.zenDeviceEffects = null; return; } @@ -1896,12 +1896,14 @@ public class ZenModeHelper { if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { policy.apply(new ZenPolicy.Builder() .disallowAllSounds() + .allowPriorityChannels(false) .build()); } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) { policy.apply(new ZenPolicy.Builder() .disallowAllSounds() .allowAlarms(true) .allowMedia(true) + .allowPriorityChannels(false) .build()); } else if (rule.zenPolicy != null) { policy.apply(rule.zenPolicy); diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig index 53244f9e5ecf..43361ed97bc6 100644 --- a/services/core/java/com/android/server/notification/flags.aconfig +++ b/services/core/java/com/android/server/notification/flags.aconfig @@ -68,4 +68,14 @@ flag { namespace: "systemui" description: "This flag enables memory restriction of notifications holding custom views with Uri Bitmaps" bug: "270553691" +} + +flag { + name: "notification_hide_unused_channels" + namespace: "systemui" + description: "By default, hide non-blocked notification channels that haven't sent a notification in the last 2 weeks" + bug: "322536537" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java index 5ad550722c93..5ebcca875d86 100644 --- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java @@ -626,7 +626,7 @@ public class PersistentDataBlockService extends SystemService { // version. If so, we deactivate FRP and set the secret to the default value. if (isUpgradingFromPreVRelease()) { Slog.w(TAG, "Upgrading from Android 14 or lower, defaulting FRP secret"); - writeFrpMagicAndDefaultSecretLocked(); + writeFrpMagicAndDefaultSecret(); mFrpActive = false; return true; } @@ -726,7 +726,7 @@ public class PersistentDataBlockService extends SystemService { synchronized (mLock) { if (!hasFrpSecretMagic()) { Slog.i(TAG, "No FRP secret magic, system must have been upgraded."); - writeFrpMagicAndDefaultSecretLocked(); + writeFrpMagicAndDefaultSecret(); } } @@ -748,7 +748,7 @@ public class PersistentDataBlockService extends SystemService { } } - private void writeFrpMagicAndDefaultSecretLocked() { + private void writeFrpMagicAndDefaultSecret() { try (FileChannel channel = getBlockOutputChannelIgnoringFrp()) { synchronized (mLock) { Slog.i(TAG, "Writing default FRP secret"); diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java index 5b0fd00162d9..017cf55541fc 100644 --- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java +++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java @@ -655,4 +655,75 @@ public class DefaultCrossProfileIntentFiltersUtils { CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES ); } + + /** Dial intent with mime type can be handled by either private profile or its parent user. */ + private static final DefaultCrossProfileIntentFilter DIAL_MIME_PRIVATE_PROFILE = + new DefaultCrossProfileIntentFilter.Builder( + DefaultCrossProfileIntentFilter.Direction.TO_PARENT, + ONLY_IF_NO_MATCH_FOUND, + /* letsPersonalDataIntoProfile= */ false) + .addAction(Intent.ACTION_DIAL) + .addAction(Intent.ACTION_VIEW) + .addCategory(Intent.CATEGORY_DEFAULT) + .addCategory(Intent.CATEGORY_BROWSABLE) + .addDataType("vnd.android.cursor.item/phone") + .addDataType("vnd.android.cursor.item/phone_v2") + .addDataType("vnd.android.cursor.item/person") + .addDataType("vnd.android.cursor.dir/calls") + .addDataType("vnd.android.cursor.item/calls") + .build(); + + /** Dial intent with data scheme can be handled by either private profile or its parent user. */ + private static final DefaultCrossProfileIntentFilter DIAL_DATA_PRIVATE_PROFILE = + new DefaultCrossProfileIntentFilter.Builder( + DefaultCrossProfileIntentFilter.Direction.TO_PARENT, + ONLY_IF_NO_MATCH_FOUND, + /* letsPersonalDataIntoProfile= */ false) + .addAction(Intent.ACTION_DIAL) + .addAction(Intent.ACTION_VIEW) + .addCategory(Intent.CATEGORY_DEFAULT) + .addCategory(Intent.CATEGORY_BROWSABLE) + .addDataScheme("tel") + .addDataScheme("sip") + .addDataScheme("voicemail") + .build(); + + /** + * Dial intent with no data scheme or type can be handled by either private profile or its + * parent user. + */ + private static final DefaultCrossProfileIntentFilter DIAL_RAW_PRIVATE_PROFILE = + new DefaultCrossProfileIntentFilter.Builder( + DefaultCrossProfileIntentFilter.Direction.TO_PARENT, + ONLY_IF_NO_MATCH_FOUND, + /* letsPersonalDataIntoProfile= */ false) + .addAction(Intent.ACTION_DIAL) + .addCategory(Intent.CATEGORY_DEFAULT) + .addCategory(Intent.CATEGORY_BROWSABLE) + .build(); + + /** SMS and MMS can be handled by the private profile or by the parent user. */ + private static final DefaultCrossProfileIntentFilter SMS_MMS_PRIVATE_PROFILE = + new DefaultCrossProfileIntentFilter.Builder( + DefaultCrossProfileIntentFilter.Direction.TO_PARENT, + ONLY_IF_NO_MATCH_FOUND, + /* letsPersonalDataIntoProfile= */ false) + .addAction(Intent.ACTION_VIEW) + .addAction(Intent.ACTION_SENDTO) + .addCategory(Intent.CATEGORY_DEFAULT) + .addCategory(Intent.CATEGORY_BROWSABLE) + .addDataScheme("sms") + .addDataScheme("smsto") + .addDataScheme("mms") + .addDataScheme("mmsto") + .build(); + + public static List<DefaultCrossProfileIntentFilter> getDefaultPrivateProfileFilters() { + return Arrays.asList( + DIAL_MIME_PRIVATE_PROFILE, + DIAL_DATA_PRIVATE_PROFILE, + DIAL_RAW_PRIVATE_PROFILE, + SMS_MMS_PRIVATE_PROFILE + ); + } } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index a1dac0456ff9..8cc242c10c16 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -701,7 +701,7 @@ final class InstallPackageHelper { pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId); pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId); // Clear any existing archive state. - mPm.mInstallerService.mPackageArchiver.clearArchiveState(packageName, userId); + mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgSetting, userId); mPm.mSettings.writePackageRestrictionsLPr(userId); mPm.mSettings.writeKernelMappingLPr(pkgSetting); installed = true; @@ -829,7 +829,8 @@ final class InstallPackageHelper { if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); - if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED && doRestore) { + final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED; + if (succeeded && doRestore) { // Pass responsibility to the Backup Manager. It will perform a // restore if appropriate, then pass responsibility back to the // Package Manager to run the post-install observer callbacks @@ -843,10 +844,27 @@ final class InstallPackageHelper { // need to be snapshotted or restored for the package. // // TODO(narayan): Get this working for cases where userId == UserHandle.USER_ALL. - if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED && !doRestore && update) { + if (succeeded && !doRestore && update) { doRestore = performRollbackManagerRestore(userId, token, request); } + if (succeeded && !request.hasPostInstallRunnable()) { + boolean hasNeverBeenRestored = + packageSetting != null && packageSetting.isPendingRestore(); + request.setPostInstallRunnable(() -> { + // Permissions should be restored on each user that has the app installed for the + // first time, unless it's an unarchive install for an archived app, in which case + // the permissions should be restored on each user that has the app updated. + int[] userIdsToRestorePermissions = hasNeverBeenRestored + ? request.getUpdateBroadcastUserIds() + : request.getFirstTimeBroadcastUserIds(); + for (int restorePermissionUserId : userIdsToRestorePermissions) { + mPm.restorePermissionsAndUpdateRolesForNewUserInstall(request.getName(), + restorePermissionUserId); + } + }); + } + if (doRestore) { if (packageSetting != null) { synchronized (mPm.mLock) { @@ -2327,7 +2345,7 @@ final class InstallPackageHelper { installerPackageName); } // Clear any existing archive state. - mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName, userId); + mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps, userId); } else if (allUsers != null) { // The caller explicitly specified INSTALL_ALL_USERS flag. // Thus, updating the settings to install the app for all users. @@ -2351,7 +2369,7 @@ final class InstallPackageHelper { installerPackageName); } // Clear any existing archive state. - mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName, + mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps, currentUserId); } else { ps.setInstalled(false, currentUserId); @@ -2851,7 +2869,6 @@ final class InstallPackageHelper { mPm.notifyInstantAppPackageInstalled(request.getPkg().getPackageName(), request.getNewUsers()); - request.populateBroadcastUsers(); final int[] firstUserIds = request.getFirstTimeBroadcastUserIds(); if (request.getPkg().getStaticSharedLibraryName() == null) { @@ -2863,12 +2880,6 @@ final class InstallPackageHelper { mPm.mRequiredInstallerPackage, /* packageSender= */ mPm, launchedForRestore, killApp, update, archived); - // Work that needs to happen on first install within each user - for (int userId : firstUserIds) { - mPm.restorePermissionsAndUpdateRolesForNewUserInstall(packageName, - userId); - } - if (request.isAllNewUsers() && !update) { mPm.notifyPackageAdded(packageName, request.getAppId()); } else { diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java index 4fb0c220708f..43075a232a23 100644 --- a/services/core/java/com/android/server/pm/InstallRequest.java +++ b/services/core/java/com/android/server/pm/InstallRequest.java @@ -692,6 +692,14 @@ final class InstallRequest { } } + public void setPostInstallRunnable(Runnable runnable) { + mPostInstallRunnable = runnable; + } + + public boolean hasPostInstallRunnable() { + return mPostInstallRunnable != null; + } + public void runPostInstallRunnable() { if (mPostInstallRunnable != null) { mPostInstallRunnable.run(); @@ -753,6 +761,7 @@ final class InstallRequest { public void setNewUsers(int[] newUsers) { mNewUsers = newUsers; + populateBroadcastUsers(); } public void setOriginPackage(String originPackage) { @@ -829,10 +838,11 @@ final class InstallRequest { } /** - * Determine the set of users who are adding this package for the first time vs. those who are - * seeing an update. + * Determine the set of users who are adding this package for the first time (aka "new" users) + * vs. those who are seeing an update (aka "update" users). The lists can be calculated as soon + * as the "new" users are set. */ - public void populateBroadcastUsers() { + private void populateBroadcastUsers() { assertScanResultExists(); mFirstTimeBroadcastUserIds = EMPTY_INT_ARRAY; mFirstTimeBroadcastInstantUserIds = EMPTY_INT_ARRAY; diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index d8d8dd2e57a9..3f9e989a5bba 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -2209,8 +2209,10 @@ public class LauncherAppsService extends SystemService { for (UserHandle user : users) { mPackageManagerInternal.forEachInstalledPackage(pkg -> { final String packageName = pkg.getPackageName(); - if (mPackageManagerInternal.getIncrementalStatesInfo(packageName, - Process.myUid(), user.getIdentifier()).isLoading()) { + final IncrementalStatesInfo info = + mPackageManagerInternal.getIncrementalStatesInfo(packageName, + Process.myUid(), user.getIdentifier()); + if (info != null && info.isLoading()) { mPackageManagerInternal.registerInstalledLoadingProgressCallback( packageName, new PackageLoadingProgressCallback(packageName, user), user.getIdentifier()); diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java index df4e5a319ee6..2b20bfd7a7c2 100644 --- a/services/core/java/com/android/server/pm/PackageArchiver.java +++ b/services/core/java/com/android/server/pm/PackageArchiver.java @@ -62,6 +62,7 @@ import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -85,6 +86,7 @@ import android.os.RemoteException; import android.os.SELinux; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.ExceptionUtils; import android.util.Pair; @@ -164,6 +166,9 @@ public class PackageArchiver { @Nullable private AppOpsManager mAppOpsManager; + @Nullable + private UserManager mUserManager; + /* IntentSender store that maps key: {userId, appPackageName} to respective existing attached unarchival intent sender. */ private final Map<Pair<Integer, String>, IntentSender> mLauncherIntentSenders; @@ -276,12 +281,8 @@ public class PackageArchiver { Slog.e(TAG, "callerPackageName cannot be null for unarchival!"); return START_CLASS_NOT_FOUND; } - if (!isCallingPackageValid(callerPackageName, callingUid, userId)) { - // Return early as the calling UID does not match caller package's UID. - return START_CLASS_NOT_FOUND; - } - String currentLauncherPackageName = getCurrentLauncherPackageName(userId); + String currentLauncherPackageName = getCurrentLauncherPackageName(getParentUserId(userId)); if ((currentLauncherPackageName == null || !callerPackageName.equals( currentLauncherPackageName)) && callingUid != Process.SHELL_UID) { // TODO(b/311619990): Remove dependency on SHELL_UID for testing @@ -316,6 +317,13 @@ public class PackageArchiver { return START_ABORTED; } + // Profiles share their UI and default apps, so we have to get the profile parent before + // fetching the default launcher. + private int getParentUserId(int userId) { + UserInfo profileParent = getUserManager().getProfileParent(userId); + return profileParent == null ? userId : profileParent.id; + } + /** * Returns true if the componentName targeted by the intent corresponds to that of an archived * app. @@ -348,19 +356,34 @@ public class PackageArchiver { } void clearArchiveState(String packageName, int userId) { + final PackageSetting ps; + synchronized (mPm.mLock) { + ps = mPm.mSettings.getPackageLPr(packageName); + } + clearArchiveState(ps, userId); + } + + void clearArchiveState(PackageSetting ps, int userId) { synchronized (mPm.mLock) { - PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); - if (ps != null) { - ps.setArchiveState(/* archiveState= */ null, userId); + if (ps == null || ps.getUserStateOrDefault(userId).getArchiveState() == null) { + // No archive states to clear + return; + } + if (DEBUG) { + Slog.e(TAG, "Clearing archive states for " + ps.getPackageName()); } + ps.setArchiveState(/* archiveState= */ null, userId); } - File iconsDir = getIconsDir(packageName, userId); + File iconsDir = getIconsDir(ps.getPackageName(), userId); if (!iconsDir.exists()) { + if (DEBUG) { + Slog.e(TAG, "Icons are already deleted at " + iconsDir.getAbsolutePath()); + } return; } // TODO(b/319238030) Move this into installd. if (!FileUtils.deleteContentsAndDir(iconsDir)) { - Slog.e(TAG, "Failed to clean up archive files for " + packageName); + Slog.e(TAG, "Failed to clean up archive files for " + ps.getPackageName()); } else { if (DEBUG) { Slog.e(TAG, "Deleted icons at " + iconsDir.getAbsolutePath()); @@ -1128,6 +1151,13 @@ public class PackageArchiver { return mAppOpsManager; } + private UserManager getUserManager() { + if (mUserManager == null) { + mUserManager = mContext.getSystemService(UserManager.class); + } + return mUserManager; + } + private void storeArchiveState(String packageName, ArchiveState archiveState, int userId) throws PackageManager.NameNotFoundException { synchronized (mPm.mLock) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index dadafd7f9438..3c256b1caa7d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -721,7 +721,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy; - @GuardedBy("mAvailableFeatures") private final ArrayMap<String, FeatureInfo> mAvailableFeatures; @Watched @@ -2983,13 +2982,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService public boolean hasSystemFeature(String name, int version) { // allow instant applications - synchronized (mAvailableFeatures) { - final FeatureInfo feat = mAvailableFeatures.get(name); - if (feat == null) { - return false; - } else { - return feat.version >= version; - } + final FeatureInfo feat = mAvailableFeatures.get(name); + if (feat == null) { + return false; + } else { + return feat.version >= version; } } @@ -5335,10 +5332,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() { // allow instant applications ArrayList<FeatureInfo> res; - synchronized (mAvailableFeatures) { - res = new ArrayList<>(mAvailableFeatures.size() + 1); - res.addAll(mAvailableFeatures.values()); - } + res = new ArrayList<>(mAvailableFeatures.size() + 1); + res.addAll(mAvailableFeatures.values()); final FeatureInfo fi = new FeatureInfo(); fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version", FeatureInfo.GL_ES_VERSION_UNDEFINED); @@ -6542,9 +6537,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mOverlayConfigSignaturePackage, mRecentsPackage); final ArrayMap<String, FeatureInfo> availableFeatures; - synchronized (mAvailableFeatures) { - availableFeatures = new ArrayMap<>(mAvailableFeatures); - } + availableFeatures = new ArrayMap<>(mAvailableFeatures); final ArraySet<String> protectedBroadcasts; synchronized (mProtectedBroadcasts) { protectedBroadcasts = new ArraySet<>(mProtectedBroadcasts); diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java index 5e8778d3e29c..9a7916a7b215 100644 --- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java +++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java @@ -53,7 +53,7 @@ import java.util.Map; * as install) led to the request. */ final class ReconcilePackageUtils { - private static final boolean ALLOW_NON_PRELOADS_SYSTEM_SIGNATURE = Build.IS_DEBUGGABLE; + private static final boolean ALLOW_NON_PRELOADS_SYSTEM_SIGNATURE = Build.IS_DEBUGGABLE || true; public static List<ReconciledPackage> reconcilePackages( List<InstallRequest> installRequests, diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 067a012ed373..114daaac3c18 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -306,6 +306,7 @@ public final class UserTypeFactory { .setDarkThemeBadgeColors( R.color.white) .setDefaultRestrictions(getDefaultProfileRestrictions()) + .setDefaultCrossProfileIntentFilters(getDefaultPrivateCrossProfileIntentFilter()) .setDefaultUserProperties(new UserProperties.Builder() .setStartWithParent(true) .setCredentialShareableWithParent(true) @@ -446,6 +447,11 @@ public final class UserTypeFactory { return DefaultCrossProfileIntentFiltersUtils.getDefaultCloneProfileFilters(); } + private static List<DefaultCrossProfileIntentFilter> getDefaultPrivateCrossProfileIntentFilter() + { + return DefaultCrossProfileIntentFiltersUtils.getDefaultPrivateProfileFilters(); + } + /** Gets a default bundle, keyed by Settings.Secure String names, for non-managed profiles. */ private static Bundle getDefaultNonManagedProfileSecureSettings() { final Bundle settings = new Bundle(); diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java index dd2b409c7100..1a9e012a7c53 100644 --- a/services/core/java/com/android/server/pm/VerifyingSession.java +++ b/services/core/java/com/android/server/pm/VerifyingSession.java @@ -47,6 +47,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.DataLoaderType; +import android.content.pm.Flags; import android.content.pm.IPackageInstallObserver2; import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; @@ -541,7 +542,12 @@ final class VerifyingSession { } final int verificationCodeAtTimeout; - if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) { + // Allows package verification to continue in the event the app being updated is verifying + // itself and fails to respond + if (Flags.emergencyInstallPermission() && requiredVerifierPackages.contains( + pkgLite.packageName)) { + verificationCodeAtTimeout = PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT; + } else if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) { verificationCodeAtTimeout = PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT; } else { verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT; diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java index 1c70af0a56ea..b18503d7d5cb 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java +++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java @@ -596,7 +596,7 @@ public class PackageInfoUtils { ai.requiredDisplayCategory = a.getRequiredDisplayCategory(); ai.requireContentUriPermissionFromCaller = a.getRequireContentUriPermissionFromCaller(); ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts()); - assignFieldsComponentInfoParsedMainComponent(ai, a, pkgSetting, userId); + assignFieldsComponentInfoParsedMainComponent(ai, a, pkgSetting, state, userId); return ai; } @@ -659,7 +659,7 @@ public class PackageInfoUtils { // Backwards compatibility, coerce to null if empty si.metaData = metaData.isEmpty() ? null : metaData; } - assignFieldsComponentInfoParsedMainComponent(si, s, pkgSetting, userId); + assignFieldsComponentInfoParsedMainComponent(si, s, pkgSetting, state, userId); return si; } @@ -710,7 +710,7 @@ public class PackageInfoUtils { pi.metaData = metaData.isEmpty() ? null : metaData; } pi.applicationInfo = applicationInfo; - assignFieldsComponentInfoParsedMainComponent(pi, p, pkgSetting, userId); + assignFieldsComponentInfoParsedMainComponent(pi, p, pkgSetting, state, userId); return pi; } @@ -903,8 +903,13 @@ public class PackageInfoUtils { private static void assignFieldsComponentInfoParsedMainComponent( @NonNull ComponentInfo info, @NonNull ParsedMainComponent component, - @NonNull PackageStateInternal pkgSetting, @UserIdInt int userId) { + @NonNull PackageStateInternal pkgSetting, @NonNull PackageUserStateInternal state, + @UserIdInt int userId) { assignFieldsComponentInfoParsedMainComponent(info, component); + // overwrite the enabled state with the current user state + info.enabled = PackageUserStateUtils.isEnabled(state, info.applicationInfo.enabled, + info.enabled, info.name, /* flags */ 0); + Pair<CharSequence, Integer> labelAndIcon = ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting, userId); diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java index b22e37bd579b..c8cb92b915da 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java @@ -167,6 +167,9 @@ public class BatterySaverStateMachine { /** Config flag to track if battery saver's sticky behaviour is disabled. */ private final boolean mBatterySaverStickyBehaviourDisabled; + /** Config flag to track if "Battery Saver turned off" notification is enabled. */ + private final boolean mBatterySaverTurnedOffNotificationEnabled; + /** * Whether or not to end sticky battery saver upon reaching a level specified by * {@link #mSettingBatterySaverStickyAutoDisableThreshold}. @@ -250,6 +253,8 @@ public class BatterySaverStateMachine { mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled); + mBatterySaverTurnedOffNotificationEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_batterySaverTurnedOffNotificationEnabled); mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger( com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold); } @@ -858,6 +863,9 @@ public class BatterySaverStateMachine { @VisibleForTesting void triggerStickyDisabledNotification() { + if (!mBatterySaverTurnedOffNotificationEnabled) { + return; + } // The current lock is the PowerManager lock, which sits very low in the service lock // hierarchy. We shouldn't call out to NotificationManager with the PowerManager lock. runOnBgThread(() -> { @@ -997,6 +1005,8 @@ public class BatterySaverStateMachine { ipw.println(mSettingBatterySaverTriggerThreshold); ipw.print("mBatterySaverStickyBehaviourDisabled="); ipw.println(mBatterySaverStickyBehaviourDisabled); + ipw.print("mBatterySaverTurnedOffNotificationEnabled="); + ipw.println(mBatterySaverTurnedOffNotificationEnabled); ipw.print("mDynamicPowerSavingsDefaultDisableThreshold="); ipw.println(mDynamicPowerSavingsDefaultDisableThreshold); 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 9b347d572459..8e3c6ac799b4 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -1591,32 +1591,76 @@ public class BatteryStatsImpl extends BatteryStats { @Override public WakeLockStats getWakeLockStats() { final long realtimeMs = mClock.elapsedRealtime(); - final long realtimeUs = realtimeMs * 1000; List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>(); + List<WakeLockStats.WakeLock> uidAggregatedWakeLockStats = new ArrayList<>(); for (int i = mUidStats.size() - 1; i >= 0; i--) { final Uid uid = mUidStats.valueAt(i); + + // Converts unaggregated wakelocks. final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = uid.mWakelockStats.getMap(); for (int j = wakelockStats.size() - 1; j >= 0; j--) { final String name = wakelockStats.keyAt(j); final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j); - final DualTimer timer = wakelock.mTimerPartial; - if (timer != null) { - final long totalTimeLockHeldMs = - timer.getTotalTimeLocked(realtimeUs, STATS_SINCE_CHARGED) / 1000; - if (totalTimeLockHeldMs != 0) { - uidWakeLockStats.add( - new WakeLockStats.WakeLock(uid.getUid(), name, - timer.getCountLocked(STATS_SINCE_CHARGED), - totalTimeLockHeldMs, - timer.isRunningLocked() - ? timer.getCurrentDurationMsLocked(realtimeMs) - : 0)); - } + final WakeLockStats.WakeLock wakeLockItem = + createWakeLock(uid, name, /* isAggregated= */ false, wakelock.mTimerPartial, + realtimeMs); + if (wakeLockItem != null) { + uidWakeLockStats.add(wakeLockItem); } } + + // Converts aggregated wakelocks. + final WakeLockStats.WakeLock aggregatedWakeLockItem = + createWakeLock( + uid, + WakeLockStats.WakeLock.NAME_AGGREGATED, + /* isAggregated= */ true, + uid.mAggregatedPartialWakelockTimer, + realtimeMs); + if (aggregatedWakeLockItem != null) { + uidAggregatedWakeLockStats.add(aggregatedWakeLockItem); + } } - return new WakeLockStats(uidWakeLockStats); + return new WakeLockStats(uidWakeLockStats, uidAggregatedWakeLockStats); + } + + // Returns a valid {@code WakeLockStats.WakeLock} or null. + private WakeLockStats.WakeLock createWakeLock( + Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs) { + if (timer == null) { + return null; + } + // Uses the primary timer for total wakelock data and used the sub timer for background + // wakelock data. + final WakeLockStats.WakeLockData totalWakeLockData = createWakeLockData(timer, realtimeMs); + final WakeLockStats.WakeLockData backgroundWakeLockData = + createWakeLockData(timer.getSubTimer(), realtimeMs); + + return WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData) + ? new WakeLockStats.WakeLock( + uid.getUid(), + name, + isAggregated, + totalWakeLockData, + backgroundWakeLockData) : null; + } + + @NonNull + private WakeLockStats.WakeLockData createWakeLockData( + DurationTimer timer, final long realtimeMs) { + if (timer == null) { + return WakeLockStats.WakeLockData.EMPTY; + } + final long totalTimeLockHeldMs = + timer.getTotalTimeLocked(realtimeMs * 1000, STATS_SINCE_CHARGED) / 1000; + if (totalTimeLockHeldMs == 0) { + return WakeLockStats.WakeLockData.EMPTY; + } + return new WakeLockStats.WakeLockData( + timer.getCountLocked(STATS_SINCE_CHARGED), + totalTimeLockHeldMs, + timer.isRunningLocked() ? timer.getCurrentDurationMsLocked(realtimeMs) : 0); } @Override @@ -1817,9 +1861,8 @@ public class BatteryStatsImpl extends BatteryStats { if (historyDirectory == null) { mCheckinFile = null; mStatsFile = null; - mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock, - traceDelegate, eventLogger); + mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER, + mStepDetailsCalculator, mClock, mMonotonicClock, traceDelegate, eventLogger); } else { mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin")); mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin")); @@ -10962,8 +11005,8 @@ public class BatteryStatsImpl extends BatteryStats { mStatsFile = null; mCheckinFile = null; mDailyFile = null; - mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock); + mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER, + mStepDetailsCalculator, mClock, mMonotonicClock); } else { mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin")); mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin")); @@ -15430,17 +15473,18 @@ public class BatteryStatsImpl extends BatteryStats { mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState; } - final boolean compatibleConfig; if (supportedStandardBuckets != null) { final EnergyConsumerStats.Config config = new EnergyConsumerStats.Config( supportedStandardBuckets, customBucketNames, SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS, getBatteryConsumerProcessStateNames()); - if (mEnergyConsumerStatsConfig == null) { - compatibleConfig = true; - } else { - compatibleConfig = mEnergyConsumerStatsConfig.isCompatible(config); + if (mEnergyConsumerStatsConfig != null + && !mEnergyConsumerStatsConfig.isCompatible(config)) { + // Supported power buckets changed since last boot. + // Existing data is no longer reliable. + resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(), + RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE); } mEnergyConsumerStatsConfig = config; @@ -15456,18 +15500,14 @@ public class BatteryStatsImpl extends BatteryStats { mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile); } } else { - compatibleConfig = (mEnergyConsumerStatsConfig == null); - // EnergyConsumer no longer supported, wipe out the existing data. + if (mEnergyConsumerStatsConfig != null) { + // EnergyConsumer no longer supported, wipe out the existing data. + resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(), + RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE); + } mEnergyConsumerStatsConfig = null; mGlobalEnergyConsumerStats = null; } - - if (!compatibleConfig) { - // Supported power buckets changed since last boot. - // Existing data is no longer reliable. - resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(), - RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE); - } } @GuardedBy("this") diff --git a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java index 3b260ca0c3b9..4df919dffbe5 100644 --- a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java +++ b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java @@ -57,7 +57,7 @@ public class PowerStatsSpan { * {@link #isCompatibleXmlFormat} to return true for all legacy versions * that are compatible with the new one. */ - private static final int VERSION = 1; + private static final int VERSION = 2; private static final String XML_TAG_METADATA = "metadata"; private static final String XML_ATTR_ID = "id"; diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java index 7091c47b8e83..ecfc040ae29c 100644 --- a/services/core/java/com/android/server/search/SearchManagerService.java +++ b/services/core/java/com/android/server/search/SearchManagerService.java @@ -17,6 +17,7 @@ package com.android.server.search; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.app.ISearchManager; import android.app.SearchManager; import android.app.SearchableInfo; @@ -24,6 +25,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.os.Binder; @@ -32,6 +34,7 @@ import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; @@ -47,6 +50,7 @@ import com.android.server.statusbar.StatusBarManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.List; /** @@ -71,11 +75,6 @@ public class SearchManagerService extends ISearchManager.Stub { } @Override - public void onUserUnlocking(@NonNull TargetUser user) { - mService.mHandler.post(() -> mService.onUnlockUser(user.getUserIdentifier())); - } - - @Override public void onUserStopped(@NonNull TargetUser user) { mService.onCleanupUser(user.getUserIdentifier()); } @@ -102,10 +101,6 @@ public class SearchManagerService extends ISearchManager.Stub { } private Searchables getSearchables(int userId) { - return getSearchables(userId, false); - } - - private Searchables getSearchables(int userId, boolean forceUpdate) { final long token = Binder.clearCallingIdentity(); try { final UserManager um = mContext.getSystemService(UserManager.class); @@ -122,21 +117,11 @@ public class SearchManagerService extends ISearchManager.Stub { Searchables searchables = mSearchables.get(userId); if (searchables == null) { searchables = new Searchables(mContext, userId); - searchables.updateSearchableList(); - mSearchables.append(userId, searchables); - } else if (forceUpdate) { - searchables.updateSearchableList(); + mSearchables.put(userId, searchables); } - return searchables; - } - } - private void onUnlockUser(int userId) { - try { - getSearchables(userId, true); - } catch (IllegalStateException ignored) { - // We're just trying to warm a cache, so we don't mind if the user - // was stopped or destroyed before we got here. + searchables.updateSearchableListIfNeeded(); + return searchables; } } @@ -150,28 +135,110 @@ public class SearchManagerService extends ISearchManager.Stub { * Refreshes the "searchables" list when packages are added/removed. */ class MyPackageMonitor extends PackageMonitor { + /** + * Packages that are appeared, disappeared, or modified for whatever reason. + */ + private final ArrayList<String> mChangedPackages = new ArrayList<>(); + + /** + * {@code true} if one or more packages that contain {@link SearchableInfo} appeared. + */ + private boolean mSearchablePackageAppeared = false; + + @Override + public void onBeginPackageChanges() { + clearPackageChangeState(); + } + + @Override + public void onPackageAppeared(String packageName, int reason) { + if (!mSearchablePackageAppeared) { + // Check if the new appeared package contains SearchableInfo. + mSearchablePackageAppeared = + hasSearchableForPackage(packageName, getChangingUserId()); + } + mChangedPackages.add(packageName); + } @Override - public void onSomePackagesChanged() { - updateSearchables(); + public void onPackageDisappeared(String packageName, int reason) { + mChangedPackages.add(packageName); } @Override - public void onPackageModified(String pkg) { - updateSearchables(); + public void onPackageModified(String packageName) { + mChangedPackages.add(packageName); } - private void updateSearchables() { + @Override + public void onFinishPackageChanges() { + onFinishPackageChangesInternal(); + clearPackageChangeState(); + } + + private void clearPackageChangeState() { + mChangedPackages.clear(); + mSearchablePackageAppeared = false; + } + + private boolean hasSearchableForPackage(String packageName, int userId) { + final List<ResolveInfo> searchList = querySearchableActivities(mContext, + new Intent(Intent.ACTION_SEARCH).setPackage(packageName), userId); + if (!searchList.isEmpty()) { + return true; + } + + final List<ResolveInfo> webSearchList = querySearchableActivities(mContext, + new Intent(Intent.ACTION_WEB_SEARCH).setPackage(packageName), userId); + if (!webSearchList.isEmpty()) { + return true; + } + + final List<ResolveInfo> globalSearchList = querySearchableActivities(mContext, + new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH).setPackage(packageName), + userId); + return !globalSearchList.isEmpty(); + } + + private boolean shouldRebuildSearchableList(@UserIdInt int changingUserId) { + // This method is guaranteed to be called only on getRegisteredHandler() + if (mSearchablePackageAppeared) { + return true; + } + + ArraySet<String> knownSearchablePackageNames = new ArraySet<>(); + synchronized (mSearchables) { + Searchables searchables = mSearchables.get(changingUserId); + if (searchables != null) { + knownSearchablePackageNames = searchables.getKnownSearchablePackageNames(); + } + } + + final int numOfPackages = mChangedPackages.size(); + for (int i = 0; i < numOfPackages; i++) { + final String packageName = mChangedPackages.get(i); + if (knownSearchablePackageNames.contains(packageName)) { + return true; + } + } + + return false; + } + + private void onFinishPackageChangesInternal() { final int changingUserId = getChangingUserId(); + if (!shouldRebuildSearchableList(changingUserId)) { + return; + } + synchronized (mSearchables) { - // Update list of searchable activities - for (int i = 0; i < mSearchables.size(); i++) { - if (changingUserId == mSearchables.keyAt(i)) { - mSearchables.valueAt(i).updateSearchableList(); - break; - } + // Invalidate the searchable list. + Searchables searchables = mSearchables.get(changingUserId); + if (searchables != null) { + searchables.invalidateSearchableList(); } } + // Inform all listeners that the list of searchables has been updated. Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING @@ -180,6 +247,17 @@ public class SearchManagerService extends ISearchManager.Stub { } } + @NonNull + static List<ResolveInfo> querySearchableActivities(Context context, Intent searchIntent, + @UserIdInt int userId) { + final List<ResolveInfo> activities = context.getPackageManager() + .queryIntentActivitiesAsUser(searchIntent, PackageManager.GET_META_DATA + | PackageManager.MATCH_INSTANT + | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId); + return activities; + } + + class GlobalSearchProviderObserver extends ContentObserver { private final ContentResolver mResolver; @@ -196,7 +274,7 @@ public class SearchManagerService extends ISearchManager.Stub { public void onChange(boolean selfChange) { synchronized (mSearchables) { for (int i = 0; i < mSearchables.size(); i++) { - mSearchables.valueAt(i).updateSearchableList(); + mSearchables.valueAt(i).invalidateSearchableList(); } } Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java index 7b397755173d..dc6733941357 100644 --- a/services/core/java/com/android/server/search/Searchables.java +++ b/services/core/java/com/android/server/search/Searchables.java @@ -35,8 +35,10 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import java.io.FileDescriptor; @@ -62,7 +64,6 @@ public class Searchables { private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; private Context mContext; - private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; private ArrayList<SearchableInfo> mSearchablesList = null; private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null; @@ -81,6 +82,12 @@ public class Searchables { final private IPackageManager mPm; // User for which this Searchables caches information private int mUserId; + @GuardedBy("this") + private boolean mRebuildSearchables = true; + + // Package names that are known to contain {@link SearchableInfo} + @GuardedBy("this") + private ArraySet<String> mKnownSearchablePackageNames = new ArraySet<>(); /** * @@ -224,7 +231,14 @@ public class Searchables { * * TODO: sort the list somehow? UI choice. */ - public void updateSearchableList() { + public void updateSearchableListIfNeeded() { + synchronized (this) { + if (!mRebuildSearchables) { + // The searchable list is valid, no need to rebuild. + return; + } + } + // These will become the new values at the end of the method HashMap<ComponentName, SearchableInfo> newSearchablesMap = new HashMap<ComponentName, SearchableInfo>(); @@ -232,6 +246,7 @@ public class Searchables { = new ArrayList<SearchableInfo>(); ArrayList<SearchableInfo> newSearchablesInGlobalSearchList = new ArrayList<SearchableInfo>(); + ArraySet<String> newKnownSearchablePackageNames = new ArraySet<>(); // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers. List<ResolveInfo> searchList; @@ -264,6 +279,7 @@ public class Searchables { mUserId); if (searchable != null) { newSearchablesList.add(searchable); + newKnownSearchablePackageNames.add(ai.packageName); newSearchablesMap.put(searchable.getSearchActivity(), searchable); if (searchable.shouldIncludeInGlobalSearch()) { newSearchablesInGlobalSearchList.add(searchable); @@ -286,16 +302,41 @@ public class Searchables { synchronized (this) { mSearchablesMap = newSearchablesMap; mSearchablesList = newSearchablesList; + mKnownSearchablePackageNames = newKnownSearchablePackageNames; mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList; mGlobalSearchActivities = newGlobalSearchActivities; mCurrentGlobalSearchActivity = newGlobalSearchActivity; mWebSearchActivity = newWebSearchActivity; + for (ResolveInfo globalSearchActivity: mGlobalSearchActivities) { + mKnownSearchablePackageNames.add( + globalSearchActivity.getComponentInfo().packageName); + } + if (mCurrentGlobalSearchActivity != null) { + mKnownSearchablePackageNames.add( + mCurrentGlobalSearchActivity.getPackageName()); + } + if (mWebSearchActivity != null) { + mKnownSearchablePackageNames.add(mWebSearchActivity.getPackageName()); + } + + mRebuildSearchables = false; } } finally { Binder.restoreCallingIdentity(ident); } } + synchronized ArraySet<String> getKnownSearchablePackageNames() { + return mKnownSearchablePackageNames; + } + + synchronized void invalidateSearchableList() { + mRebuildSearchables = true; + + // Don't rebuild the searchable list, it will be rebuilt + // when the next updateSearchableList gets called. + } + /** * Returns a sorted list of installed search providers as per * the following heuristics: @@ -532,6 +573,8 @@ public class Searchables { pw.print(" "); pw.println(info.getSuggestAuthority()); } } + + pw.println("mRebuildSearchables = " + mRebuildSearchables); } } } diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java index bb5a697114d3..7ddb61e5ca52 100644 --- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java +++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java @@ -68,12 +68,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn private final ComponentName mComponentName; RemoteSpeechRecognitionService( - Context context, ComponentName serviceName, int userId, int callingUid) { + Context context, + ComponentName serviceName, + int userId, + int callingUid, + boolean isPrivileged) { super(context, new Intent(RecognitionService.SERVICE_INTERFACE).setComponent(serviceName), - Context.BIND_AUTO_CREATE - | Context.BIND_FOREGROUND_SERVICE - | Context.BIND_INCLUDE_CAPABILITIES, + getBindingFlags(isPrivileged), userId, IRecognitionService.Stub::asInterface); @@ -85,6 +87,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn } } + private static int getBindingFlags(boolean isPrivileged) { + int bindingFlags = Context.BIND_AUTO_CREATE; + if (isPrivileged) { + bindingFlags |= Context.BIND_INCLUDE_CAPABILITIES | Context.BIND_FOREGROUND_SERVICE; + } + return bindingFlags; + } + ComponentName getServiceComponentName() { return mComponentName; } diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java index 8e9c889c8ef3..808504f50acc 100644 --- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java +++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java @@ -23,6 +23,7 @@ import android.app.AppGlobals; import android.content.AttributionSource; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -31,6 +32,7 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.permission.PermissionManager; +import android.provider.Settings; import android.speech.IModelDownloadListener; import android.speech.IRecognitionListener; import android.speech.IRecognitionService; @@ -311,9 +313,22 @@ final class SpeechRecognitionManagerServiceImpl extends return null; } + final boolean isPrivileged; + if (serviceComponent == null) { + isPrivileged = false; + } else { + // Only certain privileged recognition service can obtain process capabilities + // from persistent process to hold while-in-use permission in the background. + isPrivileged = checkPrivilege(serviceComponent); + } + RemoteSpeechRecognitionService service = new RemoteSpeechRecognitionService( - getContext(), serviceComponent, getUserId(), callingUid); + getContext(), + serviceComponent, + getUserId(), + callingUid, + isPrivileged); Set<RemoteSpeechRecognitionService> valuesByCaller = mRemoteServicesByUid.computeIfAbsent(callingUid, key -> new HashSet<>()); @@ -328,6 +343,53 @@ final class SpeechRecognitionManagerServiceImpl extends } } + /** + * Checks if the given service component should have privileged binding flags when created. Only + * a service component that matches with any of the following condition would be granted: + * + * <ul> + * <li>A default recognition service component.</li> + * <li>An on-device recognition service component.</li> + * <li>A pre-installed recognition service component.</li> + * </ul> + */ + @GuardedBy("mLock") + private boolean checkPrivilege(@NonNull ComponentName serviceComponent) { + final ComponentName defaultComponent = getDefaultRecognitionServiceComponent(); + final ComponentName onDeviceComponent = getOnDeviceComponentNameLocked(); + final boolean preinstalled = isPreinstalledApp(serviceComponent); + return serviceComponent.equals(defaultComponent) + || serviceComponent.equals(onDeviceComponent) + || preinstalled; + } + + private boolean isPreinstalledApp(@NonNull ComponentName serviceComponent) { + PackageManager pm = getContext().getPackageManager(); + if (pm == null) { + return false; + } + + try { + ApplicationInfo info = pm.getApplicationInfoAsUser(serviceComponent.getPackageName(), + PackageManager.MATCH_SYSTEM_ONLY, getUserId()); + return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + + @Nullable + private ComponentName getDefaultRecognitionServiceComponent() { + String componentName = Settings.Secure.getStringForUser( + getContext().getContentResolver(), + Settings.Secure.VOICE_RECOGNITION_SERVICE, + getUserId()); + if (componentName == null) { + return null; + } + return ComponentName.unflattenFromString(componentName); + } + private boolean componentMapsToRecognitionService(@NonNull ComponentName serviceComponent) { List<ResolveInfo> resolveInfos; diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java index 743d02d100b1..70e2e27a3bae 100644 --- a/services/core/java/com/android/server/vibrator/HalVibration.java +++ b/services/core/java/com/android/server/vibrator/HalVibration.java @@ -102,6 +102,23 @@ final class HalVibration extends Vibration { } /** + * Resolves the default vibration amplitude of {@link #getEffectToPlay()} and each fallback. + * + * @param defaultAmplitude An integer in [1,255] representing the device default amplitude to + * replace the {@link VibrationEffect#DEFAULT_AMPLITUDE}. + */ + public void resolveEffects(int defaultAmplitude) { + CombinedVibration newEffect = + mEffectToPlay.transform(VibrationEffect::resolve, defaultAmplitude); + if (!Objects.equals(mEffectToPlay, newEffect)) { + mEffectToPlay = newEffect; + } + for (int i = 0; i < mFallbacks.size(); i++) { + mFallbacks.setValueAt(i, mFallbacks.valueAt(i).resolve(defaultAmplitude)); + } + } + + /** * Scales the {@link #getEffectToPlay()} and each fallback effect with a scaling transformation. * * @param scaler A {@link VibrationEffect.Transformation<Integer>} that takes one of the diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java index 09a177a6951b..5d17884c769b 100644 --- a/services/core/java/com/android/server/vibrator/VibrationScaler.java +++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java @@ -19,7 +19,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.content.Context; import android.hardware.vibrator.V1_0.EffectStrength; -import android.os.IExternalVibratorService; +import android.os.ExternalVibrationScale; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; @@ -37,11 +37,13 @@ final class VibrationScaler { // Scale levels. Each level, except MUTE, is defined as the delta between the current setting // and the default intensity for that type of vibration (i.e. current - default). - private static final int SCALE_VERY_LOW = IExternalVibratorService.SCALE_VERY_LOW; // -2 - private static final int SCALE_LOW = IExternalVibratorService.SCALE_LOW; // -1 - private static final int SCALE_NONE = IExternalVibratorService.SCALE_NONE; // 0 - private static final int SCALE_HIGH = IExternalVibratorService.SCALE_HIGH; // 1 - private static final int SCALE_VERY_HIGH = IExternalVibratorService.SCALE_VERY_HIGH; // 2 + private static final int SCALE_VERY_LOW = + ExternalVibrationScale.ScaleLevel.SCALE_VERY_LOW; // -2 + private static final int SCALE_LOW = ExternalVibrationScale.ScaleLevel.SCALE_LOW; // -1 + private static final int SCALE_NONE = ExternalVibrationScale.ScaleLevel.SCALE_NONE; // 0 + private static final int SCALE_HIGH = ExternalVibrationScale.ScaleLevel.SCALE_HIGH; // 1 + private static final int SCALE_VERY_HIGH = + ExternalVibrationScale.ScaleLevel.SCALE_VERY_HIGH; // 2 // Scale factors for each level. private static final float SCALE_FACTOR_VERY_LOW = 0.6f; @@ -73,12 +75,19 @@ final class VibrationScaler { } /** + * Returns the default vibration amplitude configured for this device, value in [1,255]. + */ + public int getDefaultVibrationAmplitude() { + return mDefaultVibrationAmplitude; + } + + /** * Calculates the scale to be applied to external vibration with given usage. * * @param usageHint one of VibrationAttributes.USAGE_* - * @return one of IExternalVibratorService.SCALE_* + * @return one of ExternalVibrationScale.ScaleLevel.SCALE_* */ - public int getExternalVibrationScale(int usageHint) { + public int getExternalVibrationScaleLevel(int usageHint) { int defaultIntensity = mSettingsController.getDefaultIntensity(usageHint); int currentIntensity = mSettingsController.getCurrentIntensity(usageHint); @@ -100,6 +109,22 @@ final class VibrationScaler { } /** + * Returns the adaptive haptics scale that should be applied to the vibrations with + * the given usage. When no adaptive scales are available for the usages, then returns 1 + * indicating no scaling will be applied + * + * @param usageHint one of VibrationAttributes.USAGE_* + * @return The adaptive haptics scale. + */ + public float getAdaptiveHapticsScale(int usageHint) { + if (shouldApplyAdaptiveHapticsScale(usageHint)) { + return mAdaptiveHapticsScales.get(usageHint); + } + + return 1f; // no scaling + } + + /** * Scale a {@link VibrationEffect} based on the given usage hint for this vibration. * * @param effect the effect to be scaled @@ -145,9 +170,7 @@ final class VibrationScaler { } // If adaptive haptics scaling is available for this usage, apply it to the segment. - if (Flags.adaptiveHapticsEnabled() - && mAdaptiveHapticsScales.size() > 0 - && mAdaptiveHapticsScales.contains(usageHint)) { + if (shouldApplyAdaptiveHapticsScale(usageHint)) { float adaptiveScale = mAdaptiveHapticsScales.get(usageHint); segment = segment.scaleLinearly(adaptiveScale); } @@ -217,6 +240,10 @@ final class VibrationScaler { mAdaptiveHapticsScales.clear(); } + private boolean shouldApplyAdaptiveHapticsScale(int usageHint) { + return Flags.adaptiveHapticsEnabled() && mAdaptiveHapticsScales.contains(usageHint); + } + /** Mapping of Vibrator.VIBRATION_INTENSITY_* values to {@link EffectStrength}. */ private static int intensityToEffectStrength(int intensity) { switch (intensity) { diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java index 9cf942e91439..f6af9ad991ff 100644 --- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java +++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java @@ -160,7 +160,10 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { if (Flags.adaptiveHapticsEnabled()) { waitForVibrationParamsIfRequired(); } + // Scale resolves the default amplitudes from the effect before scaling them. mVibration.scaleEffects(mVibrationScaler::scale); + } else { + mVibration.resolveEffects(mVibrationScaler.getDefaultVibrationAmplitude()); } mVibration.adaptToDevice(mDeviceAdapter); diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index d979c6112cf5..78e0ebbb53fa 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -16,6 +16,7 @@ package com.android.server.vibrator; +import static android.os.ExternalVibrationScale.ScaleLevel.SCALE_MUTE; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; @@ -35,6 +36,7 @@ import android.os.Binder; import android.os.Build; import android.os.CombinedVibration; import android.os.ExternalVibration; +import android.os.ExternalVibrationScale; import android.os.Handler; import android.os.IBinder; import android.os.IExternalVibratorService; @@ -277,7 +279,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { context.registerReceiver(mIntentReceiver, filter, Context.RECEIVER_NOT_EXPORTED); injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService()); - if (ServiceManager.isDeclared(VIBRATOR_CONTROL_SERVICE)) { + if (injector.isServiceDeclared(VIBRATOR_CONTROL_SERVICE)) { injector.addService(VIBRATOR_CONTROL_SERVICE, mVibratorControlService); } @@ -884,8 +886,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private Vibration.EndInfo startVibrationOnInputDevicesLocked(HalVibration vib) { if (!vib.callerInfo.attrs.isFlagSet( VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)) { - // Scale effect before dispatching it to the input devices. + // Scale resolves the default amplitudes from the effect before scaling them. vib.scaleEffects(mVibrationScaler::scale); + } else { + vib.resolveEffects(mVibrationScaler.getDefaultVibrationAmplitude()); } mInputDeviceDelegate.vibrateIfAvailable(vib.callerInfo, vib.getEffectToPlay()); @@ -1425,6 +1429,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { VibratorControllerHolder createVibratorControllerHolder() { return new VibratorControllerHolder(); } + + boolean isServiceDeclared(String name) { + return ServiceManager.isDeclared(name); + } } /** @@ -1592,7 +1600,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { IBinder.DeathRecipient { public final ExternalVibration externalVibration; - public int scale; + public ExternalVibrationScale scale = new ExternalVibrationScale(); private Vibration.Status mStatus; @@ -1603,7 +1611,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // instead of using DEVICE_ID_INVALID here and relying on the UID checks. Context.DEVICE_ID_INVALID, externalVibration.getPackage(), null)); this.externalVibration = externalVibration; - this.scale = IExternalVibratorService.SCALE_NONE; mStatus = Vibration.Status.RUNNING; } @@ -1656,7 +1663,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { public Vibration.DebugInfo getDebugInfo() { return new Vibration.DebugInfo(mStatus, stats, /* playedEffect= */ null, - /* originalEffect= */ null, scale, callerInfo); + /* originalEffect= */ null, scale.scaleLevel, callerInfo); } public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) { @@ -1986,11 +1993,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { /** Implementation of {@link IExternalVibratorService} to be triggered on external control. */ @VisibleForTesting final class ExternalVibratorService extends IExternalVibratorService.Stub { + private static final ExternalVibrationScale SCALE_MUTE = new ExternalVibrationScale(); + + static { + SCALE_MUTE.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE; + } @Override - public int onExternalVibrationStart(ExternalVibration vib) { + public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) { + if (!hasExternalControlCapability()) { - return IExternalVibratorService.SCALE_MUTE; + return SCALE_MUTE; } if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE, vib.getUid(), -1 /*owningUid*/, true /*exported*/) @@ -1998,7 +2011,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid() + " tried to play externally controlled vibration" + " without VIBRATE permission, ignoring."); - return IExternalVibratorService.SCALE_MUTE; + return SCALE_MUTE; } // Create Vibration.Stats as close to the received request as possible, for tracking. @@ -2031,7 +2044,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } if (vibrationEndInfo != null) { - vibHolder.scale = IExternalVibratorService.SCALE_MUTE; + vibHolder.scale = SCALE_MUTE; // Failed to start the vibration, end it and report metrics right away. endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo); return vibHolder.scale; @@ -2072,7 +2085,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } mCurrentExternalVibration = vibHolder; vibHolder.linkToDeath(); - vibHolder.scale = mVibrationScaler.getExternalVibrationScale(attrs.getUsage()); + vibHolder.scale.scaleLevel = mVibrationScaler.getExternalVibrationScaleLevel( + attrs.getUsage()); + vibHolder.scale.adaptiveHapticsScale = mVibrationScaler.getAdaptiveHapticsScale( + attrs.getUsage()); } if (waitForCompletion) { @@ -2084,7 +2100,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING), /* continueExternalControl= */ false); } - return IExternalVibratorService.SCALE_MUTE; + return SCALE_MUTE; } } if (!alreadyUnderExternalControl) { diff --git a/services/core/java/com/android/server/wearable/RemoteWearableSensingService.java b/services/core/java/com/android/server/wearable/RemoteWearableSensingService.java index 3077fb8aaee9..e230b95fe907 100644 --- a/services/core/java/com/android/server/wearable/RemoteWearableSensingService.java +++ b/services/core/java/com/android/server/wearable/RemoteWearableSensingService.java @@ -43,16 +43,16 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable com.android.server.wearable.RemoteWearableSensingService.class.getSimpleName(); private final static boolean DEBUG = false; - private final Object mSecureWearableConnectionLock = new Object(); + private final Object mSecureConnectionLock = new Object(); - // mNextSecureWearableConnectionContext will only be non-null when we are waiting for the + // mNextSecureConnectionContext will only be non-null when we are waiting for the // WearableSensingService process to restart. It will be set to null after it is passed into // WearableSensingService. - @GuardedBy("mSecureWearableConnectionLock") - private SecureWearableConnectionContext mNextSecureWearableConnectionContext; + @GuardedBy("mSecureConnectionLock") + private SecureWearableConnectionContext mNextSecureConnectionContext; - @GuardedBy("mSecureWearableConnectionLock") - private boolean mSecureWearableConnectionProvided = false; + @GuardedBy("mSecureConnectionLock") + private boolean mSecureConnectionProvided = false; RemoteWearableSensingService(Context context, ComponentName serviceName, int userId) { @@ -77,23 +77,23 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable * @param secureWearableConnection The secure connection to the wearable * @param callback The callback for service status */ - public void provideSecureWearableConnection( + public void provideSecureConnection( ParcelFileDescriptor secureWearableConnection, RemoteCallback callback) { if (DEBUG) { - Slog.i(TAG, "#provideSecureWearableConnection"); + Slog.i(TAG, "#provideSecureConnection"); } if (!Flags.enableRestartWssProcess()) { Slog.d( TAG, "FLAG_ENABLE_RESTART_WSS_PROCESS is disabled. Do not attempt to restart the" + " WearableSensingService process"); - provideSecureWearableConnectionInternal(secureWearableConnection, callback); + provideSecureConnectionInternal(secureWearableConnection, callback); return; } - synchronized (mSecureWearableConnectionLock) { - if (mNextSecureWearableConnectionContext != null) { + synchronized (mSecureConnectionLock) { + if (mNextSecureConnectionContext != null) { // A process restart is in progress, #binderDied is about to be called. Replace - // the previous mNextSecureWearableConnectionContext with the current one + // the previous mNextSecureConnectionContext with the current one Slog.i( TAG, "A new wearable connection is provided before the process restart triggered" @@ -101,33 +101,33 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable + " connection."); if (Flags.enableProvideWearableConnectionApi()) { WearableSensingManagerPerUserService.notifyStatusCallback( - mNextSecureWearableConnectionContext.mStatusCallback, + mNextSecureConnectionContext.mStatusCallback, WearableSensingManager.STATUS_CHANNEL_ERROR); } - mNextSecureWearableConnectionContext = + mNextSecureConnectionContext = new SecureWearableConnectionContext(secureWearableConnection, callback); return; } - if (!mSecureWearableConnectionProvided) { + if (!mSecureConnectionProvided) { // no need to kill the process - provideSecureWearableConnectionInternal(secureWearableConnection, callback); - mSecureWearableConnectionProvided = true; + provideSecureConnectionInternal(secureWearableConnection, callback); + mSecureConnectionProvided = true; return; } - mNextSecureWearableConnectionContext = + mNextSecureConnectionContext = new SecureWearableConnectionContext(secureWearableConnection, callback); // Killing the process causes the binder to die. #binderDied will then be triggered killWearableSensingServiceProcess(); } } - private void provideSecureWearableConnectionInternal( + private void provideSecureConnectionInternal( ParcelFileDescriptor secureWearableConnection, RemoteCallback callback) { Slog.d(TAG, "Providing secure wearable connection."); var unused = post( service -> { - service.provideSecureWearableConnection( + service.provideSecureConnection( secureWearableConnection, callback); try { // close the local fd after it has been sent to the WSS process @@ -141,15 +141,15 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable @Override public void binderDied() { super.binderDied(); - synchronized (mSecureWearableConnectionLock) { - if (mNextSecureWearableConnectionContext != null) { + synchronized (mSecureConnectionLock) { + if (mNextSecureConnectionContext != null) { // This will call #post, which will recreate the process and bind to it - provideSecureWearableConnectionInternal( - mNextSecureWearableConnectionContext.mSecureWearableConnection, - mNextSecureWearableConnectionContext.mStatusCallback); - mNextSecureWearableConnectionContext = null; + provideSecureConnectionInternal( + mNextSecureConnectionContext.mSecureConnection, + mNextSecureConnectionContext.mStatusCallback); + mNextSecureConnectionContext = null; } else { - mSecureWearableConnectionProvided = false; + mSecureConnectionProvided = false; Slog.w(TAG, "Binder died but there is no secure wearable connection to provide."); } } @@ -307,12 +307,12 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable } private static class SecureWearableConnectionContext { - final ParcelFileDescriptor mSecureWearableConnection; + final ParcelFileDescriptor mSecureConnection; final RemoteCallback mStatusCallback; SecureWearableConnectionContext( ParcelFileDescriptor secureWearableConnection, RemoteCallback statusCallback) { - this.mSecureWearableConnection = secureWearableConnection; + this.mSecureConnection = secureWearableConnection; this.mStatusCallback = statusCallback; } } diff --git a/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java b/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java index 2b43203628d9..34b9fe968994 100644 --- a/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java +++ b/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java @@ -189,9 +189,9 @@ final class WearableSensingManagerPerUserService extends * Creates a CompanionDeviceManager secure channel and sends a proxy to the wearable sensing * service. */ - public void onProvideWearableConnection( + public void onProvideConnection( ParcelFileDescriptor wearableConnection, RemoteCallback callback) { - Slog.i(TAG, "onProvideWearableConnection in per user service."); + Slog.i(TAG, "onProvideConnection in per user service."); synchronized (mLock) { if (!setUpServiceIfNeeded()) { Slog.w(TAG, "Detection service is not available at this moment."); @@ -217,7 +217,7 @@ final class WearableSensingManagerPerUserService extends Slog.i(TAG, "calling over to remote service."); synchronized (mLock) { ensureRemoteServiceInitiated(); - mRemoteService.provideSecureWearableConnection( + mRemoteService.provideSecureConnection( secureTransport, callback); } } diff --git a/services/core/java/com/android/server/wearable/WearableSensingManagerService.java b/services/core/java/com/android/server/wearable/WearableSensingManagerService.java index d05482d75083..5f6ffd988c84 100644 --- a/services/core/java/com/android/server/wearable/WearableSensingManagerService.java +++ b/services/core/java/com/android/server/wearable/WearableSensingManagerService.java @@ -399,9 +399,9 @@ public class WearableSensingManagerService extends private final class WearableSensingManagerInternal extends IWearableSensingManager.Stub { @Override - public void provideWearableConnection( + public void provideConnection( ParcelFileDescriptor wearableConnection, RemoteCallback callback) { - Slog.i(TAG, "WearableSensingManagerInternal provideWearableConnection."); + Slog.i(TAG, "WearableSensingManagerInternal provideConnection."); Objects.requireNonNull(wearableConnection); Objects.requireNonNull(callback); mContext.enforceCallingOrSelfPermission( @@ -413,7 +413,7 @@ public class WearableSensingManagerService extends return; } callPerUserServiceIfExist( - service -> service.onProvideWearableConnection(wearableConnection, callback), + service -> service.onProvideConnection(wearableConnection, callback), callback); } diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java index 3b2e69a97889..c6e8eb8d3743 100644 --- a/services/core/java/com/android/server/webkit/SystemImpl.java +++ b/services/core/java/com/android/server/webkit/SystemImpl.java @@ -23,6 +23,7 @@ import android.app.AppGlobals; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; @@ -225,6 +226,21 @@ public class SystemImpl implements SystemInterface { } @Override + public void installExistingPackageForAllUsers(Context context, String packageName) { + UserManager userManager = context.getSystemService(UserManager.class); + for (UserInfo userInfo : userManager.getUsers()) { + installPackageForUser(packageName, userInfo.id); + } + } + + private void installPackageForUser(String packageName, int userId) { + final Context context = AppGlobals.getInitialApplication(); + final Context contextAsUser = context.createContextAsUser(UserHandle.of(userId), 0); + final PackageInstaller installer = contextAsUser.getPackageManager().getPackageInstaller(); + installer.installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN, null); + } + + @Override public boolean systemIsDebuggable() { return Build.IS_DEBUGGABLE; } diff --git a/services/core/java/com/android/server/webkit/SystemInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java index 5ed2cfe4252d..ad32f623c80d 100644 --- a/services/core/java/com/android/server/webkit/SystemInterface.java +++ b/services/core/java/com/android/server/webkit/SystemInterface.java @@ -43,6 +43,7 @@ public interface SystemInterface { public void killPackageDependents(String packageName); public void enablePackageForAllUsers(Context context, String packageName, boolean enable); + public void installExistingPackageForAllUsers(Context context, String packageName); public boolean systemIsDebuggable(); public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo) diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java index b3c8b0b3a47a..596de686089e 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java @@ -107,15 +107,20 @@ class WebViewUpdateServiceImpl2 implements WebViewUpdateServiceInterface { mContext = context; mSystemInterface = systemInterface; WebViewProviderInfo[] webviewProviders = getWebViewPackages(); + + WebViewProviderInfo defaultProvider = null; for (WebViewProviderInfo provider : webviewProviders) { if (provider.availableByDefault) { - mDefaultProvider = provider; + defaultProvider = provider; break; } } - // This should be unreachable because the config parser enforces that there is at least one - // availableByDefault provider. - throw new AndroidRuntimeException("No available by default WebView Provider."); + if (defaultProvider == null) { + // This should be unreachable because the config parser enforces that there is at least + // one availableByDefault provider. + throw new AndroidRuntimeException("No available by default WebView Provider."); + } + mDefaultProvider = defaultProvider; } @Override @@ -206,14 +211,16 @@ class WebViewUpdateServiceImpl2 implements WebViewUpdateServiceInterface { } if (repairNeeded) { - // We didn't find a valid WebView implementation. Try explicitly re-enabling the - // default package for all users in case it was disabled, even if we already did the - // one-time migration before. If this actually changes the state, we will see the - // PackageManager broadcast shortly and try again. + // We didn't find a valid WebView implementation. Try explicitly re-installing and + // re-enabling the default package for all users in case it was disabled, even if we + // already did the one-time migration before. If this actually changes the state, we + // will see the PackageManager broadcast shortly and try again. Slog.w( TAG, - "No provider available for all users, trying to enable " + "No provider available for all users, trying to install and enable " + mDefaultProvider.packageName); + mSystemInterface.installExistingPackageForAllUsers( + mContext, mDefaultProvider.packageName); mSystemInterface.enablePackageForAllUsers( mContext, mDefaultProvider.packageName, true); } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 44a0547a6828..d08e272d76dd 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -304,9 +304,9 @@ final class AccessibilityController { Surface forceShowMagnifierSurface(int displayId) { final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); if (displayMagnifier != null) { - displayMagnifier.mMagnifedViewport.mWindow.setAlpha(DisplayMagnifier.MagnifiedViewport + displayMagnifier.mMagnifiedViewport.mWindow.setAlpha(DisplayMagnifier.MagnifiedViewport .ViewportWindow.AnimationController.MAX_ALPHA); - return displayMagnifier.mMagnifedViewport.mWindow.mSurface; + return displayMagnifier.mMagnifiedViewport.mWindow.mSurface; } return null; } @@ -463,6 +463,10 @@ final class AccessibilityController { } void drawMagnifiedRegionBorderIfNeeded(int displayId) { + if (Flags.magnificationAlwaysDrawFullscreenBorder()) { + return; + } + if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { mAccessibilityTracing.logTrace( TAG + ".drawMagnifiedRegionBorderIfNeeded", @@ -614,7 +618,7 @@ final class AccessibilityController { private final Context mDisplayContext; private final WindowManagerService mService; - private final MagnifiedViewport mMagnifedViewport; + private final MagnifiedViewport mMagnifiedViewport; private final Handler mHandler; private final DisplayContent mDisplayContent; private final Display mDisplay; @@ -649,7 +653,8 @@ final class AccessibilityController { mDisplayContent = displayContent; mDisplay = display; mHandler = new MyHandler(mService.mH.getLooper()); - mMagnifedViewport = new MagnifiedViewport(); + mMagnifiedViewport = Flags.magnificationAlwaysDrawFullscreenBorder() + ? null : new MagnifiedViewport(); mAccessibilityTracing = AccessibilityController.getAccessibilityControllerInternal(mService); mLongAnimationDuration = mDisplayContext.getResources().getInteger( @@ -692,7 +697,9 @@ final class AccessibilityController { mMagnificationSpec.clear(); } - mMagnifedViewport.setShowMagnifiedBorderIfNeeded(); + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.setShowMagnifiedBorderIfNeeded(); + } } void setFullscreenMagnificationActivated(boolean activated) { @@ -701,8 +708,10 @@ final class AccessibilityController { FLAGS_MAGNIFICATION_CALLBACK, "activated=" + activated); } mIsFullscreenMagnificationActivated = activated; - mMagnifedViewport.setMagnifiedRegionBorderShown(activated, true); - mMagnifedViewport.showMagnificationBoundsIfNeeded(); + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.setMagnifiedRegionBorderShown(activated, true); + mMagnifiedViewport.showMagnificationBoundsIfNeeded(); + } } boolean isFullscreenMagnificationActivated() { @@ -737,7 +746,9 @@ final class AccessibilityController { } recomputeBounds(); - mMagnifedViewport.onDisplaySizeChanged(); + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.onDisplaySizeChanged(); + } mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED); } @@ -901,7 +912,10 @@ final class AccessibilityController { if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { mAccessibilityTracing.logTrace(LOG_TAG + ".destroy", FLAGS_MAGNIFICATION_CALLBACK); } - mMagnifedViewport.destroyWindow(); + + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.destroyWindow(); + } } void drawMagnifiedRegionBorderIfNeeded() { @@ -909,7 +923,10 @@ final class AccessibilityController { mAccessibilityTracing.logTrace(LOG_TAG + ".drawMagnifiedRegionBorderIfNeeded", FLAGS_MAGNIFICATION_CALLBACK); } - mMagnifedViewport.drawWindowIfNeeded(); + + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.drawWindowIfNeeded(); + } } void recomputeBounds() { @@ -1006,14 +1023,16 @@ final class AccessibilityController { } visibleWindows.clear(); - mMagnifedViewport.intersectWithDrawBorderInset(screenWidth, screenHeight); - + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.intersectWithDrawBorderInset(screenWidth, screenHeight); + } final boolean magnifiedChanged = !mOldMagnificationRegion.equals(mMagnificationRegion); if (magnifiedChanged) { - mMagnifedViewport.updateBorderDrawingStatus(screenWidth, screenHeight); - + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.updateBorderDrawingStatus(screenWidth, screenHeight); + } mOldMagnificationRegion.set(mMagnificationRegion); final SomeArgs args = SomeArgs.obtain(); args.arg1 = Region.obtain(mMagnificationRegion); @@ -1070,7 +1089,9 @@ final class AccessibilityController { } void dump(PrintWriter pw, String prefix) { - mMagnifedViewport.dump(pw, prefix); + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.dump(pw, prefix); + } } private final class MagnifiedViewport { @@ -1079,7 +1100,7 @@ final class AccessibilityController { private final int mHalfBorderWidth; private final int mDrawBorderInset; - private final ViewportWindow mWindow; + @Nullable private final ViewportWindow mWindow; private boolean mFullRedrawNeeded; @@ -1138,9 +1159,9 @@ final class AccessibilityController { void onDisplaySizeChanged() { // If fullscreen magnification is activated, hide the border immediately so // the user does not see strange artifacts during display size changed caused by - // rotation or folding/unfolding the device. In the rotation case, the screenshot - // used for rotation already has the border. After the rotation is complete - // we will show the border. + // rotation or folding/unfolding the device. In the rotation case, the + // screenshot used for rotation already has the border. After the rotation is + // completed we will show the border. if (isFullscreenMagnificationActivated()) { setMagnifiedRegionBorderShown(false, false); final long delay = (long) (mLongAnimationDuration @@ -1173,6 +1194,8 @@ final class AccessibilityController { mWindow.dump(pw, prefix); } + // TODO(291891390): Remove this class when we clean up the flag + // magnificationAlwaysDrawFullscreenBorder private final class ViewportWindow implements Runnable { private static final String SURFACE_TITLE = "Magnification Overlay"; @@ -1467,6 +1490,9 @@ final class AccessibilityController { public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1; public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3; public static final int MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED = 4; + + // TODO(291891390): Remove this field when we clean up the flag + // magnificationAlwaysDrawFullscreenBorder public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5; public static final int MESSAGE_NOTIFY_IME_WINDOW_VISIBILITY_CHANGED = 6; @@ -1495,7 +1521,9 @@ final class AccessibilityController { case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : { synchronized (mService.mGlobalLock) { if (isFullscreenMagnificationActivated()) { - mMagnifedViewport.setMagnifiedRegionBorderShown(true, true); + if (!Flags.magnificationAlwaysDrawFullscreenBorder()) { + mMagnifiedViewport.setMagnifiedRegionBorderShown(true, true); + } mService.scheduleAnimationLocked(); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 56024f75545c..5036fc646327 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -353,6 +353,7 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.TransitionOldType; import android.view.animation.Animation; +import android.window.ActivityWindowInfo; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; import android.window.SizeConfigurationBuckets; @@ -519,6 +520,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private int mLastReportedDisplayId; boolean mLastReportedMultiWindowMode; boolean mLastReportedPictureInPictureMode; + private final ActivityWindowInfo mLastReportedActivityWindowInfo = new ActivityWindowInfo(); ActivityRecord resultTo; // who started this entry, so will get our reply final String resultWho; // additional identifier for use by resultTo. final int requestCode; // code given by requester (resultTo) @@ -958,6 +960,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private final Configuration mTmpConfig = new Configuration(); private final Rect mTmpBounds = new Rect(); + private final ActivityWindowInfo mTmpActivityWindowInfo = new ActivityWindowInfo(); // Token for targeting this activity for assist purposes. final Binder assistToken = new Binder(); @@ -1096,6 +1099,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.println(prefix + "mLastReportedConfigurations:"); mLastReportedConfiguration.dump(pw, prefix + " "); + if (Flags.activityWindowInfoFlag()) { + pw.print(prefix); + pw.print("mLastReportedActivityWindowInfo="); + pw.println(mLastReportedActivityWindowInfo); + } + pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration()); if (!getRequestedOverrideConfiguration().equals(EMPTY)) { pw.println(prefix + "RequestedOverrideConfiguration=" @@ -1535,11 +1544,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Picture-in-picture mode changes also trigger a multi-window mode change as well, so // update that here in order. Set the last reported MW state to the same as the PiP // state since we haven't yet actually resized the task (these callbacks need to - // precede the configuration change from the resize. + // precede the configuration change from the resize.) mLastReportedPictureInPictureMode = inPictureInPictureMode; mLastReportedMultiWindowMode = inPictureInPictureMode; ensureActivityConfiguration(true /* ignoreVisibility */); - if (inPictureInPictureMode && findMainWindow() == null) { + if (inPictureInPictureMode && findMainWindow() == null + && task.topRunningActivity() == this) { // Prevent malicious app entering PiP without valid WindowState, which can in turn // result a non-touchable PiP window since the InputConsumer for PiP requires it. EventLog.writeEvent(0x534e4554, "265293293", -1, ""); @@ -3149,6 +3159,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + /** + * This is different from {@link #isEmbedded()}. + * {@link #isEmbedded()} is {@code true} when any of the parent {@link TaskFragment} is created + * by a {@link android.window.TaskFragmentOrganizer}, while this method is {@code true} when + * the parent {@link TaskFragment} is embedded and has bounds override that does not fill the + * leaf {@link Task}. + */ + boolean isEmbeddedInHostContainer() { + final TaskFragment taskFragment = getOrganizedTaskFragment(); + return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride(); + } + + @NonNull + ActivityWindowInfo getActivityWindowInfo() { + if (!Flags.activityWindowInfoFlag() || !isAttached()) { + return mTmpActivityWindowInfo; + } + mTmpActivityWindowInfo.set( + isEmbeddedInHostContainer(), + getTask().getBounds(), + getTaskFragment().getBounds()); + return mTmpActivityWindowInfo; + } + @Override @Nullable TaskDisplayArea getDisplayArea() { @@ -3549,7 +3583,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A IBinder callerToken = new Binder(); if (android.security.Flags.contentUriPermissionApis()) { try { - resultTo.computeCallerInfo(callerToken, intent, this.getUid(), + resultTo.computeCallerInfo(callerToken, resultData, this.getUid(), mAtmService.getPackageManager().getNameForUid(this.getUid()), /* isShareIdentityEnabled */ false); // Result callers cannot share their identity via @@ -8212,6 +8246,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLastReportedConfiguration.setConfiguration(global, override); } + void setLastReportedActivityWindowInfo(@NonNull ActivityWindowInfo activityWindowInfo) { + if (Flags.activityWindowInfoFlag()) { + mLastReportedActivityWindowInfo.set(activityWindowInfo); + } + } + @Nullable CompatDisplayInsets getCompatDisplayInsets() { if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { @@ -10019,7 +10059,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pendingResults, pendingNewIntents, configChangeFlags, new MergedConfiguration(getProcessGlobalConfiguration(), getMergedOverrideConfiguration()), - preserveWindow); + preserveWindow, getActivityWindowInfo()); final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(token, isTransitionForward(), diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 63cdf0ef4b43..c137c54949e9 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -414,6 +414,7 @@ class ActivityStarter { int filterCallingUid; PendingIntentRecord originatingPendingIntent; BackgroundStartPrivileges forcedBalByPiSender; + boolean freezeScreen; final StringBuilder logMessage = new StringBuilder(); @@ -477,6 +478,7 @@ class ActivityStarter { filterCallingUid = UserHandle.USER_NULL; originatingPendingIntent = null; forcedBalByPiSender = BackgroundStartPrivileges.NONE; + freezeScreen = false; errorCallbackToken = null; } @@ -520,6 +522,7 @@ class ActivityStarter { filterCallingUid = request.filterCallingUid; originatingPendingIntent = request.originatingPendingIntent; forcedBalByPiSender = request.forcedBalByPiSender; + freezeScreen = request.freezeScreen; errorCallbackToken = request.errorCallbackToken; } @@ -1525,6 +1528,18 @@ class ActivityStarter { Transition newTransition = transitionController.isShellTransitionsEnabled() ? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null; RemoteTransition remoteTransition = r.takeRemoteTransition(); + // Create a display snapshot as soon as possible. + if (newTransition != null && mRequest.freezeScreen) { + final TaskDisplayArea tda = mLaunchParams.hasPreferredTaskDisplayArea() + ? mLaunchParams.mPreferredTaskDisplayArea + : mRootWindowContainer.getDefaultTaskDisplayArea(); + final DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate( + tda.getDisplayId()); + if (dc != null) { + transitionController.collect(dc); + transitionController.collectVisibleChange(dc); + } + } try { mService.deferWindowLayout(); transitionController.collect(r); @@ -1533,6 +1548,8 @@ class ActivityStarter { result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, options, inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid); + } catch (Exception ex) { + Slog.e(TAG, "Exception on startActivityInner", ex); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startedActivityRootTask = handleStartResult(r, options, result, newTransition, @@ -3270,6 +3287,11 @@ class ActivityStarter { return this; } + ActivityStarter setFreezeScreen(boolean freezeScreen) { + mRequest.freezeScreen = freezeScreen; + return this; + } + ActivityStarter setErrorCallbackToken(@Nullable IBinder errorCallbackToken) { mRequest.errorCallbackToken = errorCallbackToken; return this; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index ed556a55010e..4a5b2211800c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -275,6 +275,19 @@ public abstract class ActivityTaskManagerInternal { int startFlags, @Nullable Bundle options, int userId); /** + * Start activity {@code intent} with initially under screenshot. The screen of launching + * display will be frozen before transition occur. + * + * - DO NOT call it with the calling UID cleared. + * - The caller must do the calling user ID check. + * + * @return error codes used by {@link IActivityManager#startActivity} and its siblings. + */ + public abstract int startActivityWithScreenshot(@NonNull Intent intent, + @NonNull String callingPackage, int callingUid, int callingPid, + @Nullable IBinder resultTo, @Nullable Bundle options, int userId); + + /** * Called after virtual display Id is updated by * {@link com.android.server.vr.Vr2dDisplay} with a specific * {@param vr2dDisplayId}. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 24c228e88c1c..514a3d87ecf0 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2505,6 +2505,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId, "getRecentTasks"); final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(), callingUid); + if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKED)) { + Slog.i(TAG, "User " + userId + " is locked. Cannot load recents"); + return ParceledListSlice.emptyList(); + } + mRecentTasks.loadRecentTasksIfNeeded(userId); synchronized (mGlobalLock) { return mRecentTasks.getRecentTasks(maxNum, flags, allowed, userId, callingUid); } @@ -6014,6 +6019,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { false /*validateIncomingUser*/); } + @Override + public int startActivityWithScreenshot(@NonNull Intent intent, + @NonNull String callingPackage, int callingUid, int callingPid, + @Nullable IBinder resultTo, @Nullable Bundle options, int userId) { + return getActivityStartController() + .obtainStarter(intent, "startActivityWithScreenshot") + .setCallingUid(callingUid) + .setCallingPid(callingPid) + .setCallingPackage(callingPackage) + .setResultTo(resultTo) + .setActivityOptions(createSafeActivityOptionsWithBalAllowed(options)) + .setRealCallingUid(Binder.getCallingUid()) + .setUserId(userId) + .setBackgroundStartPrivileges(BackgroundStartPrivileges.ALLOW_BAL) + .setFreezeScreen(true) + .execute(); + } + /** * Called after virtual display Id is updated by * {@link com.android.server.vr.Vr2dDisplay} with a specific @@ -7038,11 +7061,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void loadRecentTasksForUser(int userId) { - synchronized (mGlobalLock) { - mRecentTasks.loadUserRecentsLocked(userId); - // TODO renaming the methods(?) - mPackageConfigPersister.loadUserPackages(userId); - } + // This runs on android.fg thread when the user is unlocking. + mRecentTasks.loadRecentTasksIfNeeded(userId); + mPackageConfigPersister.loadUserPackages(userId); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 09f5eda5b571..aefa777a1db7 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -138,6 +138,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.view.Display; +import android.window.ActivityWindowInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; @@ -909,6 +910,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { final Configuration overrideConfig = r.getMergedOverrideConfiguration(); r.setLastReportedConfiguration(procConfig, overrideConfig); + final ActivityWindowInfo activityWindowInfo = r.getActivityWindowInfo(); + r.setLastReportedActivityWindowInfo(activityWindowInfo); + logIfTransactionTooLarge(r.intent, r.getSavedState()); final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment(); @@ -931,7 +935,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken, - r.initialCallerInfoAccessToken); + r.initialCallerInfoAccessToken, activityWindowInfo); // Set desired final state. final ActivityLifecycleItem lifecycleItem; @@ -1889,7 +1893,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Check that we aren't reparenting to the same root task that the task is already in if (prevRootTask != null && prevRootTask.mTaskId == rootTaskId) { Slog.w(TAG, "Can not reparent to same root task, task=" + task - + " already in rootTaskId=" + rootTaskId); + + " already in rootTaskId=" + rootTaskId + " by " + Debug.getCallers(8)); return prevRootTask; } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 939cf1ae471b..1a63f14e1b8c 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -137,7 +137,6 @@ import android.view.animation.TranslateAnimation; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TransitionAnimation; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.DumpUtils.Dump; import com.android.internal.util.function.pooled.PooledLambda; @@ -248,7 +247,7 @@ public class AppTransition implements Dump { mHandler = new Handler(service.mH.getLooper()); mDisplayContent = displayContent; mTransitionAnimation = new TransitionAnimation( - context, ProtoLogImpl.isEnabled(WM_DEBUG_ANIM), TAG); + context, ProtoLog.isEnabled(WM_DEBUG_ANIM), TAG); mGridLayoutRecentsEnabled = SystemProperties.getBoolean("ro.recents.grid", false); diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java index 1dc9493eddc6..f11d6ec0828c 100644 --- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java @@ -16,8 +16,6 @@ package com.android.server.wm; -import static android.util.DisplayMetrics.DENSITY_DEFAULT; - import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -30,7 +28,6 @@ import android.util.Slog; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.wm.shell.Flags; - /** * The class that defines default launch params for tasks in desktop mode */ @@ -44,12 +41,9 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier { private static final boolean ENABLE_DESKTOP_WINDOWING = Flags.enableDesktopWindowing(); private static final boolean DESKTOP_MODE_PROTO2_SUPPORTED = SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false); - // Override default freeform task width when desktop mode is enabled. In dips. - private static final int DESKTOP_MODE_DEFAULT_WIDTH_DP = SystemProperties.getInt( - "persist.wm.debug.desktop_mode.default_width", 840); - // Override default freeform task height when desktop mode is enabled. In dips. - private static final int DESKTOP_MODE_DEFAULT_HEIGHT_DP = SystemProperties.getInt( - "persist.wm.debug.desktop_mode.default_height", 630); + public static final float DESKTOP_MODE_INITIAL_BOUNDS_SCALE = + SystemProperties + .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f; private StringBuilder mLogBuilder; @@ -108,23 +102,29 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier { return RESULT_SKIP; } - // Update width and height with default desktop mode values - float density = (float) task.getConfiguration().densityDpi / DENSITY_DEFAULT; - final int width = (int) (DESKTOP_MODE_DEFAULT_WIDTH_DP * density + 0.5f); - final int height = (int) (DESKTOP_MODE_DEFAULT_HEIGHT_DP * density + 0.5f); - outParams.mBounds.right = width; - outParams.mBounds.bottom = height; - - // Center the task in window bounds - Rect windowBounds = task.getWindowConfiguration().getBounds(); - outParams.mBounds.offset(windowBounds.centerX() - outParams.mBounds.centerX(), - windowBounds.centerY() - outParams.mBounds.centerY()); + calculateAndCentreInitialBounds(task, outParams); appendLog("setting desktop mode task bounds to %s", outParams.mBounds); return RESULT_DONE; } + /** + * Calculates the initial height and width of a task in desktop mode and centers it within the + * window bounds. + */ + private void calculateAndCentreInitialBounds(Task task, + LaunchParamsController.LaunchParams outParams) { + // TODO(b/319819547): Account for app constraints so apps do not become letterboxed + final Rect windowBounds = task.getDisplayArea().getBounds(); + final int width = (int) (windowBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int height = (int) (windowBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + outParams.mBounds.right = width; + outParams.mBounds.bottom = height; + outParams.mBounds.offset(windowBounds.centerX() - outParams.mBounds.centerX(), + windowBounds.centerY() - outParams.mBounds.centerY()); + } + private void initLogBuilder(Task task, ActivityRecord activity) { if (DEBUG) { mLogBuilder = new StringBuilder( diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 5cf9acdbc0d6..7f3df958664c 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -47,6 +47,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLO import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; @@ -1533,9 +1534,19 @@ public class DisplayPolicy { // Check the windows that overlap with system bars to determine system bars' appearance. if ((appWindow && attached == null && attrs.isFullscreen()) || attrs.type == TYPE_VOICE_INTERACTION) { - // Record the top-fullscreen-app-window which will be used to determine system UI + + // If this is the exiting starting window, don't let it control the system bars. + // The app window behind it should be the controlling window instead. Reason: when an + // activity starts another activity behind a starting window, the app window of the + // first activity will lose the window focus. And then mTopFullscreenOpaqueWindowState + // will control the system bars. The logic here is to let first app window keep + // controlling system bars until the second app window is ready. + final boolean exitingStartingWindow = + attrs.type == TYPE_APPLICATION_STARTING && win.mAnimatingExit; + + // Record the top-fullscreen-app-window which will be used to determine the system UI // controlling window. - if (mTopFullscreenOpaqueWindowState == null) { + if (mTopFullscreenOpaqueWindowState == null && !exitingStartingWindow) { mTopFullscreenOpaqueWindowState = win; } diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index e027eb63f1d5..dd146420c748 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.app.ActivityManager.FLAG_AND_UNLOCKED; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.app.ActivityManager.RECENT_WITH_EXCLUDED; import static android.app.ActivityTaskManager.INVALID_TASK_ID; @@ -69,6 +68,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArraySet; +import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -89,9 +89,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; /** * Class for managing the recent tasks list. The list is ordered by most recent (index 0) to the @@ -167,8 +167,9 @@ class RecentTasks { /** * Mapping of user id -> whether recent tasks have been loaded for that user. + * The AtomicBoolean per user will be locked when reading persisted task from storage. */ - private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray( + private final SparseArray<AtomicBoolean> mUsersWithRecentsLoaded = new SparseArray<>( DEFAULT_INITIAL_CAPACITY); /** @@ -481,29 +482,49 @@ class RecentTasks { /** * Loads the persistent recentTasks for {@code userId} into this list from persistent storage. - * Does nothing if they are already loaded. - * - * @param userId the user Id + * Does nothing if they are already loaded. This may perform IO operation, so the caller should + * not hold a lock. */ - void loadUserRecentsLocked(int userId) { - if (mUsersWithRecentsLoaded.get(userId)) { - // User already loaded, return early - return; + void loadRecentTasksIfNeeded(int userId) { + AtomicBoolean userLoaded; + synchronized (mService.mGlobalLock) { + userLoaded = mUsersWithRecentsLoaded.get(userId); + if (userLoaded == null) { + mUsersWithRecentsLoaded.append(userId, userLoaded = new AtomicBoolean()); + } } + synchronized (userLoaded) { + if (userLoaded.get()) { + // The recent tasks of the user are already loaded. + return; + } + // Read task files from storage. + final SparseBooleanArray persistedTaskIds = + mTaskPersister.readPersistedTaskIdsFromFileForUser(userId); + final TaskPersister.RecentTaskFiles taskFiles = TaskPersister.loadTasksForUser(userId); + synchronized (mService.mGlobalLock) { + restoreRecentTasksLocked(userId, persistedTaskIds, taskFiles); + } + userLoaded.set(true); + } + } - // Load the task ids if not loaded. - loadPersistedTaskIdsForUserLocked(userId); - - // Check if any tasks are added before recents is loaded - final SparseBooleanArray preaddedTasks = new SparseBooleanArray(); - for (final Task task : mTasks) { + /** Restores recent tasks from raw data (the files are already read into memory). */ + private void restoreRecentTasksLocked(int userId, SparseBooleanArray persistedTaskIds, + TaskPersister.RecentTaskFiles taskFiles) { + mTaskPersister.setPersistedTaskIds(userId, persistedTaskIds); + mPersistedTaskIds.put(userId, persistedTaskIds.clone()); + // Check if any tasks are added before recents is loaded. + final IntArray existedTaskIds = new IntArray(); + for (int i = mTasks.size() - 1; i >= 0; i--) { + final Task task = mTasks.get(i); if (task.mUserId == userId && shouldPersistTaskLocked(task)) { - preaddedTasks.put(task.mTaskId, true); + existedTaskIds.add(task.mTaskId); } } - - Slog.i(TAG, "Loading recents for user " + userId + " into memory."); - List<Task> tasks = mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks); + Slog.i(TAG, "Restoring recents for user " + userId); + final ArrayList<Task> tasks = mTaskPersister.restoreTasksForUserLocked(userId, taskFiles, + existedTaskIds); // Tasks are ordered from most recent to least recent. Update the last active time to be // in sync with task recency when device reboots, so the most recent task has the @@ -516,37 +537,34 @@ class RecentTasks { mTasks.addAll(tasks); cleanupLocked(userId); - mUsersWithRecentsLoaded.put(userId, true); // If we have tasks added before loading recents, we need to update persistent task IDs. - if (preaddedTasks.size() > 0) { + if (existedTaskIds.size() > 0) { syncPersistentTaskIdsLocked(); } } - private void loadPersistedTaskIdsForUserLocked(int userId) { - // An empty instead of a null set here means that no persistent taskIds were present - // on file when we loaded them. - if (mPersistedTaskIds.get(userId) == null) { - mPersistedTaskIds.put(userId, mTaskPersister.loadPersistedTaskIdsForUser(userId)); - Slog.i(TAG, "Loaded persisted task ids for user " + userId); - } + private boolean isRecentTasksLoaded(int userId) { + final AtomicBoolean userLoaded = mUsersWithRecentsLoaded.get(userId); + return userLoaded != null && userLoaded.get(); } /** * @return whether the {@param taskId} is currently in use for the given user. */ boolean containsTaskId(int taskId, int userId) { - loadPersistedTaskIdsForUserLocked(userId); - return mPersistedTaskIds.get(userId).get(taskId); + final SparseBooleanArray taskIds = mPersistedTaskIds.get(userId); + return taskIds != null && taskIds.get(taskId); } - /** - * @return all the task ids for the user with the given {@param userId}. - */ - SparseBooleanArray getTaskIdsForUser(int userId) { - loadPersistedTaskIdsForUserLocked(userId); - return mPersistedTaskIds.get(userId); + /** Returns all the task ids for the user from {@link #usersWithRecentsLoadedLocked}. */ + SparseBooleanArray getTaskIdsForLoadedUser(int loadedUserId) { + final SparseBooleanArray taskIds = mPersistedTaskIds.get(loadedUserId); + if (taskIds == null) { + Slog.wtf(TAG, "Loaded user without loaded tasks, userId=" + loadedUserId); + return new SparseBooleanArray(); + } + return taskIds; } /** @@ -565,7 +583,7 @@ class RecentTasks { private void syncPersistentTaskIdsLocked() { for (int i = mPersistedTaskIds.size() - 1; i >= 0; i--) { int userId = mPersistedTaskIds.keyAt(i); - if (mUsersWithRecentsLoaded.get(userId)) { + if (isRecentTasksLoaded(userId)) { // Recents are loaded only after task ids are loaded. Therefore, the set of taskids // referenced here should not be null. mPersistedTaskIds.valueAt(i).clear(); @@ -621,7 +639,7 @@ class RecentTasks { int len = 0; for (int i = 0; i < usersWithRecentsLoaded.length; i++) { int userId = mUsersWithRecentsLoaded.keyAt(i); - if (mUsersWithRecentsLoaded.valueAt(i)) { + if (mUsersWithRecentsLoaded.valueAt(i).get()) { usersWithRecentsLoaded[len++] = userId; } } @@ -639,7 +657,7 @@ class RecentTasks { * @param userId the id of the user */ void unloadUserDataFromMemoryLocked(int userId) { - if (mUsersWithRecentsLoaded.get(userId)) { + if (isRecentTasksLoaded(userId)) { Slog.i(TAG, "Unloading recents for user " + userId + " from memory."); mUsersWithRecentsLoaded.delete(userId); removeTasksForUserLocked(userId); @@ -922,11 +940,6 @@ class RecentTasks { return mService.mAmInternal.getCurrentProfileIds(); } - @VisibleForTesting - boolean isUserRunning(int userId, int flags) { - return mService.mAmInternal.isUserRunning(userId, flags); - } - /** * @return the list of recent tasks for presentation. */ @@ -942,13 +955,6 @@ class RecentTasks { private ArrayList<ActivityManager.RecentTaskInfo> getRecentTasksImpl(int maxNum, int flags, boolean getTasksAllowed, int userId, int callingUid) { final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0; - - if (!isUserRunning(userId, FLAG_AND_UNLOCKED)) { - Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents"); - return new ArrayList<>(); - } - loadUserRecentsLocked(userId); - final Set<Integer> includedUsers = getProfileIds(userId); includedUsers.add(Integer.valueOf(userId)); diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index a98b9f7cd1d1..3ef6eeb2ecf3 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -44,7 +44,6 @@ import android.view.SurfaceControl.Transaction; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.FastPrintWriter; import com.android.server.wm.SurfaceAnimator.AnimationType; @@ -210,7 +209,7 @@ class RemoteAnimationController implements DeathRecipient { Slog.e(TAG, "Failed to start remote animation", e); onAnimationFinished(); } - if (ProtoLogImpl.isEnabled(WM_DEBUG_REMOTE_ANIMATIONS)) { + if (ProtoLog.isEnabled(WM_DEBUG_REMOTE_ANIMATIONS)) { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation(): Notify animation start:"); writeStartDebugStatement(); } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index b562ccfb3d2b..07a03ebcc9b2 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2158,7 +2158,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> organizedTf.mClearedTaskFragmentForPip = true; } - transitionController.collect(rootTask); + if (isPip2ExperimentEnabled()) { + transitionController.collectExistenceChange(rootTask); + } else { + transitionController.collect(rootTask); + } if (transitionController.isShellTransitionsEnabled()) { // set mode NOW so that when we reparent the activity, it won't be resumed. diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index c3de4d5acc21..d67684c7038e 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -32,7 +32,6 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; @@ -193,7 +192,7 @@ public class SurfaceAnimator { return; } mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback); - if (ProtoLogImpl.isEnabled(WM_DEBUG_ANIM)) { + if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mAnimation.dump(pw, ""); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2bee095e7f46..1353ff09b292 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3750,8 +3750,7 @@ class Task extends TaskFragment { // Boost the adjacent TaskFragment for dimmer if needed. final TaskFragment taskFragment = wc.asTaskFragment(); - if (taskFragment != null && taskFragment.isEmbedded() - && taskFragment.isVisibleRequested()) { + if (taskFragment != null && taskFragment.isEmbedded()) { final TaskFragment adjacentTf = taskFragment.getAdjacentTaskFragment(); if (adjacentTf != null && adjacentTf.shouldBoostDimmer()) { adjacentTf.assignLayer(t, layer++); diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 10cbc6633533..85d81c4db2ca 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -104,6 +104,7 @@ import android.window.TaskFragmentOrganizerToken; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.internal.util.ToBooleanFunction; import com.android.server.am.HostingRecord; import com.android.server.pm.pkg.AndroidPackage; import com.android.window.flags.Flags; @@ -3025,11 +3026,17 @@ class TaskFragment extends WindowContainer<WindowContainer> { return false; } - // boost if there's an Activity window that has FLAG_DIM_BEHIND flag. - return forAllWindows( + ToBooleanFunction<WindowState> getDimBehindWindow = (w) -> (w.mAttrs.flags & FLAG_DIM_BEHIND) != 0 && w.mActivityRecord != null && w.mActivityRecord.isEmbedded() && (w.mActivityRecord.isVisibleRequested() - || w.mActivityRecord.isVisible()), true); + || w.mActivityRecord.isVisible()); + if (adjacentTf.forAllWindows(getDimBehindWindow, true)) { + // early return if the adjacent Tf has a dimming window. + return false; + } + + // boost if there's an Activity window that has FLAG_DIM_BEHIND flag. + return forAllWindows(getDimBehindWindow, true); } @Override diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 8d054db8994a..24b533a23af6 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -1197,16 +1197,13 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr } } - // TODO(b/204399167): change to push the embedded state to the client side @Override public boolean isActivityEmbedded(IBinder activityToken) { synchronized (mGlobalLock) { final ActivityRecord activity = ActivityRecord.forTokenLocked(activityToken); - if (activity == null) { - return false; - } - final TaskFragment taskFragment = activity.getOrganizedTaskFragment(); - return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride(); + return activity != null + ? activity.isEmbeddedInHostContainer() + : false; } } diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java index 5ec0119725cb..d89dc0b8e81c 100644 --- a/services/core/java/com/android/server/wm/TaskPersister.java +++ b/services/core/java/com/android/server/wm/TaskPersister.java @@ -27,6 +27,7 @@ import android.os.FileUtils; import android.os.SystemClock; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -43,20 +44,20 @@ import org.xmlpull.v1.XmlPullParser; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.List; /** * Persister that saves recent tasks into disk. @@ -129,11 +130,9 @@ public class TaskPersister implements PersisterQueue.Listener { ImageWriteQueueItem.class); } + /** Reads task ids from file. This should not be called in lock. */ @NonNull - SparseBooleanArray loadPersistedTaskIdsForUser(int userId) { - if (mTaskIdsInFile.get(userId) != null) { - return mTaskIdsInFile.get(userId).clone(); - } + SparseBooleanArray readPersistedTaskIdsFromFileForUser(int userId) { final SparseBooleanArray persistedTaskIds = new SparseBooleanArray(); synchronized (mIoLock) { BufferedReader reader = null; @@ -154,11 +153,10 @@ public class TaskPersister implements PersisterQueue.Listener { IoUtils.closeQuietly(reader); } } - mTaskIdsInFile.put(userId, persistedTaskIds); - return persistedTaskIds.clone(); + Slog.i(TAG, "Loaded persisted task ids for user " + userId); + return persistedTaskIds; } - @VisibleForTesting void writePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds, int userId) { if (userId < 0) { @@ -183,6 +181,10 @@ public class TaskPersister implements PersisterQueue.Listener { } } + void setPersistedTaskIds(int userId, @NonNull SparseBooleanArray taskIds) { + mTaskIdsInFile.put(userId, taskIds); + } + void unloadUserDataFromMemory(int userId) { mTaskIdsInFile.delete(userId); } @@ -241,7 +243,7 @@ public class TaskPersister implements PersisterQueue.Listener { return item != null ? item.mImage : null; } - private String fileToString(File file) { + private static String fileToString(File file) { final String newline = System.lineSeparator(); try { BufferedReader reader = new BufferedReader(new FileReader(file)); @@ -272,44 +274,64 @@ public class TaskPersister implements PersisterQueue.Listener { return null; } - List<Task> restoreTasksForUserLocked(final int userId, SparseBooleanArray preaddedTasks) { - final ArrayList<Task> tasks = new ArrayList<Task>(); - ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>(); - - File userTasksDir = getUserTasksDir(userId); - - File[] recentFiles = userTasksDir.listFiles(); + /** Loads task files from disk. This should not be called in lock. */ + static RecentTaskFiles loadTasksForUser(int userId) { + final ArrayList<RecentTaskFile> taskFiles = new ArrayList<>(); + final File userTasksDir = getUserTasksDir(userId); + final File[] recentFiles = userTasksDir.listFiles(); if (recentFiles == null) { - Slog.e(TAG, "restoreTasksForUserLocked: Unable to list files from " + userTasksDir); - return tasks; + Slog.i(TAG, "loadTasksForUser: Unable to list files from " + userTasksDir + + " exists=" + userTasksDir.exists()); + return new RecentTaskFiles(new File[0], taskFiles); } - - for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) { - File taskFile = recentFiles[taskNdx]; - if (DEBUG) { - Slog.d(TAG, "restoreTasksForUserLocked: userId=" + userId - + ", taskFile=" + taskFile.getName()); - } - + for (File taskFile : recentFiles) { if (!taskFile.getName().endsWith(TASK_FILENAME_SUFFIX)) { continue; } + final int taskId; try { - final int taskId = Integer.parseInt(taskFile.getName().substring( + taskId = Integer.parseInt(taskFile.getName().substring( 0 /* beginIndex */, taskFile.getName().length() - TASK_FILENAME_SUFFIX.length())); - if (preaddedTasks.get(taskId, false)) { - Slog.w(TAG, "Task #" + taskId + - " has already been created so we don't restore again"); - continue; - } } catch (NumberFormatException e) { Slog.w(TAG, "Unexpected task file name", e); continue; } + try { + taskFiles.add(new RecentTaskFile(taskId, taskFile)); + } catch (IOException e) { + Slog.w(TAG, "Failed to read file: " + fileToString(taskFile), e); + taskFile.delete(); + } + } + return new RecentTaskFiles(recentFiles, taskFiles); + } + + /** Restores tasks from raw bytes (no read storage operation). */ + ArrayList<Task> restoreTasksForUserLocked(int userId, RecentTaskFiles recentTaskFiles, + IntArray existedTaskIds) { + final ArrayList<Task> tasks = new ArrayList<>(); + final ArrayList<RecentTaskFile> taskFiles = recentTaskFiles.mLoadedFiles; + if (taskFiles.isEmpty()) { + return tasks; + } + + final ArraySet<Integer> recoveredTaskIds = new ArraySet<>(); + for (int taskNdx = 0; taskNdx < taskFiles.size(); ++taskNdx) { + final RecentTaskFile recentTask = taskFiles.get(taskNdx); + if (existedTaskIds.contains(recentTask.mTaskId)) { + Slog.w(TAG, "Task #" + recentTask.mTaskId + + " has already been created, so skip restoring"); + continue; + } + final File taskFile = recentTask.mFile; + if (DEBUG) { + Slog.d(TAG, "restoreTasksForUserLocked: userId=" + userId + + ", taskFile=" + taskFile.getName()); + } boolean deleteFile = false; - try (InputStream is = new FileInputStream(taskFile)) { + try (InputStream is = recentTask.mXmlContent) { final TypedXmlPullParser in = Xml.resolvePullParser(is); int event; @@ -345,7 +367,7 @@ public class TaskPersister implements PersisterQueue.Listener { } else if (userId != task.mUserId) { // Should not happen. Slog.wtf(TAG, "Task with userId " + task.mUserId + " found in " - + userTasksDir.getAbsolutePath()); + + taskFile.getAbsolutePath()); } else { // Looks fine. mTaskSupervisor.setNextTaskIdForUser(taskId, userId); @@ -377,7 +399,7 @@ public class TaskPersister implements PersisterQueue.Listener { } if (!DEBUG) { - removeObsoleteFiles(recoveredTaskIds, userTasksDir.listFiles()); + removeObsoleteFiles(recoveredTaskIds, recentTaskFiles.mUserTaskFiles); } // Fix up task affiliation from taskIds @@ -456,7 +478,7 @@ public class TaskPersister implements PersisterQueue.Listener { SparseArray<SparseBooleanArray> changedTaskIdsPerUser = new SparseArray<>(); synchronized (mService.mGlobalLock) { for (int userId : mRecentTasks.usersWithRecentsLoadedLocked()) { - SparseBooleanArray taskIdsToSave = mRecentTasks.getTaskIdsForUser(userId); + SparseBooleanArray taskIdsToSave = mRecentTasks.getTaskIdsForLoadedUser(userId); SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId); if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIdsToSave)) { continue; @@ -512,6 +534,30 @@ public class TaskPersister implements PersisterQueue.Listener { return parentDir.isDirectory() || parentDir.mkdir(); } + private static class RecentTaskFile { + final int mTaskId; + final File mFile; + final ByteArrayInputStream mXmlContent; + + RecentTaskFile(int taskId, File file) throws IOException { + mTaskId = taskId; + mFile = file; + mXmlContent = new ByteArrayInputStream(Files.readAllBytes(file.toPath())); + } + } + + static class RecentTaskFiles { + /** All files under the user task directory. */ + final File[] mUserTaskFiles; + /** The successfully loaded files. */ + final ArrayList<RecentTaskFile> mLoadedFiles; + + RecentTaskFiles(File[] userFiles, ArrayList<RecentTaskFile> loadedFiles) { + mUserTaskFiles = userFiles; + mLoadedFiles = loadedFiles; + } + } + private static class TaskWriteQueueItem implements PersisterQueue.WriteQueueItem { private final ActivityTaskManagerService mService; private final Task mTask; diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 001f46d4c36c..594043d380c9 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -58,7 +58,6 @@ import android.window.ScreenCapture; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.wallpaper.WallpaperCropper.WallpaperCropUtils; @@ -336,7 +335,7 @@ class WallpaperController { for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) { final WallpaperWindowToken token = mWallpaperTokens.get(i); token.setVisibility(false); - if (ProtoLogImpl.isEnabled(WM_DEBUG_WALLPAPER) && token.isVisible()) { + if (ProtoLog.isEnabled(WM_DEBUG_WALLPAPER) && token.isVisible()) { ProtoLog.d(WM_DEBUG_WALLPAPER, "Hiding wallpaper %s from %s target=%s prev=%s callers=%s", token, winGoingAway, mWallpaperTarget, mPrevWallpaperTarget, diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 61fde5e31e8f..fd0289edc84b 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -113,7 +113,6 @@ import android.window.WindowContainerToken; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.wm.SurfaceAnimator.Animatable; @@ -3410,7 +3409,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition. a.restrictDuration(MAX_APP_TRANSITION_DURATION); } - if (ProtoLogImpl.isEnabled(WM_DEBUG_ANIM)) { + if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) { ProtoLog.i(WM_DEBUG_ANIM, "Loaded animation %s for %s, duration: %d, stack=%s", a, this, ((a != null) ? a.getDuration() : 0), Debug.getCallers(20)); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 9b7bc4383e0c..08d43ae6f4c9 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -327,8 +327,8 @@ import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IKeyguardLockedStateListener; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyInterceptionInfo; +import com.android.internal.protolog.LegacyProtoLogImpl; import com.android.internal.protolog.ProtoLogGroup; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; @@ -6701,7 +6701,11 @@ public class WindowManagerService extends IWindowManager.Stub private void dumpLogStatus(PrintWriter pw) { pw.println("WINDOW MANAGER LOGGING (dumpsys window logging)"); - pw.println(ProtoLogImpl.getSingleInstance().getStatus()); + if (android.tracing.Flags.perfettoProtolog()) { + pw.println("Deprecated legacy command. Use Perfetto commands instead."); + return; + } + ((LegacyProtoLogImpl) ProtoLog.getSingleInstance()).getStatus(); } private void dumpSessionsLocked(PrintWriter pw) { diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 8fad9509af44..0b29f9688acd 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -48,7 +48,9 @@ import android.view.IWindowManager; import android.view.ViewDebug; import com.android.internal.os.ByteTransferPipe; -import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.LegacyProtoLogImpl; +import com.android.internal.protolog.common.IProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.IoThread; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import com.android.server.wm.LetterboxConfiguration.LetterboxHorizontalReachabilityPosition; @@ -107,11 +109,19 @@ public class WindowManagerShellCommand extends ShellCommand { // trace files can be written. return mInternal.mWindowTracing.onShellCommand(this); case "logging": - int result = ProtoLogImpl.getSingleInstance().onShellCommand(this); - if (result != 0) { - pw.println("Not handled, please use " - + "`adb shell dumpsys activity service SystemUIService WMShell` " - + "if you are looking for ProtoLog in WMShell"); + IProtoLog instance = ProtoLog.getSingleInstance(); + int result = 0; + if (instance instanceof LegacyProtoLogImpl) { + result = ((LegacyProtoLogImpl) instance).onShellCommand(this); + if (result != 0) { + pw.println("Not handled, please use " + + "`adb shell dumpsys activity service SystemUIService " + + "WMShell` if you are looking for ProtoLog in WMShell"); + } + } else { + result = -1; + pw.println("Command not supported. " + + "Only supported when using legacy ProtoLog."); } return result; case "user-rotation": diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 90f5b62b4a08..a7a28c282ff9 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -245,7 +245,6 @@ import android.window.OnBackInvokedCallbackInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.KeyInterceptionInfo; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ToBooleanFunction; @@ -4681,7 +4680,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } void onExitAnimationDone() { - if (ProtoLogImpl.isEnabled(WM_DEBUG_ANIM)) { + if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) { final AnimationAdapter animationAdapter = mSurfaceAnimator.getAnimation(); StringWriter sw = new StringWriter(); if (animationAdapter != null) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 6428591d8b8d..7f7c2493cd68 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -60,7 +60,6 @@ import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; @@ -584,7 +583,7 @@ class WindowStateAnimator { mWin.mAttrs, attr, TRANSIT_OLD_NONE); } } - if (ProtoLogImpl.isEnabled(WM_DEBUG_ANIM)) { + if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) { ProtoLog.v(WM_DEBUG_ANIM, "applyAnimation: win=%s" + " anim=%d attr=0x%x a=%s transit=%d type=%d isEntrance=%b Callers %s", this, anim, attr, a, transit, mAttrType, isEntrance, Debug.getCallers(20)); diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java index 416d0427a0d6..424d50434010 100644 --- a/services/core/java/com/android/server/wm/WindowTracing.java +++ b/services/core/java/com/android/server/wm/WindowTracing.java @@ -35,7 +35,9 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.Choreographer; -import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.LegacyProtoLogImpl; +import com.android.internal.protolog.common.IProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.TraceBuffer; import java.io.File; @@ -77,6 +79,8 @@ class WindowTracing { private volatile boolean mEnabledLockFree; private boolean mScheduled; + private final IProtoLog mProtoLog; + static WindowTracing createDefaultAndStartLooper(WindowManagerService service, Choreographer choreographer) { File file = new File(TRACE_FILENAME); @@ -96,6 +100,7 @@ class WindowTracing { mTraceFile = file; mBuffer = new TraceBuffer(bufferCapacity); setLogLevel(WindowTraceLogLevel.TRIM, null /* pw */); + mProtoLog = ProtoLog.getSingleInstance(); } void startTrace(@Nullable PrintWriter pw) { @@ -104,7 +109,6 @@ class WindowTracing { return; } synchronized (mEnabledLock) { - ProtoLogImpl.getSingleInstance().startProtoLog(pw); logAndPrintln(pw, "Start tracing to " + mTraceFile + "."); mBuffer.resetBuffer(); mEnabled = mEnabledLockFree = true; @@ -132,7 +136,6 @@ class WindowTracing { writeTraceToFileLocked(); logAndPrintln(pw, "Trace written to " + mTraceFile + "."); } - ProtoLogImpl.getSingleInstance().stopProtoLog(pw, true); } /** @@ -152,11 +155,15 @@ class WindowTracing { logAndPrintln(pw, "Stop tracing to " + mTraceFile + ". Waiting for traces to flush."); writeTraceToFileLocked(); logAndPrintln(pw, "Trace written to " + mTraceFile + "."); - ProtoLogImpl.getSingleInstance().stopProtoLog(pw, true); + if (!android.tracing.Flags.perfettoProtolog()) { + ((LegacyProtoLogImpl) mProtoLog).stopProtoLog(pw, true); + } logAndPrintln(pw, "Start tracing to " + mTraceFile + "."); mBuffer.resetBuffer(); mEnabled = mEnabledLockFree = true; - ProtoLogImpl.getSingleInstance().startProtoLog(pw); + if (!android.tracing.Flags.perfettoProtolog()) { + ((LegacyProtoLogImpl) mProtoLog).startProtoLog(pw); + } } } diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index f5e6c45c75b8..f47a59d6cec9 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -370,6 +370,7 @@ static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr, return JNI_FALSE; } vibrator::Info info = wrapper->getVibratorInfo(); + info.logFailures(); if (info.capabilities.isOk()) { env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setCapabilities, @@ -443,7 +444,7 @@ static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr, env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyProfile, frequencyProfile); - return info.isFailedLogged("vibratorGetInfo") ? JNI_FALSE : JNI_TRUE; + return info.shouldRetry() ? JNI_FALSE : JNI_TRUE; } static const JNINativeMethod method_table[] = { diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index a46916553abc..b38a2f9558e9 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -117,6 +117,9 @@ <xs:element type="sensorDetails" name="proxSensor"> <xs:annotation name="final"/> </xs:element> + <xs:element type="sensorDetails" name="tempSensor"> + <xs:annotation name="final"/> + </xs:element> <!-- Length of the ambient light horizon used to calculate the long & short term estimates of ambient light in milliseconds.--> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index 79ea274e2fca..b329db4a2076 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -133,6 +133,7 @@ package com.android.server.display.config { method public final java.math.BigDecimal getScreenBrightnessRampSlowIncreaseIdle(); method public final com.android.server.display.config.SensorDetails getScreenOffBrightnessSensor(); method public final com.android.server.display.config.IntegerArray getScreenOffBrightnessSensorValueToLux(); + method public final com.android.server.display.config.SensorDetails getTempSensor(); method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling(); method public final com.android.server.display.config.UsiVersion getUsiVersion(); method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds); @@ -167,6 +168,7 @@ package com.android.server.display.config { method public final void setScreenBrightnessRampSlowIncreaseIdle(java.math.BigDecimal); method public final void setScreenOffBrightnessSensor(com.android.server.display.config.SensorDetails); method public final void setScreenOffBrightnessSensorValueToLux(com.android.server.display.config.IntegerArray); + method public final void setTempSensor(com.android.server.display.config.SensorDetails); method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling); method public final void setUsiVersion(com.android.server.display.config.UsiVersion); } diff --git a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java index 723c52f37574..ca72638fd0ff 100644 --- a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java @@ -150,7 +150,8 @@ public class GetCandidateRequestSession extends RequestSession<GetCredentialRequ @Override public void onFinalErrorReceived(ComponentName componentName, String errorType, String message) { - respondToClientWithErrorAndFinish(errorType, message); + Slog.d(TAG, "onFinalErrorReceived"); + respondToFinalReceiverWithFailureAndFinish(this.mFinalResponseReceiver, errorType, message); } @Override @@ -163,6 +164,13 @@ public class GetCandidateRequestSession extends RequestSession<GetCredentialRequ message = "The UI was interrupted - please try again."; } mRequestSessionMetric.collectFrameworkException(exception); + respondToFinalReceiverWithFailureAndFinish(finalResponseReceiver, exception, message); + } + + private void respondToFinalReceiverWithFailureAndFinish( + ResultReceiver finalResponseReceiver, + String exception, String message + ) { if (finalResponseReceiver != null) { Bundle resultData = new Bundle(); resultData.putStringArray( @@ -170,16 +178,16 @@ public class GetCandidateRequestSession extends RequestSession<GetCredentialRequ new String[] {exception, message}); finalResponseReceiver.send(Constants.FAILURE_CREDMAN_SELECTOR, resultData); } else { - respondToClientWithErrorAndFinish(exception, message); + Slog.w(TAG, "onUiCancellation called but finalResponseReceiver not found"); } + finishSession(/*propagateCancellation=*/false); } @Override public void onUiSelectorInvocationFailure() { String exception = GetCandidateCredentialsException.TYPE_NO_CREDENTIAL; mRequestSessionMetric.collectFrameworkException(exception); - respondToClientWithErrorAndFinish(exception, - "No credentials available."); + // TODO(): Propagate through final receiver } @Override diff --git a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java index 21ac9e44de65..bc8c2b07f427 100644 --- a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java +++ b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java @@ -82,7 +82,7 @@ public class PendingIntentResultHandler { if (resultData == null) { return null; } - return resultData.getParcelableExtra( + return resultData.getSerializableExtra( CredentialProviderService.EXTRA_CREATE_CREDENTIAL_EXCEPTION, CreateCredentialException.class); } @@ -94,7 +94,7 @@ public class PendingIntentResultHandler { if (resultData == null) { return null; } - return resultData.getParcelableExtra( + return resultData.getSerializableExtra( CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION, GetCredentialException.class); } diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java index ca23d62601bb..fa63bc899cb5 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java @@ -30,9 +30,7 @@ import android.credentials.selection.AuthenticationEntry; import android.credentials.selection.Entry; import android.credentials.selection.GetCredentialProviderData; import android.credentials.selection.ProviderPendingIntentResponse; -import android.os.Bundle; import android.os.ICancellationSignal; -import android.service.autofill.Flags; import android.service.credentials.Action; import android.service.credentials.BeginGetCredentialOption; import android.service.credentials.BeginGetCredentialRequest; @@ -44,7 +42,6 @@ import android.service.credentials.GetCredentialRequest; import android.service.credentials.RemoteEntry; import android.util.Pair; import android.util.Slog; -import android.view.autofill.AutofillId; import java.util.ArrayList; import java.util.HashMap; @@ -77,10 +74,6 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential @NonNull private final Map<String, CredentialOption> mBeginGetOptionToCredentialOptionMap; - @NonNull - private final Map<String, AutofillId> mCredentialEntryKeyToAutofilLIdMap; - - /** The complete request to be used in the second round. */ private final android.credentials.GetCredentialRequest mCompleteRequest; private final CallingAppInfo mCallingAppInfo; @@ -249,7 +242,6 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential mBeginGetOptionToCredentialOptionMap = new HashMap<>(beginGetOptionToCredentialOptionMap); mProviderResponseDataHandler = new ProviderResponseDataHandler( ComponentName.unflattenFromString(hybridService)); - mCredentialEntryKeyToAutofilLIdMap = new HashMap<>(); } /** Called when the provider response has been updated by an external source. */ @@ -303,7 +295,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential invokeCallbackOnInternalInvalidState(); return; } - onCredentialEntrySelected(providerPendingIntentResponse, entryKey); + onCredentialEntrySelected(providerPendingIntentResponse); break; case ACTION_ENTRY_KEY: Action actionEntry = mProviderResponseDataHandler.getActionEntry(entryKey); @@ -312,7 +304,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential invokeCallbackOnInternalInvalidState(); return; } - onActionEntrySelected(providerPendingIntentResponse, entryKey); + onActionEntrySelected(providerPendingIntentResponse); break; case AUTHENTICATION_ACTION_ENTRY_KEY: Action authenticationEntry = mProviderResponseDataHandler @@ -342,7 +334,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential break; case REMOTE_ENTRY_KEY: if (mProviderResponseDataHandler.getRemoteEntry(entryKey) != null) { - onRemoteEntrySelected(providerPendingIntentResponse, entryKey); + onRemoteEntrySelected(providerPendingIntentResponse); } else { Slog.i(TAG, "Unexpected remote entry key"); invokeCallbackOnInternalInvalidState(); @@ -381,7 +373,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential return null; } - private Intent setUpFillInIntentWithFinalRequest(@NonNull String id, String entryKey) { + private Intent setUpFillInIntentWithFinalRequest(@NonNull String id) { // TODO: Determine if we should skip this entry if entry id is not set, or is set // but does not resolve to a valid option. For now, not skipping it because // it may be possible that the provider adds their own extras and expects to receive @@ -392,13 +384,6 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential Slog.w(TAG, "Id from Credential Entry does not resolve to a valid option"); return intent; } - AutofillId autofillId = credentialOption - .getCandidateQueryData() - .getParcelable(CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class); - if (autofillId != null && Flags.autofillCredmanIntegration()) { - intent.putExtra(CredentialProviderService.EXTRA_AUTOFILL_ID, autofillId); - mCredentialEntryKeyToAutofilLIdMap.put(entryKey, autofillId); - } return intent.putExtra( CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST, new GetCredentialRequest( @@ -414,13 +399,12 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential } private void onRemoteEntrySelected( - ProviderPendingIntentResponse providerPendingIntentResponse, String entryKey) { - onCredentialEntrySelected(providerPendingIntentResponse, entryKey); + ProviderPendingIntentResponse providerPendingIntentResponse) { + onCredentialEntrySelected(providerPendingIntentResponse); } private void onCredentialEntrySelected( - ProviderPendingIntentResponse providerPendingIntentResponse, - String entryKey) { + ProviderPendingIntentResponse providerPendingIntentResponse) { if (providerPendingIntentResponse == null) { invokeCallbackOnInternalInvalidState(); return; @@ -437,18 +421,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential GetCredentialResponse getCredentialResponse = PendingIntentResultHandler .extractGetCredentialResponse( providerPendingIntentResponse.getResultData()); - if (getCredentialResponse != null && getCredentialResponse.getCredential() != null) { - Bundle credentialData = getCredentialResponse.getCredential().getData(); - AutofillId autofillId = mCredentialEntryKeyToAutofilLIdMap.get(entryKey); - if (Flags.autofillCredmanIntegration() - && entryKey != null && autofillId != null && credentialData != null - ) { - Slog.d(TAG, "Adding autofillId to credential response: " + autofillId); - credentialData.putParcelable( - CredentialProviderService.EXTRA_AUTOFILL_ID, - mCredentialEntryKeyToAutofilLIdMap.get(entryKey) - ); - } + if (getCredentialResponse != null) { mCallbacks.onFinalResponseReceived(mComponentName, getCredentialResponse); return; @@ -532,9 +505,9 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential /** Returns true if either an exception or a response is found. */ private void onActionEntrySelected(ProviderPendingIntentResponse - providerPendingIntentResponse, String entryKey) { + providerPendingIntentResponse) { Slog.i(TAG, "onActionEntrySelected"); - onCredentialEntrySelected(providerPendingIntentResponse, entryKey); + onCredentialEntrySelected(providerPendingIntentResponse); } @@ -632,7 +605,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential Entry entry = new Entry(CREDENTIAL_ENTRY_KEY, id, credentialEntry.getSlice(), setUpFillInIntentWithFinalRequest(credentialEntry - .getBeginGetCredentialOptionId(), id)); + .getBeginGetCredentialOptionId())); mUiCredentialEntries.put(id, new Pair<>(credentialEntry, entry)); mCredentialEntryTypes.add(credentialEntry.getType()); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java index e7855bc85061..c4e2dc802104 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java @@ -15,6 +15,10 @@ */ package com.android.server.devicepolicy; +import static android.app.admin.DevicePolicyManager.CONTENT_PROTECTION_DISABLED; +import static android.app.admin.DevicePolicyManager.ContentProtectionPolicy; + +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyManager; @@ -70,10 +74,14 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */ private final AtomicBoolean mCanGrantSensorsPermissions = new AtomicBoolean(false); + @GuardedBy("mLock") + private final SparseIntArray mContentProtectionPolicy = new SparseIntArray(); + public void onUserRemoved(int userHandle) { synchronized (mLock) { mPasswordQuality.delete(userHandle); mPermissionPolicy.delete(userHandle); + mContentProtectionPolicy.delete(userHandle); } } @@ -143,6 +151,24 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { } @Override + public @ContentProtectionPolicy int getContentProtectionPolicy(@UserIdInt int userId) { + synchronized (mLock) { + return mContentProtectionPolicy.get(userId, CONTENT_PROTECTION_DISABLED); + } + } + + /** Update the content protection policy for the given user. */ + public void setContentProtectionPolicy(@UserIdInt int userId, @Nullable Integer value) { + synchronized (mLock) { + if (value == null) { + mContentProtectionPolicy.delete(userId); + } else { + mContentProtectionPolicy.put(userId, value); + } + } + } + + @Override public boolean canAdminGrantSensorsPermissions() { return mCanGrantSensorsPermissions.get(); } @@ -178,6 +204,7 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { pw.println("Screen capture disallowed users: " + mScreenCaptureDisallowedUsers); pw.println("Password quality: " + mPasswordQuality); pw.println("Permission policy: " + mPermissionPolicy); + pw.println("Content protection policy: " + mContentProtectionPolicy); pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get()); pw.print("Shortcuts overrides: "); pw.println(mLauncherShortcutOverrides); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 9c48f2991267..0f97f4a7cdc0 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3633,6 +3633,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { userId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : userId); updatePermissionPolicyCache(userId); updateAdminCanGrantSensorsPermissionCache(userId); + updateContentProtectionPolicyCache(userId); final List<PreferentialNetworkServiceConfig> preferentialNetworkServiceConfigs; synchronized (getLockObject()) { @@ -23534,6 +23535,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void updateContentProtectionPolicyCache(@UserIdInt int userId) { + mPolicyCache.setContentProtectionPolicy( + userId, + mDevicePolicyEngine.getResolvedPolicy(PolicyDefinition.CONTENT_PROTECTION, userId)); + } + @Override public ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy() { synchronized (getLockObject()) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 1247f900260a..71facab99fce 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -359,7 +359,7 @@ final class PolicyDefinition<V> { new NoArgsPolicyKey(DevicePolicyIdentifiers.CONTENT_PROTECTION_POLICY), new MostRecent<>(), POLICY_FLAG_LOCAL_ONLY_POLICY, - (Integer value, Context context, Integer userId, PolicyKey policyKey) -> true, + PolicyEnforcerCallbacks::setContentProtectionPolicy, new IntegerPolicySerializer()); private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java index 54242ab279b0..c108deaf33bc 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java @@ -18,6 +18,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyManager; @@ -282,6 +283,21 @@ final class PolicyEnforcerCallbacks { return true; } + static boolean setContentProtectionPolicy( + @Nullable Integer value, + @NonNull Context context, + @UserIdInt Integer userId, + @NonNull PolicyKey policyKey) { + Binder.withCleanCallingIdentity( + () -> { + DevicePolicyCache cache = DevicePolicyCache.getInstance(); + if (cache instanceof DevicePolicyCacheImpl cacheImpl) { + cacheImpl.setContentProtectionPolicy(userId, value); + } + }); + return true; + } + private static void updateScreenCaptureDisabled() { BackgroundThread.getHandler().post(() -> { try { diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java index a212812b0768..c16c61271280 100644 --- a/services/midi/java/com/android/server/midi/MidiService.java +++ b/services/midi/java/com/android/server/midi/MidiService.java @@ -1012,7 +1012,11 @@ public class MidiService extends IMidiManager.Stub { } } - if (user.getUserIdentifier() == mUserManager.getMainUser().getIdentifier()) { + // Allow only the main user to create BluetoothMidiService. + // If there is no main user, allow all users to create it. + UserHandle mainUser = mUserManager.getMainUser(); + if ((mainUser == null) + || (user.getUserIdentifier() == mainUser.getIdentifier())) { PackageInfo info; try { info = mPackageManager.getPackageInfoAsUser( diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp index afd6dbd7f6a7..3bce9b54e320 100644 --- a/services/tests/InputMethodSystemServerTests/Android.bp +++ b/services/tests/InputMethodSystemServerTests/Android.bp @@ -69,7 +69,7 @@ android_test { } android_ravenwood_test { - name: "FrameworksInputMethodSystemServerTests_host", + name: "FrameworksInputMethodSystemServerTestsRavenwood", static_libs: [ "androidx.annotation_annotation", "androidx.test.rules", @@ -85,7 +85,6 @@ android_ravenwood_test { srcs: [ "src/com/android/server/inputmethod/**/ClientControllerTest.java", ], - sdk_version: "test_current", auto_gen_config: true, } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java index dc9631a8f2e2..9e3d9ec6b9b6 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java @@ -32,10 +32,8 @@ import android.content.pm.PackageManagerInternal; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.platform.test.annotations.IgnoreUnderRavenwood; import android.platform.test.ravenwood.RavenwoodRule; import android.view.Display; -import android.view.inputmethod.InputBinding; import com.android.internal.inputmethod.IInputMethodClient; import com.android.internal.inputmethod.IRemoteInputConnection; @@ -53,7 +51,7 @@ import java.util.concurrent.TimeUnit; public final class ClientControllerTest { private static final int ANY_DISPLAY_ID = Display.DEFAULT_DISPLAY; private static final int ANY_CALLER_UID = 1; - private static final int ANY_CALLER_PID = 1; + private static final int ANY_CALLER_PID = 2; private static final String SOME_PACKAGE_NAME = "some.package"; @Rule @@ -82,13 +80,16 @@ public final class ClientControllerTest { mController = new ClientController(mMockPackageManagerInternal); } + // TODO(b/322895594): No need to directly invoke create$ravenwood once b/322895594 is fixed. + private IInputMethodClientInvoker createInvoker(IInputMethodClient client, Handler handler) { + return RavenwoodRule.isOnRavenwood() + ? IInputMethodClientInvoker.create$ravenwood(client, handler) : + IInputMethodClientInvoker.create(client, handler); + } + @Test - // TODO(b/314150112): Enable host side mode for this test once Ravenwood is enabled for - // inputmethod server classes. - @IgnoreUnderRavenwood(blockedBy = {InputBinding.class, IInputMethodClientInvoker.class}) public void testAddClient_cannotAddTheSameClientTwice() { - var invoker = IInputMethodClientInvoker.create(mClient, mHandler); - + final var invoker = createInvoker(mClient, mHandler); synchronized (ImfLock.class) { mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID, ANY_CALLER_PID); @@ -101,18 +102,17 @@ public final class ClientControllerTest { } }); assertThat(thrown.getMessage()).isEqualTo( - "uid=1/pid=1/displayId=0 is already registered"); + "uid=" + ANY_CALLER_UID + "/pid=" + ANY_CALLER_PID + + "/displayId=0 is already registered"); } } @Test - // TODO(b/314150112): Enable host side mode for this test once Ravenwood is enabled for - // inputmethod server classes. - @IgnoreUnderRavenwood(blockedBy = {InputBinding.class, IInputMethodClientInvoker.class}) public void testAddClient() throws Exception { + final var invoker = createInvoker(mClient, mHandler); synchronized (ImfLock.class) { - var invoker = IInputMethodClientInvoker.create(mClient, mHandler); - var added = mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID, + final var added = mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, + ANY_CALLER_UID, ANY_CALLER_PID); verify(invoker.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0)); @@ -121,16 +121,12 @@ public final class ClientControllerTest { } @Test - // TODO(b/314150112): Enable host side mode for this test once Ravenwood is enabled for - // inputmethod server classes. - @IgnoreUnderRavenwood(blockedBy = {InputBinding.class, IInputMethodClientInvoker.class}) public void testRemoveClient() { - var callback = new TestClientControllerCallback(); + final var invoker = createInvoker(mClient, mHandler); + final var callback = new TestClientControllerCallback(); ClientState added; synchronized (ImfLock.class) { mController.addClientControllerCallback(callback); - - var invoker = IInputMethodClientInvoker.create(mClient, mHandler); added = mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID, ANY_CALLER_PID); assertThat(mController.getClient(invoker.asBinder())).isSameInstanceAs(added); @@ -138,21 +134,17 @@ public final class ClientControllerTest { } // Test callback - var removed = callback.waitForRemovedClient(5, TimeUnit.SECONDS); + final var removed = callback.waitForRemovedClient(5, TimeUnit.SECONDS); assertThat(removed).isSameInstanceAs(added); } @Test - // TODO(b/314150112): Enable host side mode for this test once Ravenwood is enabled for - // inputmethod server classes and updated to newer Mockito with static mock support (mock - // InputMethodUtils#checkIfPackageBelongsToUid instead of PackageManagerInternal#isSameApp) - @IgnoreUnderRavenwood(blockedBy = {InputMethodUtils.class}) public void testVerifyClientAndPackageMatch() { + final var invoker = createInvoker(mClient, mHandler); when(mMockPackageManagerInternal.isSameApp(eq(SOME_PACKAGE_NAME), /* flags= */ anyLong(), eq(ANY_CALLER_UID), /* userId= */ anyInt())).thenReturn(true); synchronized (ImfLock.class) { - var invoker = IInputMethodClientInvoker.create(mClient, mHandler); mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID, ANY_CALLER_PID); assertThat( diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp b/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp new file mode 100644 index 000000000000..39ef50112cba --- /dev/null +++ b/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp @@ -0,0 +1,38 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_team: "trendy_team_framework_android_packages", + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "PreVerifiedDomainsTests", + srcs: [ + "src/**/*.kt", + ], + static_libs: [ + "compatibility-device-util-axt", + "androidx.test.runner", + "truth", + ], + platform_apis: true, + certificate: "platform", + test_suites: ["device-tests"], +} diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml new file mode 100644 index 000000000000..ad731fc1a61c --- /dev/null +++ b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.android.server.pm.test.preverifieddomains"> + + <application android:label="PreVerified Domains Tests"> + <activity + android:name="com.android.server.pm.test.preverifieddomains.FakeInstantAppInstallerActivity" + android:enabled="true" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.INSTALL_INSTANT_APP_PACKAGE_TEST" /> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="file"/> + <data android:mimeType="application/vnd.android.package-archive"/> + </intent-filter> + </activity> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.server.pm.test.preverifieddomains" + android:label="Package Manager Service Tests for pre-verified domains"> + </instrumentation> + +</manifest> + diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml new file mode 100644 index 000000000000..45e193b03e36 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<configuration description="Runs Package Manager Service Pre-Verified Domains Tests."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="PreVerifiedDomainsTests.apk" /> + </target_preparer> + + <option name="test-tag" value="PreVerifiedDomainsTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.server.pm.test.preverifieddomains" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false" /> + </test> +</configuration> diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt new file mode 100644 index 000000000000..d330490516f4 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.pm.test.preverifieddomains + +import android.app.Activity + +class FakeInstantAppInstallerActivity : Activity() diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt new file mode 100644 index 000000000000..70432168ca5c --- /dev/null +++ b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.pm.test.preverifieddomains + +import android.app.UiAutomation +import android.content.ComponentName +import android.content.Context +import android.content.pm.Flags +import android.content.pm.PackageInstaller +import android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL +import android.content.pm.PackageManager +import android.os.Build +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.android.compatibility.common.util.DeviceConfigStateManager +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.AfterClass +import org.junit.Assert.assertThrows +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Rule +import org.junit.Test +import org.junit.function.ThrowingRunnable +import org.junit.runner.RunWith + +/** + * Pre-verified domains API tests. These tests require the device's default instant app + * installer to be disabled temporarily and is only able to run on ENG builds. + */ +@RunWith(AndroidJUnit4::class) +class PreVerifiedDomainsTests { + companion object { + private const val PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT = + "pre_verified_domains_count_limit" + private const val PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT = + "pre_verified_domain_length_limit" + private const val TEMP_COUNT_LIMIT = 10 + private const val TEMP_LENGTH_LIMIT = 15 + private val testDomains = setOf("com.foo", "com.bar") + + private val uiAutomation: UiAutomation = + InstrumentationRegistry.getInstrumentation().getUiAutomation() + private lateinit var packageManager: PackageManager + private var defaultInstantAppInstaller: ComponentName? = null + private lateinit var fakeInstantAppInstaller: ComponentName + + @JvmStatic + @BeforeClass + fun setupBeforeClass() { + val context = InstrumentationRegistry.getInstrumentation().getContext() + packageManager = context.packageManager + defaultInstantAppInstaller = packageManager.getInstantAppInstallerComponent() + fakeInstantAppInstaller = ComponentName( + context.packageName, + context.packageName + ".FakeInstantAppInstallerActivity") + // By disabling the original instant app installer, this test app becomes the instant + // app installer + uiAutomation.adoptShellPermissionIdentity() + try { + // Enable the fake instant app installer before disabling the default one + packageManager.setComponentEnabledSetting( + fakeInstantAppInstaller, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ) + if (defaultInstantAppInstaller != null) { + packageManager.setComponentEnabledSetting( + defaultInstantAppInstaller!!, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + 0 + ) + } + } finally { + uiAutomation.dropShellPermissionIdentity() + } + assertThat(fakeInstantAppInstaller).isEqualTo( + packageManager.getInstantAppInstallerComponent()) + } + + @JvmStatic + @AfterClass + fun restoreInstantAppInstaller() { + uiAutomation.adoptShellPermissionIdentity() + try { + // Enable the original instant app installer before disabling the temporary one, so + // there won't be a time when the device doesn't have a valid instant app installer + if (defaultInstantAppInstaller != null) { + packageManager.setComponentEnabledSetting( + defaultInstantAppInstaller!!, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + 0 + ) + } + // Be careful not to let this test process killed, or the test will be considered + // as failed + packageManager.setComponentEnabledSetting( + fakeInstantAppInstaller, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + ) + } finally { + uiAutomation.dropShellPermissionIdentity() + } + } + } + + private lateinit var packageInstaller: PackageInstaller + private lateinit var context: Context + private lateinit var packageManager: PackageManager + private var mDefaultCountLimit: String? = null + private var mDefaultLengthLimit: String? = null + + @JvmField + @Rule + val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + @Before + fun setUp() { + context = InstrumentationRegistry.getInstrumentation().getContext() + packageManager = context.packageManager + packageInstaller = packageManager.packageInstaller + mDefaultCountLimit = getLimitFromDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT) + mDefaultLengthLimit = getLimitFromDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT) + } + + @After + fun cleanUp() { + setLimitInDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT, mDefaultCountLimit) + setLimitInDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT, mDefaultLengthLimit) + } + + @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS) + @Test + fun testSetPreVerifiedDomainsExceedsCountLimit() { + // Temporarily change the count limit to a much smaller number so the test can exceed it + setLimitInDeviceConfig( + PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT, + TEMP_COUNT_LIMIT.toString() + ) + val domains = mutableSetOf<String>() + for (i in 0 until(TEMP_COUNT_LIMIT + 1)) { + domains.add("domain$i") + } + + uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS) + try { + assertThrows( + IllegalArgumentException::class.java, + ThrowingRunnable { + createSessionWithPreVerifiedDomains(domains) + } + ) + } finally { + uiAutomation.dropShellPermissionIdentity() + } + } + + @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS) + @Test + fun testSetPreVerifiedDomainsExceedsLengthLimit() { + // Temporarily change the count limit to a much smaller number so the test can exceed it + setLimitInDeviceConfig( + PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT, + TEMP_LENGTH_LIMIT.toString() + ) + val invalidDomain = "a".repeat(TEMP_LENGTH_LIMIT + 1) + + uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS) + try { + assertThrows( + "Pre-verified domain: [" + + invalidDomain + " ] exceeds maximum length allowed: " + + TEMP_LENGTH_LIMIT, + IllegalArgumentException::class.java, + ThrowingRunnable { + createSessionWithPreVerifiedDomains(setOf(invalidDomain)) + } + ) + } finally { + uiAutomation.dropShellPermissionIdentity() + } + } + + @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS) + @Test + fun testSetAndGetPreVerifiedDomains() { + // Fake instant app installers can only work on ENG builds + assumeTrue("eng" == Build.TYPE) + var session: PackageInstaller.Session? = null + uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS) + try { + val sessionId = createSessionWithPreVerifiedDomains(testDomains) + session = packageInstaller.openSession(sessionId) + assertThat(session.getPreVerifiedDomains()).isEqualTo(testDomains) + } finally { + uiAutomation.dropShellPermissionIdentity() + session?.abandon() + } + } + + private fun createSessionWithPreVerifiedDomains(domains: Set<String>): Int { + val sessionParam = PackageInstaller.SessionParams(MODE_FULL_INSTALL) + val sessionId = packageInstaller.createSession(sessionParam) + val session = packageInstaller.openSession(sessionId) + try { + session.setPreVerifiedDomains(domains) + } catch (e: Exception) { + session.abandon() + throw e + } + return sessionId + } + + private fun getLimitFromDeviceConfig(propertyName: String): String? { + val stateManager = DeviceConfigStateManager( + context, + NAMESPACE_PACKAGE_MANAGER_SERVICE, + propertyName + ) + return stateManager.get() + } + + private fun setLimitInDeviceConfig(propertyName: String, value: String?) { + val stateManager = DeviceConfigStateManager( + context, + NAMESPACE_PACKAGE_MANAGER_SERVICE, + propertyName + ) + val currentValue = stateManager.get() + if (currentValue != value) { + // Only change the value if the current value is different + stateManager.set(value) + } + } +} diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 418b78cd696b..9c9aeeaadb71 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -16,6 +16,7 @@ package com.android.server.display; +import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE; @@ -1016,4 +1017,34 @@ public class AutomaticBrightnessControllerTest { listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500)); assertEquals(500, mController.getAmbientLux(), EPSILON); } + + @Test + public void testBrightnessBasedOnLastObservedLux() throws Exception { + ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), + eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class)); + SensorEventListener listener = listenerCaptor.getValue(); + + // Set up system to return 0.3f as a brightness value + float lux = 100.0f; + // Brightness as float (from 0.0f to 1.0f) + float normalizedBrightness = 0.3f; + when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); + when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); + when(mBrightnessMappingStrategy.getBrightness(eq(lux), eq(null), anyInt())) + .thenReturn(normalizedBrightness); + when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessThrottler.isThrottled()).thenReturn(true); + + // Send a new sensor value, disable the sensor and verify + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); + mController.configure(AUTO_BRIGHTNESS_DISABLED, /* configuration= */ null, + /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, + /* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, + /* shouldResetShortTermModel= */ true); + assertEquals(normalizedBrightness, + mController.getAutomaticScreenBrightnessBasedOnLastObservedLux( + /* brightnessEvent= */ null), EPSILON); + } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java index 8faaf5998d13..05c243fda2b8 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java @@ -43,6 +43,7 @@ import com.android.internal.os.BackgroundThread; import com.android.server.display.BrightnessThrottler.Injector; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; +import com.android.server.display.config.SensorData; import com.android.server.display.mode.DisplayModeDirectorTest; import org.junit.Before; @@ -56,6 +57,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; @SmallTest @RunWith(AndroidJUnit4.class) @@ -292,6 +294,53 @@ public class BrightnessThrottlerTest { assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); } + + @Test + public void testThermalThrottlingWithDisplaySensor() throws Exception { + final ThrottlingLevel level = + new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f); + List<ThrottlingLevel> levels = new ArrayList<>(List.of(level)); + final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); + final SensorData tempSensor = new SensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY"); + final BrightnessThrottler throttler = + createThrottlerSupportedWithTempSensor(data, tempSensor); + assertTrue(throttler.deviceSupportsThrottling()); + + verify(mThermalServiceMock) + .registerThermalEventListenerWithType( + mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_DISPLAY)); + final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); + + // Set VIRTUAL-SKIN-DISPLAY tatus too low to verify no throttling. + listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus - 1)); + mTestLooper.dispatchAll(); + assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); + assertFalse(throttler.isThrottled()); + assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); + + // Verify when skin sensor throttled, no brightness throttling triggered. + listener.notifyThrottling(getSkinTemp(level.thermalStatus + 1)); + mTestLooper.dispatchAll(); + assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); + assertFalse(throttler.isThrottled()); + assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); + + // Verify when display sensor of another name throttled, no brightness throttling triggered. + listener.notifyThrottling(getDisplayTempWithName("ANOTHER-NAME", level.thermalStatus + 1)); + mTestLooper.dispatchAll(); + assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); + assertFalse(throttler.isThrottled()); + assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); + + // Verify when display sensor of current name throttled, brightness throttling triggered. + listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus + 1)); + mTestLooper.dispatchAll(); + assertEquals(level.brightness, throttler.getBrightnessCap(), 0f); + assertTrue(throttler.isThrottled()); + assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, + throttler.getBrightnessMaxReason()); + } + @Test public void testUpdateThermalThrottlingData() throws Exception { // Initialise brightness throttling levels // Ensure that they are overridden by setting the data through device config. @@ -476,18 +525,30 @@ public class BrightnessThrottlerTest { return new BrightnessThrottler(mInjectorMock, mHandler, mHandler, /* throttlingChangeCallback= */ () -> {}, /* uniqueDisplayId= */ null, /* thermalThrottlingDataId= */ null, - /* thermalThrottlingDataMap= */ new HashMap<>(1)); + /* thermalThrottlingDataMap= */ new HashMap<>(1), + /* tempSensor= */ null); } private BrightnessThrottler createThrottlerSupported(ThermalBrightnessThrottlingData data) { + SensorData tempSensor = SensorData.loadTempSensorUnspecifiedConfig(); + return createThrottlerSupportedWithTempSensor(data, tempSensor); + } + private BrightnessThrottler createThrottlerSupportedWithTempSensor( + ThermalBrightnessThrottlingData data, SensorData tempSensor) { assertNotNull(data); - HashMap<String, ThermalBrightnessThrottlingData> throttlingDataMap = new HashMap<>(1); + Map<String, ThermalBrightnessThrottlingData> throttlingDataMap = new HashMap<>(1); throttlingDataMap.put("default", data); return new BrightnessThrottler(mInjectorMock, mHandler, BackgroundThread.getHandler(), - () -> {}, "123", "default", throttlingDataMap); + () -> {}, "123", "default", throttlingDataMap, tempSensor); } private Temperature getSkinTemp(@ThrottlingStatus int status) { return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); } + + private Temperature getDisplayTempWithName( + String sensorName, @ThrottlingStatus int status) { + assertNotNull(sensorName); + return new Temperature(30.0f, Temperature.TYPE_DISPLAY, sensorName, status); + } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java index b29fc8828f58..2867041511b5 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -20,6 +20,7 @@ package com.android.server.display; import static com.android.internal.display.BrightnessSynchronizer.brightnessIntToFloat; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT; import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE; +import static com.android.server.display.config.SensorData.TEMPERATURE_TYPE_SKIN; import static com.android.server.display.config.SensorData.SupportedMode; import static com.android.server.display.utils.DeviceConfigParsingUtils.ambientBrightnessThresholdsIntToFloat; import static com.android.server.display.utils.DeviceConfigParsingUtils.displayBrightnessThresholdsIntToFloat; @@ -106,6 +107,7 @@ public final class DisplayDeviceConfigTest { MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); when(mFlags.areAutoBrightnessModesEnabled()).thenReturn(true); + when(mFlags.isSensorBasedBrightnessThrottlingEnabled()).thenReturn(true); mockDeviceConfigs(); } @@ -143,6 +145,8 @@ public final class DisplayDeviceConfigTest { assertEquals("", mDisplayDeviceConfig.getAmbientLightSensor().name); assertNull(mDisplayDeviceConfig.getProximitySensor().type); assertNull(mDisplayDeviceConfig.getProximitySensor().name); + assertEquals(TEMPERATURE_TYPE_SKIN, mDisplayDeviceConfig.getTempSensor().type); + assertNull(mDisplayDeviceConfig.getTempSensor().name); assertTrue(mDisplayDeviceConfig.isAutoBrightnessAvailable()); } @@ -592,6 +596,13 @@ public final class DisplayDeviceConfigTest { } @Test + public void testTempSensorFromDisplayConfig() throws IOException { + setupDisplayDeviceConfigFromDisplayConfigFile(); + assertEquals("DISPLAY", mDisplayDeviceConfig.getTempSensor().type); + assertEquals("VIRTUAL-SKIN-DISPLAY", mDisplayDeviceConfig.getTempSensor().name); + } + + @Test public void testBlockingZoneThresholdsFromDisplayConfig() throws IOException { setupDisplayDeviceConfigFromDisplayConfigFile(); @@ -1356,6 +1367,10 @@ public final class DisplayDeviceConfigTest { + "<name>Test Binned Brightness Sensor</name>\n" + "</screenOffBrightnessSensor>\n" + proxSensor + + "<tempSensor>\n" + + "<type>DISPLAY</type>\n" + + "<name>VIRTUAL-SKIN-DISPLAY</name>\n" + + "</tempSensor>\n" + "<ambientBrightnessChangeThresholds>\n" + "<brighteningThresholds>\n" + "<minimum>10</minimum>\n" 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 807774f90655..acddc9d22953 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -1665,6 +1665,35 @@ public final class DisplayPowerControllerTest { /* luxTimestamps= */ any()); } + @Test + public void testInitialDozeBrightness() { + when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true); + when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, false); + float brightness = 0.277f; + when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); + when(mHolder.automaticBrightnessController + .getAutomaticScreenBrightnessBasedOnLastObservedLux(any(BrightnessEvent.class))) + .thenReturn(brightness); + when(mHolder.hbmController.getCurrentBrightnessMax()) + .thenReturn(PowerManager.BRIGHTNESS_MAX); + when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + dpr.policy = DisplayPowerRequest.POLICY_DOZE; + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState + + verify(mHolder.animator).animateTo(eq(brightness), + /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), + /* ignoreAnimationLimits= */ anyBoolean()); + } + /** * Creates a mock and registers it to {@link LocalServices}. */ diff --git a/services/tests/displayservicetests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java b/services/tests/displayservicetests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java index a8af98f7a332..8a6c2440a232 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED; + import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE; import static org.junit.Assert.assertEquals; @@ -50,6 +52,8 @@ public class RefreshRateSettingsUtilsTest { private DisplayManager mDisplayManagerMock; @Mock private Display mDisplayMock; + @Mock + private Display mDisplayMock2; @Before public void setUp() { @@ -65,25 +69,54 @@ public class RefreshRateSettingsUtilsTest { new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, /* refreshRate= */ 90) }; - when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock); when(mDisplayMock.getSupportedModes()).thenReturn(modes); + + Display.Mode[] modes2 = new Display.Mode[]{ + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 70), + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 130), + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 80) + }; + when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY + 1)).thenReturn(mDisplayMock2); + when(mDisplayMock2.getSupportedModes()).thenReturn(modes2); + + when(mDisplayManagerMock.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) + .thenReturn(new Display[]{ mDisplayMock, mDisplayMock2 }); } @Test public void testFindHighestRefreshRateForDefaultDisplay() { - when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock); assertEquals(120, RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext), /* delta= */ 0); } @Test - public void testFindHighestRefreshRate_DisplayIsNull() { + public void testFindHighestRefreshRateForDefaultDisplay_DisplayIsNull() { when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(null); assertEquals(DEFAULT_REFRESH_RATE, RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext), /* delta= */ 0); } + + @Test + public void testFindHighestRefreshRateAmongAllDisplays() { + assertEquals(130, + RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays(mContext), + /* delta= */ 0); + } + + @Test + public void testFindHighestRefreshRateAmongAllDisplays_NoDisplays() { + when(mDisplayManagerMock.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) + .thenReturn(new Display[0]); + assertEquals(DEFAULT_REFRESH_RATE, + RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays(mContext), + /* delta= */ 0); + + } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/BrightnessEventTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/BrightnessEventTest.java index c0c63c69add8..060f99b4317a 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/BrightnessEventTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/BrightnessEventTest.java @@ -16,9 +16,12 @@ package com.android.server.display.brightness; +import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE; + import static org.junit.Assert.assertEquals; import android.hardware.display.BrightnessInfo; +import android.view.Display; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -39,6 +42,7 @@ public final class BrightnessEventTest { mBrightnessEvent.setReason( getReason(BrightnessReason.REASON_DOZE, BrightnessReason.MODIFIER_LOW_POWER)); mBrightnessEvent.setPhysicalDisplayId("test"); + mBrightnessEvent.setDisplayState(Display.STATE_ON); mBrightnessEvent.setLux(100.0f); mBrightnessEvent.setPreThresholdLux(150.0f); mBrightnessEvent.setTime(System.currentTimeMillis()); @@ -55,6 +59,7 @@ public final class BrightnessEventTest { mBrightnessEvent.setAdjustmentFlags(0); mBrightnessEvent.setAutomaticBrightnessEnabled(true); mBrightnessEvent.setDisplayBrightnessStrategyName(DISPLAY_BRIGHTNESS_STRATEGY_NAME); + mBrightnessEvent.setAutoBrightnessMode(AUTO_BRIGHTNESS_MODE_IDLE); } @Test @@ -69,20 +74,20 @@ public final class BrightnessEventTest { public void testToStringWorksAsExpected() { String actualString = mBrightnessEvent.toString(false); String expectedString = - "BrightnessEvent: disp=1, physDisp=test, brt=0.6, initBrt=25.0, rcmdBrt=0.6," - + " preBrt=NaN, lux=100.0, preLux=150.0, hbmMax=0.62, hbmMode=off, rbcStrength=-1," - + " thrmMax=0.65, powerFactor=0.2, wasShortTermModelActive=true, flags=," - + " reason=doze [ low_pwr ], autoBrightness=true, strategy=" - + DISPLAY_BRIGHTNESS_STRATEGY_NAME; + "BrightnessEvent: disp=1, physDisp=test, displayState=ON, brt=0.6, initBrt=25.0," + + " rcmdBrt=0.6, preBrt=NaN, lux=100.0, preLux=150.0, hbmMax=0.62, hbmMode=off," + + " rbcStrength=-1, thrmMax=0.65, powerFactor=0.2, wasShortTermModelActive=true," + + " flags=, reason=doze [ low_pwr ], autoBrightness=true, strategy=" + + DISPLAY_BRIGHTNESS_STRATEGY_NAME + ", autoBrightnessMode=idle"; assertEquals(expectedString, actualString); } @Test public void testFlagsToString() { mBrightnessEvent.reset(); - mBrightnessEvent.setFlags(mBrightnessEvent.getFlags() | BrightnessEvent.FLAG_IDLE_CURVE); + mBrightnessEvent.setFlags(mBrightnessEvent.getFlags() | BrightnessEvent.FLAG_RBC); String actualString = mBrightnessEvent.flagsToString(); - String expectedString = "idle_curve "; + String expectedString = "rbc "; assertEquals(expectedString, actualString); } @@ -90,10 +95,10 @@ public final class BrightnessEventTest { public void testFlagsToString_multipleFlags() { mBrightnessEvent.reset(); mBrightnessEvent.setFlags(mBrightnessEvent.getFlags() - | BrightnessEvent.FLAG_IDLE_CURVE + | BrightnessEvent.FLAG_RBC | BrightnessEvent.FLAG_LOW_POWER_MODE); String actualString = mBrightnessEvent.flagsToString(); - String expectedString = "idle_curve low_power_mode "; + String expectedString = "rbc low_power_mode "; assertEquals(expectedString, actualString); } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java index 37d0f6250aaf..34f352e7bf54 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java @@ -37,10 +37,14 @@ import com.android.internal.annotations.Keep; import com.android.server.display.DisplayDeviceConfig; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; +import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.testutils.FakeDeviceConfigInterface; import com.android.server.testutils.TestHandler; +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,9 +54,6 @@ import org.mockito.MockitoAnnotations; import java.util.List; -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; - @RunWith(JUnitParamsRunner.class) public class BrightnessThermalClamperTest { @@ -125,13 +126,13 @@ public class BrightnessThermalClamperTest { public void testNotifyThrottlingAfterOnDisplayChange(List<ThrottlingLevel> throttlingLevels, @Temperature.ThrottlingStatus int throttlingStatus, boolean expectedActive, float expectedBrightness) throws RemoteException { - IThermalEventListener thermalEventListener = captureThermalEventListener(); + IThermalEventListener thermalEventListener = captureSkinThermalEventListener(); mClamper.onDisplayChanged(new TestThermalData(throttlingLevels)); mTestHandler.flush(); assertFalse(mClamper.isActive()); assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); - thermalEventListener.notifyThrottling(createTemperature(throttlingStatus)); + thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus)); mTestHandler.flush(); assertEquals(expectedActive, mClamper.isActive()); assertEquals(expectedBrightness, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); @@ -139,11 +140,11 @@ public class BrightnessThermalClamperTest { @Test @Parameters(method = "testThrottlingData") - public void testOnDisplayChangeAfterNotifyThrottlng(List<ThrottlingLevel> throttlingLevels, + public void testOnDisplayChangeAfterNotifyThrottling(List<ThrottlingLevel> throttlingLevels, @Temperature.ThrottlingStatus int throttlingStatus, boolean expectedActive, float expectedBrightness) throws RemoteException { - IThermalEventListener thermalEventListener = captureThermalEventListener(); - thermalEventListener.notifyThrottling(createTemperature(throttlingStatus)); + IThermalEventListener thermalEventListener = captureSkinThermalEventListener(); + thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus)); mTestHandler.flush(); assertFalse(mClamper.isActive()); assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); @@ -156,8 +157,8 @@ public class BrightnessThermalClamperTest { @Test public void testOverrideData() throws RemoteException { - IThermalEventListener thermalEventListener = captureThermalEventListener(); - thermalEventListener.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE)); + IThermalEventListener thermalEventListener = captureSkinThermalEventListener(); + thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE)); mTestHandler.flush(); assertFalse(mClamper.isActive()); assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); @@ -183,15 +184,60 @@ public class BrightnessThermalClamperTest { assertEquals(0.4f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); } - private IThermalEventListener captureThermalEventListener() throws RemoteException { + @Test + public void testDisplaySensorBasedThrottling() throws RemoteException { + final int severity = PowerManager.THERMAL_STATUS_SEVERE; + IThermalEventListener thermalEventListener = captureSkinThermalEventListener(); + // Update config to listen to display type sensor. + final SensorData tempSensor = new SensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY"); + final TestThermalData thermalData = + new TestThermalData( + DISPLAY_ID, + DisplayDeviceConfig.DEFAULT_ID, + List.of(new ThrottlingLevel(severity, 0.5f)), + tempSensor); + mClamper.onDisplayChanged(thermalData); + mTestHandler.flush(); + verify(mMockThermalService).unregisterThermalEventListener(thermalEventListener); + thermalEventListener = captureThermalEventListener(Temperature.TYPE_DISPLAY); + assertFalse(mClamper.isActive()); + + // Verify no throttling triggered when any other sensor notification received. + thermalEventListener.notifyThrottling(createSkinTemperature(severity)); + mTestHandler.flush(); + assertFalse(mClamper.isActive()); + + thermalEventListener.notifyThrottling(createDisplayTemperature("OTHER-SENSOR", severity)); + mTestHandler.flush(); + assertFalse(mClamper.isActive()); + + assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); + + // Verify throttling triggered when display sensor of given name throttled. + thermalEventListener.notifyThrottling(createDisplayTemperature(tempSensor.name, severity)); + mTestHandler.flush(); + assertTrue(mClamper.isActive()); + assertEquals(0.5f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE); + } + + private IThermalEventListener captureSkinThermalEventListener() throws RemoteException { + return captureThermalEventListener(Temperature.TYPE_SKIN); + } + + private IThermalEventListener captureThermalEventListener(int type) throws RemoteException { ArgumentCaptor<IThermalEventListener> captor = ArgumentCaptor.forClass( IThermalEventListener.class); verify(mMockThermalService).registerThermalEventListenerWithType(captor.capture(), eq( - Temperature.TYPE_SKIN)); + type)); return captor.getValue(); } - private Temperature createTemperature(@Temperature.ThrottlingStatus int status) { + private Temperature createDisplayTemperature( + @NonNull String sensorName, @Temperature.ThrottlingStatus int status) { + return new Temperature(100, Temperature.TYPE_DISPLAY, sensorName, status); + } + + private Temperature createSkinTemperature(@Temperature.ThrottlingStatus int status) { return new Temperature(100, Temperature.TYPE_SKIN, "test_temperature", status); } @@ -217,19 +263,26 @@ public class BrightnessThermalClamperTest { private final String mUniqueDisplayId; private final String mDataId; private final ThermalBrightnessThrottlingData mData; + private final SensorData mTempSensor; private TestThermalData() { - this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, null); + this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, null, + SensorData.loadTempSensorUnspecifiedConfig()); } private TestThermalData(List<ThrottlingLevel> data) { - this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, data); + this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, data, + SensorData.loadTempSensorUnspecifiedConfig()); } - private TestThermalData(String uniqueDisplayId, String dataId, List<ThrottlingLevel> data) { + + private TestThermalData(String uniqueDisplayId, String dataId, List<ThrottlingLevel> data, + SensorData tempSensor) { mUniqueDisplayId = uniqueDisplayId; mDataId = dataId; mData = ThermalBrightnessThrottlingData.create(data); + mTempSensor = tempSensor; } + @NonNull @Override public String getUniqueDisplayId() { @@ -247,5 +300,11 @@ public class BrightnessThermalClamperTest { public ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData() { return mData; } + + @NonNull + @Override + public SensorData getTempSensor() { + return mTempSensor; + } } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java index 5408e1143330..886780655de2 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java @@ -359,11 +359,17 @@ public class AutomaticBrightnessStrategyTest { AutomaticBrightnessController.class); when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class))) .thenReturn(automaticScreenBrightness); + when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastObservedLux( + any(BrightnessEvent.class))) + .thenReturn(automaticScreenBrightness); mAutomaticBrightnessStrategy.setAutomaticBrightnessController( automaticBrightnessController); assertEquals(automaticScreenBrightness, mAutomaticBrightnessStrategy.getAutomaticScreenBrightness( new BrightnessEvent(DISPLAY_ID)), 0.0f); + assertEquals(automaticScreenBrightness, + mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastObservedLux( + new BrightnessEvent(DISPLAY_ID)), 0.0f); } @Test diff --git a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java index 8f5d1253406e..a918be2292af 100644 --- a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java +++ b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java @@ -16,6 +16,8 @@ package com.android.server.media; +import static android.Manifest.permission.MODIFY_AUDIO_ROUTING; + import static com.android.server.media.AudioRoutingUtils.ATTRIBUTES_MEDIA; import static com.android.server.media.AudioRoutingUtils.getMediaAudioProductStrategy; @@ -31,6 +33,7 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.Instrumentation; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.content.Context; @@ -48,6 +51,7 @@ import android.os.UserHandle; import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -85,6 +89,7 @@ public class AudioManagerRouteControllerTest { /* name= */ null, /* address= */ null); + private Instrumentation mInstrumentation; private AudioDeviceInfo mSelectedAudioDeviceInfo; private Set<AudioDeviceInfo> mAvailableAudioDeviceInfos; @Mock private AudioManager mMockAudioManager; @@ -96,10 +101,11 @@ public class AudioManagerRouteControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(MODIFY_AUDIO_ROUTING); Resources mockResources = Mockito.mock(Resources.class); when(mockResources.getText(anyInt())).thenReturn(FAKE_ROUTE_NAME); - Context realContext = InstrumentationRegistry.getInstrumentation().getContext(); + Context realContext = mInstrumentation.getContext(); Context mockContext = Mockito.mock(Context.class); when(mockContext.getResources()).thenReturn(mockResources); // The bluetooth stack needs the application info, but we cannot use a spy because the @@ -135,6 +141,11 @@ public class AudioManagerRouteControllerTest { clearInvocations(mOnDeviceRouteChangedListener); } + @After + public void tearDown() { + mInstrumentation.getUiAutomation().dropShellPermissionIdentity(); + } + @Test public void getSelectedRoute_afterDevicesConnect_returnsRightSelectedRoute() { assertThat(mControllerUnderTest.getSelectedRoute().getType()) diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java index dad36e787360..2366f56707fa 100644 --- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Binder; +import android.os.Process; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; @@ -52,6 +53,8 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Set; + @SmallTest @RunWith(AndroidTestingRunner.class) @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_APP_PROTECTION) @@ -62,12 +65,14 @@ import org.mockito.MockitoAnnotations; public class SensitiveContentProtectionManagerServiceContentTest { private final PackageInfo mPackageInfo = new PackageInfo("test.package", 12345, new Binder()); + private final String mScreenRecorderPackage = "test.screen.recorder.package"; + private final String mExemptedScreenRecorderPackage = "test.exempted.screen.recorder.package"; private SensitiveContentProtectionManagerService mSensitiveContentProtectionManagerService; private MediaProjectionManager.Callback mMediaPorjectionCallback; @Mock private WindowManagerInternal mWindowManager; @Mock private MediaProjectionManager mProjectionManager; - @Mock private MediaProjectionInfo mMediaProjectionInfo; + private MediaProjectionInfo mMediaProjectionInfo; @Captor private ArgumentCaptor<MediaProjectionManager.Callback> mMediaProjectionCallbackCaptor; @@ -85,9 +90,22 @@ public class SensitiveContentProtectionManagerServiceContentTest { MockitoAnnotations.initMocks(this); mSensitiveContentProtectionManagerService = new SensitiveContentProtectionManagerService(mContext); - mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager); + mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, + new ArraySet<>(Set.of(mExemptedScreenRecorderPackage))); verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue(); + mMediaProjectionInfo = + new MediaProjectionInfo(mScreenRecorderPackage, Process.myUserHandle(), null); + } + + @Test + public void testExemptedRecorderPackageForScreenCapture() { + MediaProjectionInfo exemptedRecorderPackage = new MediaProjectionInfo( + mExemptedScreenRecorderPackage, Process.myUserHandle(), null); + mMediaPorjectionCallback.onStart(exemptedRecorderPackage); + mSensitiveContentProtectionManagerService.setSensitiveContentProtection( + mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true); + verifyZeroInteractions(mWindowManager); } @Test diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java index 08050a9b30e0..e74fe296d0a5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java @@ -78,6 +78,8 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { private static final String NOTIFICATION_PKG_1 = "com.android.server.notification.one"; private static final String NOTIFICATION_PKG_2 = "com.android.server.notification.two"; + private static final String EXEMPTED_SCREEN_RECORDER_PACKAGE = "test.screen.recorder.package"; + private static final int NOTIFICATION_UID_1 = 5; private static final int NOTIFICATION_UID_2 = 6; @@ -138,7 +140,8 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { setupSensitiveNotification(); - mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager); + mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, + new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); // Obtain useful mMediaProjectionCallback verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); @@ -275,6 +278,16 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { } @Test + public void mediaProjectionOnStart_verifyExemptedRecorderPackage() { + MediaProjectionInfo mediaProjectionInfo = mock(MediaProjectionInfo.class); + when(mediaProjectionInfo.getPackageName()).thenReturn(EXEMPTED_SCREEN_RECORDER_PACKAGE); + + mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); + + verifyZeroInteractions(mWindowManager); + } + + @Test public void mediaProjectionOnStart_onProjectionStart_setWmBlockedPackages() { ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification(); diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index a4761555384e..99752212fcbd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.alarm; import static android.Manifest.permission.SCHEDULE_EXACT_ALARM; +import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; +import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED; @@ -42,6 +44,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; +import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.NULL_DEFAULT; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; @@ -135,6 +138,7 @@ import android.net.Uri; import android.os.BatteryManager; import android.os.Bundle; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -145,9 +149,11 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; +import android.platform.test.flag.util.FlagSetException; import android.provider.DeviceConfig; -import android.provider.Settings; import android.text.format.DateFormat; import android.util.ArraySet; import android.util.Log; @@ -215,6 +221,7 @@ public final class AlarmManagerServiceTest { private AppStateTrackerImpl.Listener mListener; private AlarmManagerService.UninstallReceiver mPackageChangesReceiver; private AlarmManagerService.ChargingReceiver mChargingReceiver; + private ActivityManager.UidFrozenStateChangedCallback mUidFrozenStateCallback; private IAppOpsCallback mIAppOpsCallback; private IAlarmManager mBinder; @Mock @@ -240,6 +247,8 @@ public final class AlarmManagerServiceTest { @Mock private ActivityManagerInternal mActivityManagerInternal; @Mock + private ActivityManager mActivityManager; + @Mock private PackageManagerInternal mPackageManagerInternal; @Mock private AppStateTrackerImpl mAppStateTracker; @@ -403,15 +412,31 @@ public final class AlarmManagerServiceTest { .mockStatic(PermissionChecker.class) .mockStatic(PermissionManagerService.class) .mockStatic(ServiceManager.class) - .mockStatic(Settings.Global.class) .mockStatic(SystemProperties.class) .spyStatic(UserHandle.class) .afterSessionFinished( () -> LocalServices.removeServiceForTest(AlarmManagerInternal.class)) .build(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(NULL_DEFAULT); + + /** + * Have to do this to switch the {@link Flags} implementation to {@link FakeFeatureFlagsImpl}. + * All methods that need any flag enabled should use the + * {@link android.platform.test.annotations.EnableFlags} annotation, in which case disabling + * the flag will fail with an exception that we will swallow here. + */ + private void disableFlagsNotSetByAnnotation() { + try { + mSetFlagsRule.disableFlags(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS); + } catch (FlagSetException fse) { + // Expected if the test about to be run requires this enabled. + } + } + @Before - public final void setUp() { + public void setUp() { doReturn(mIActivityManager).when(ActivityManager::getService); doReturn(mDeviceIdleInternal).when( () -> LocalServices.getService(DeviceIdleInternal.class)); @@ -469,6 +494,7 @@ public final class AlarmManagerServiceTest { when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); when(mMockContext.getSystemService(BatteryManager.class)).thenReturn(mBatteryManager); + when(mMockContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); registerAppIds(new String[]{TEST_CALLING_PACKAGE}, new Integer[]{UserHandle.getAppId(TEST_CALLING_UID)}); @@ -479,7 +505,18 @@ public final class AlarmManagerServiceTest { mService = new AlarmManagerService(mMockContext, mInjector); spyOn(mService); + disableFlagsNotSetByAnnotation(); + mService.onStart(); + + if (Flags.useFrozenStateToDropListenerAlarms()) { + final ArgumentCaptor<ActivityManager.UidFrozenStateChangedCallback> frozenCaptor = + ArgumentCaptor.forClass(ActivityManager.UidFrozenStateChangedCallback.class); + verify(mActivityManager).registerUidFrozenStateChangedCallback( + any(HandlerExecutor.class), frozenCaptor.capture()); + mUidFrozenStateCallback = frozenCaptor.getValue(); + } + // Unable to mock mMockContext to return a mock stats manager. // So just mocking the whole MetricsHelper instance. mService.mMetricsHelper = mock(MetricsHelper.class); @@ -3741,9 +3778,87 @@ public final class AlarmManagerServiceTest { mListener.handleUidCachedChanged(TEST_CALLING_UID, true); assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); assertEquals(3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + assertEquals(numExactListenerUid2 + 2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); mListener.handleUidCachedChanged(TEST_CALLING_UID_2, true); assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); + assertEquals(3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); + } + + private void executeUidFrozenStateCallback(int[] uids, int[] frozenStates) { + assertNotNull(mUidFrozenStateCallback); + mUidFrozenStateCallback.onUidFrozenStateChanged(uids, frozenStates); + } + + @EnableFlags(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS) + @Test + public void exactListenerAlarmsRemovedOnFrozen() { + mockChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, true); + + setTestAlarmWithListener(ELAPSED_REALTIME, 31, getNewListener(() -> {}), WINDOW_EXACT, + TEST_CALLING_UID); + setTestAlarmWithListener(RTC, 42, getNewListener(() -> {}), 56, TEST_CALLING_UID); + setTestAlarm(ELAPSED_REALTIME, 54, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, + TEST_CALLING_UID, null); + setTestAlarm(RTC, 49, 154, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID, null); + + setTestAlarmWithListener(ELAPSED_REALTIME, 21, getNewListener(() -> {}), WINDOW_EXACT, + TEST_CALLING_UID_2); + setTestAlarmWithListener(RTC, 412, getNewListener(() -> {}), 561, TEST_CALLING_UID_2); + setTestAlarm(ELAPSED_REALTIME, 26, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, + TEST_CALLING_UID_2, null); + setTestAlarm(RTC, 549, 234, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID_2, null); + + assertEquals(8, mService.mAlarmStore.size()); + + executeUidFrozenStateCallback( + new int[] {TEST_CALLING_UID, TEST_CALLING_UID_2}, + new int[] {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN}); + assertEquals(7, mService.mAlarmStore.size()); + + executeUidFrozenStateCallback( + new int[] {TEST_CALLING_UID_2}, new int[] {UID_FROZEN_STATE_FROZEN}); + assertEquals(6, mService.mAlarmStore.size()); + } + + @EnableFlags(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS) + @Test + public void alarmCountOnListenerFrozen() { + mockChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, true); + + // Set some alarms for TEST_CALLING_UID. + final int numExactListenerUid1 = 17; + for (int i = 0; i < numExactListenerUid1; i++) { + setTestAlarmWithListener(ALARM_TYPES[i % 4], mNowElapsedTest + i, + getNewListener(() -> {})); + } + setTestAlarmWithListener(RTC, 42, getNewListener(() -> {}), 56, TEST_CALLING_UID); + setTestAlarm(ELAPSED_REALTIME, 54, getNewMockPendingIntent()); + setTestAlarm(RTC, 49, 154, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID, null); + + // Set some alarms for TEST_CALLING_UID_2. + final int numExactListenerUid2 = 11; + for (int i = 0; i < numExactListenerUid2; i++) { + setTestAlarmWithListener(ALARM_TYPES[i % 4], mNowElapsedTest + i, + getNewListener(() -> {}), WINDOW_EXACT, TEST_CALLING_UID_2); + } + setTestAlarmWithListener(RTC, 412, getNewListener(() -> {}), 561, TEST_CALLING_UID_2); + setTestAlarm(RTC_WAKEUP, 26, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, + TEST_CALLING_UID_2, null); + + assertEquals(numExactListenerUid1 + 3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + assertEquals(numExactListenerUid2 + 2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); + + executeUidFrozenStateCallback( + new int[] {TEST_CALLING_UID, TEST_CALLING_UID_2}, + new int[] {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN}); + assertEquals(3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + assertEquals(numExactListenerUid2 + 2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); + + executeUidFrozenStateCallback( + new int[] {TEST_CALLING_UID_2}, new int[] {UID_FROZEN_STATE_FROZEN}); + assertEquals(3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); } diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java index 940469f89b16..414532b88e22 100644 --- a/services/tests/mockingservicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java @@ -29,16 +29,20 @@ import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.app.backup.BackupTransport; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.Build; import android.os.Message; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.testing.TestableDeviceConfig; +import com.android.server.backup.Flags; import com.android.server.backup.UserBackupManagerService; import com.android.server.backup.internal.BackupHandler; import com.android.server.backup.transport.BackupTransportClient; @@ -56,10 +60,12 @@ import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; @@ -74,10 +80,17 @@ public class PerformUnifiedRestoreTaskTest { private static final String SYSTEM_PACKAGE_NAME = "android"; private static final String NON_SYSTEM_PACKAGE_NAME = "package"; - @Mock private BackupDataInput mBackupDataInput; - @Mock private BackupDataOutput mBackupDataOutput; - @Mock private UserBackupManagerService mBackupManagerService; - @Mock private TransportConnection mTransportConnection; + private static final String V_TO_U_ALLOWLIST = "pkg1"; + private static final String V_TO_U_DENYLIST = "pkg2"; + + @Mock + private BackupDataInput mBackupDataInput; + @Mock + private BackupDataOutput mBackupDataOutput; + @Mock + private UserBackupManagerService mBackupManagerService; + @Mock + private TransportConnection mTransportConnection; private Set<String> mExcludedkeys = new HashSet<>(); private Map<String, String> mBackupData = new HashMap<>(); @@ -91,6 +104,10 @@ public class PerformUnifiedRestoreTaskTest { public TestableDeviceConfig.TestableDeviceConfigRule mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private Context mContext; @Before @@ -118,7 +135,8 @@ public class PerformUnifiedRestoreTaskTest { return null; }); - mRestoreTask = new PerformUnifiedRestoreTask(mBackupManagerService, mTransportConnection); + mRestoreTask = new PerformUnifiedRestoreTask(mBackupManagerService, mTransportConnection, + V_TO_U_ALLOWLIST, V_TO_U_DENYLIST); } private void populateTestData() { @@ -235,6 +253,122 @@ public class PerformUnifiedRestoreTaskTest { == UnifiedRestoreState.FINAL); } + @Test + public void testCreateVToUList_listSettingIsNull_returnEmptyList() { + List<String> expectedEmptyList = new ArrayList<>(); + + List<String> list = mRestoreTask.createVToUList(null); + + assertEquals(list, expectedEmptyList); + } + + @Test + public void testCreateVToUList_listIsNotNull_returnCorrectList() { + List<String> expectedList = Arrays.asList("a", "b", "c"); + String listString = "a,b,c"; + + List<String> list = mRestoreTask.createVToUList(listString); + + assertEquals(list, expectedList); + } + + @Test + public void testIsVToUDowngrade_vToUFlagIsOffAndTargetIsUSourceIsV_returnFalse() { + mSetFlagsRule.disableFlags( + Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST); + + boolean isVToUDowngrade = mRestoreTask.isVToUDowngrade( + Build.VERSION_CODES.VANILLA_ICE_CREAM, Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + + assertFalse(isVToUDowngrade); + } + + @Test + public void testIsVToUDowngrade_vToUFlagIsOnAndTargetIsUSourceIsV_returnTrue() { + mSetFlagsRule.enableFlags( + Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST); + + boolean isVToUDowngrade = mRestoreTask.isVToUDowngrade( + Build.VERSION_CODES.VANILLA_ICE_CREAM, Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + + assertTrue(isVToUDowngrade); + } + + @Test + public void testIsVToUDowngrade_vToUFlagIsOnAndSourceIsNotV_returnFalse() { + mSetFlagsRule.enableFlags( + Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST); + + boolean isVToUDowngrade = mRestoreTask.isVToUDowngrade(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, + Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + + assertFalse(isVToUDowngrade); + } + + @Test + public void testIsVToUDowngrade_vToUFlagIsOnAndTargetIsNotU_returnFalse() { + mSetFlagsRule.enableFlags( + Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST); + + boolean isVToUDowngrade = mRestoreTask.isVToUDowngrade( + Build.VERSION_CODES.VANILLA_ICE_CREAM, Build.VERSION_CODES.VANILLA_ICE_CREAM); + + assertFalse(isVToUDowngrade); + } + + + @Test + public void testIsEligibleForVToUDowngrade_pkgIsNotOnAllowlist_returnFalse() { + PackageInfo testPackageInfo = new PackageInfo(); + testPackageInfo.packageName = "pkg"; + testPackageInfo.applicationInfo = new ApplicationInfo(); + // restoreAnyVersion flag is off + testPackageInfo.applicationInfo.flags = 0; + + boolean eligibilityCriteria = mRestoreTask.isPackageEligibleForVToURestore(testPackageInfo); + + assertFalse(eligibilityCriteria); + } + + @Test + public void testIsEligibleForVToUDowngrade_pkgIsOnAllowlist_returnTrue() { + PackageInfo testPackageInfo = new PackageInfo(); + testPackageInfo.packageName = "pkg1"; + testPackageInfo.applicationInfo = new ApplicationInfo(); + // restoreAnyVersion flag is off + testPackageInfo.applicationInfo.flags = 0; + + boolean eligibilityCriteria = mRestoreTask.isPackageEligibleForVToURestore(testPackageInfo); + + assertTrue(eligibilityCriteria); + } + + @Test + public void testIsEligibleForVToUDowngrade_pkgIsNotOnDenyList_returnTrue() { + PackageInfo testPackageInfo = new PackageInfo(); + testPackageInfo.packageName = "pkg"; + testPackageInfo.applicationInfo = new ApplicationInfo(); + // restoreAnyVersion flag is on + testPackageInfo.applicationInfo.flags = ApplicationInfo.FLAG_RESTORE_ANY_VERSION; + + boolean eligibilityCriteria = mRestoreTask.isPackageEligibleForVToURestore(testPackageInfo); + + assertTrue(eligibilityCriteria); + } + + @Test + public void testIsEligibleForVToUDowngrade_pkgIsOnDenyList_returnFalse() { + PackageInfo testPackageInfo = new PackageInfo(); + testPackageInfo.packageName = "pkg2"; + testPackageInfo.applicationInfo = new ApplicationInfo(); + // restoreAnyVersion flag is on + testPackageInfo.applicationInfo.flags = ApplicationInfo.FLAG_RESTORE_ANY_VERSION; + + boolean eligibilityCriteria = mRestoreTask.isPackageEligibleForVToURestore(testPackageInfo); + + assertFalse(eligibilityCriteria); + } + private void setupForRestoreKeyValueState(int transportStatus) throws RemoteException, TransportNotAvailableException { // Mock BackupHandler to do nothing when executeNextState() is called diff --git a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java index a8faa54fe9d6..ad68de84eace 100644 --- a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java @@ -196,6 +196,9 @@ public class BatterySaverStateMachineTest { when(mMockResources.getBoolean( com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled)) .thenReturn(false); + when(mMockResources.getBoolean( + com.android.internal.R.bool.config_batterySaverTurnedOffNotificationEnabled)) + .thenReturn(true); when(mMockResources.getInteger( com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold)) .thenReturn(80); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java index 548fae7a0b01..a1101cd0f0bc 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java @@ -578,45 +578,136 @@ public class BatteryStatsImplTest { // First wakelock, acquired once, not currently held mMockClock.realtime = 1000; - mBatteryStatsImpl.noteStartWakeLocked(10100, 100, null, "wakeLock1", null, - BatteryStats.WAKE_TYPE_PARTIAL, false); + mBatteryStatsImpl.noteStartWakeLocked( + 10100, 100, null, "wakeLock1", null, BatteryStats.WAKE_TYPE_PARTIAL, false); mMockClock.realtime = 3000; - mBatteryStatsImpl.noteStopWakeLocked(10100, 100, null, "wakeLock1", null, - BatteryStats.WAKE_TYPE_PARTIAL); + mBatteryStatsImpl.noteStopWakeLocked( + 10100, 100, null, "wakeLock1", null, BatteryStats.WAKE_TYPE_PARTIAL); // Second wakelock, acquired twice, still held mMockClock.realtime = 4000; - mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null, - BatteryStats.WAKE_TYPE_PARTIAL, false); + mBatteryStatsImpl.noteStartWakeLocked( + 10200, 101, null, "wakeLock2", null, BatteryStats.WAKE_TYPE_PARTIAL, false); mMockClock.realtime = 5000; - mBatteryStatsImpl.noteStopWakeLocked(10200, 101, null, "wakeLock2", null, - BatteryStats.WAKE_TYPE_PARTIAL); + mBatteryStatsImpl.noteStopWakeLocked( + 10200, 101, null, "wakeLock2", null, BatteryStats.WAKE_TYPE_PARTIAL); mMockClock.realtime = 6000; - mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null, - BatteryStats.WAKE_TYPE_PARTIAL, false); + mBatteryStatsImpl.noteStartWakeLocked( + 10200, 101, null, "wakeLock2", null, BatteryStats.WAKE_TYPE_PARTIAL, false); - mMockClock.realtime = 9000; - - List<WakeLockStats.WakeLock> wakeLockStats = - mBatteryStatsImpl.getWakeLockStats().getWakeLocks(); - assertThat(wakeLockStats).hasSize(2); + // Third and fourth wakelocks, overlapped with each other. + mMockClock.realtime = 7000; + mBatteryStatsImpl.noteStartWakeLocked( + 10300, 102, null, "wakeLock3", null, BatteryStats.WAKE_TYPE_PARTIAL, false); - WakeLockStats.WakeLock wakeLock1 = wakeLockStats.stream() - .filter(wl -> wl.uid == 10100 && wl.name.equals("wakeLock1")).findFirst().get(); + mMockClock.realtime = 8000; + mBatteryStatsImpl.noteStartWakeLocked( + 10400, 103, null, "wakeLock4", null, BatteryStats.WAKE_TYPE_PARTIAL, false); - assertThat(wakeLock1.timesAcquired).isEqualTo(1); - assertThat(wakeLock1.timeHeldMs).isEqualTo(0); // Not currently held - assertThat(wakeLock1.totalTimeHeldMs).isEqualTo(2000); // 3000-1000 + mMockClock.realtime = 9000; + mBatteryStatsImpl.noteStopWakeLocked( + 10400, 103, null, "wakeLock4", null, BatteryStats.WAKE_TYPE_PARTIAL); + + mMockClock.realtime = 10000; + mBatteryStatsImpl.noteStartWakeLocked( + 10400, 104, null, "wakeLock5", null, BatteryStats.WAKE_TYPE_PARTIAL, false); + + mMockClock.realtime = 11000; + mBatteryStatsImpl.noteStopWakeLocked( + 10400, 104, null, "wakeLock5", null, BatteryStats.WAKE_TYPE_PARTIAL); + + mMockClock.realtime = 12000; + mBatteryStatsImpl.noteStopWakeLocked( + 10300, 102, null, "wakeLock3", null, BatteryStats.WAKE_TYPE_PARTIAL); + + mMockClock.realtime = 13000; + + // Verify un-aggregated wakelocks. + WakeLockStats wakeLockStats = mBatteryStatsImpl.getWakeLockStats(); + List<WakeLockStats.WakeLock> wakeLockList = wakeLockStats.getWakeLocks(); + assertThat(wakeLockList).hasSize(4); + + WakeLockStats.WakeLock wakeLock1 = getWakeLockFromList(wakeLockList, 10100, "wakeLock1"); + assertThat(wakeLock1.isAggregated).isFalse(); + assertThat(wakeLock1.totalWakeLockData.timesAcquired).isEqualTo(1); + assertThat(wakeLock1.totalWakeLockData.timeHeldMs).isEqualTo(0); // Not currently held + assertThat(wakeLock1.totalWakeLockData.totalTimeHeldMs).isEqualTo(2000); // 3000-1000 + + WakeLockStats.WakeLock wakeLock3 = getWakeLockFromList(wakeLockList, 10300, "wakeLock3"); + assertThat(wakeLock3.isAggregated).isFalse(); + assertThat(wakeLock3.totalWakeLockData.timesAcquired).isEqualTo(1); + assertThat(wakeLock3.totalWakeLockData.timeHeldMs).isEqualTo(0); // Not currently held + // (8000-7000)/2 + (9000-8000)/3 + (10000-9000)/2 + (11000-10000)/3 + (12000-11000)/2 + assertThat(wakeLock3.totalWakeLockData.totalTimeHeldMs).isEqualTo(2166); + + WakeLockStats.WakeLock wakeLock4 = getWakeLockFromList(wakeLockList, 10400, "wakeLock4"); + assertThat(wakeLock4.isAggregated).isFalse(); + assertThat(wakeLock4.totalWakeLockData.timesAcquired).isEqualTo(1); + assertThat(wakeLock4.totalWakeLockData.timeHeldMs).isEqualTo(0); // Not currently held + assertThat(wakeLock4.totalWakeLockData.totalTimeHeldMs).isEqualTo(333); // (9000-8000)/3 + + WakeLockStats.WakeLock wakeLock5 = getWakeLockFromList(wakeLockList, 10400, "wakeLock5"); + assertThat(wakeLock5.isAggregated).isFalse(); + assertThat(wakeLock5.totalWakeLockData.timesAcquired).isEqualTo(1); + assertThat(wakeLock5.totalWakeLockData.timeHeldMs).isEqualTo(0); // Not currently held + assertThat(wakeLock5.totalWakeLockData.totalTimeHeldMs).isEqualTo(333); // (11000-10000)/3 + + // Verify aggregated wakelocks. + List<WakeLockStats.WakeLock> aggregatedWakeLockList = + wakeLockStats.getAggregatedWakeLocks(); + assertThat(aggregatedWakeLockList).hasSize(4); + + WakeLockStats.WakeLock aggregatedWakeLock1 = + getAggregatedWakeLockFromList(aggregatedWakeLockList, 10100); + assertThat(aggregatedWakeLock1.isAggregated).isTrue(); + assertThat(aggregatedWakeLock1.totalWakeLockData.timesAcquired).isEqualTo(1); + // Not currently held + assertThat(aggregatedWakeLock1.totalWakeLockData.timeHeldMs).isEqualTo(0); + // 3000-1000 + assertThat(aggregatedWakeLock1.totalWakeLockData.totalTimeHeldMs).isEqualTo(2000); + + WakeLockStats.WakeLock aggregatedWakeLock2 = + getAggregatedWakeLockFromList(aggregatedWakeLockList, 10200); + assertThat(aggregatedWakeLock2.isAggregated).isTrue(); + assertThat(aggregatedWakeLock2.totalWakeLockData.timesAcquired).isEqualTo(2); + assertThat(aggregatedWakeLock2.totalWakeLockData.timeHeldMs).isEqualTo(7000); // 13000-6000 + // (5000-4000) + (13000-6000) + assertThat(aggregatedWakeLock2.totalWakeLockData.totalTimeHeldMs) + .isEqualTo(8000); + + WakeLockStats.WakeLock aggregatedWakeLock3 = + getAggregatedWakeLockFromList(aggregatedWakeLockList, 10300); + assertThat(aggregatedWakeLock3.isAggregated).isTrue(); + assertThat(aggregatedWakeLock3.totalWakeLockData.timesAcquired).isEqualTo(1); + // Not currently held + assertThat(aggregatedWakeLock3.totalWakeLockData.timeHeldMs).isEqualTo(0); + // 12000-7000 + assertThat(aggregatedWakeLock3.totalWakeLockData.totalTimeHeldMs).isEqualTo(5000); + + WakeLockStats.WakeLock aggregatedWakeLock4 = + getAggregatedWakeLockFromList(aggregatedWakeLockList, 10400); + assertThat(aggregatedWakeLock4.isAggregated).isTrue(); + assertThat(aggregatedWakeLock4.totalWakeLockData.timesAcquired).isEqualTo(2); + // Not currently held + assertThat(aggregatedWakeLock4.totalWakeLockData.timeHeldMs).isEqualTo(0); + assertThat(aggregatedWakeLock4.totalWakeLockData.totalTimeHeldMs) + .isEqualTo(2000); // (9000-8000) + (11000-10000) + } - WakeLockStats.WakeLock wakeLock2 = wakeLockStats.stream() - .filter(wl -> wl.uid == 10200 && wl.name.equals("wakeLock2")).findFirst().get(); + private WakeLockStats.WakeLock getAggregatedWakeLockFromList( + List<WakeLockStats.WakeLock> wakeLockList, final int uid) { + return getWakeLockFromList(wakeLockList, uid, WakeLockStats.WakeLock.NAME_AGGREGATED); + } - assertThat(wakeLock2.timesAcquired).isEqualTo(2); - assertThat(wakeLock2.timeHeldMs).isEqualTo(3000); // 9000-6000 - assertThat(wakeLock2.totalTimeHeldMs).isEqualTo(4000); // (5000-4000) + (9000-6000) + private WakeLockStats.WakeLock getWakeLockFromList( + List<WakeLockStats.WakeLock> wakeLockList, final int uid, final String name) { + return wakeLockList.stream() + .filter(wl -> wl.uid == uid && wl.name.equals(name)) + .findFirst() + .get(); } @Test diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java index 6cd79bc09fb6..374426ad67a1 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java @@ -18,12 +18,17 @@ package com.android.server.power.stats; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.Context; import android.hardware.SensorManager; +import android.os.AggregateBatteryConsumer; import android.os.BatteryConsumer; import android.os.BatteryManager; import android.os.BatteryStats; @@ -34,6 +39,7 @@ import android.os.Parcel; import android.os.Process; import android.os.UidBatteryConsumer; import android.platform.test.ravenwood.RavenwoodRule; +import android.util.SparseLongArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -49,7 +55,6 @@ import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.List; @SmallTest @@ -64,11 +69,10 @@ public class BatteryUsageStatsProviderTest { private static final long MINUTE_IN_MS = 60 * 1000; private static final double PRECISION = 0.00001; - private File mHistoryDir; - @Rule(order = 1) public final BatteryUsageStatsRule mStatsRule = - new BatteryUsageStatsRule(12345, mHistoryDir) + new BatteryUsageStatsRule(12345) + .createTempDirectory() .setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0) .setAveragePower(PowerProfile.POWER_AUDIO, 720.0); @@ -77,9 +81,6 @@ public class BatteryUsageStatsProviderTest { @Before public void setup() throws IOException { - mHistoryDir = Files.createTempDirectory("BatteryUsageStatsProviderTest").toFile(); - clearDirectory(mHistoryDir); - if (RavenwoodRule.isUnderRavenwood()) { mContext = mock(Context.class); SensorManager sensorManager = mock(SensorManager.class); @@ -89,17 +90,6 @@ public class BatteryUsageStatsProviderTest { } } - private void clearDirectory(File dir) { - if (dir.exists()) { - for (File child : dir.listFiles()) { - if (child.isDirectory()) { - clearDirectory(child); - } - child.delete(); - } - } - } - @Test public void test_getBatteryUsageStats() { BatteryStatsImpl batteryStats = prepareBatteryStats(); @@ -417,7 +407,7 @@ public class BatteryUsageStatsProviderTest { } PowerStatsStore powerStatsStore = new PowerStatsStore( - new File(mHistoryDir, "powerstatsstore"), + new File(mStatsRule.getHistoryDir(), "powerstatsstore"), mStatsRule.getHandler(), null); powerStatsStore.reset(); @@ -517,6 +507,57 @@ public class BatteryUsageStatsProviderTest { } @Test + public void saveBatteryUsageStatsOnReset_incompatibleEnergyConsumers() throws Throwable { + MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); + batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); + int componentId0 = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID; + int componentId1 = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1; + + synchronized (batteryStats) { + batteryStats.getUidStatsLocked(APP_UID); + + SparseLongArray uidEnergies = new SparseLongArray(); + uidEnergies.put(APP_UID, 30_000_000); + batteryStats.updateCustomEnergyConsumerStatsLocked(0, 100_000_000, uidEnergies); + batteryStats.updateCustomEnergyConsumerStatsLocked(1, 200_000_000, uidEnergies); + } + + BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null, + mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock); + + PowerStatsStore powerStatsStore = mock(PowerStatsStore.class); + doAnswer(invocation -> { + BatteryUsageStats stats = invocation.getArgument(1); + AggregateBatteryConsumer device = stats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + assertThat(device.getCustomPowerComponentName(componentId0)).isEqualTo("FOO"); + assertThat(device.getCustomPowerComponentName(componentId1)).isEqualTo("BAR"); + assertThat(device.getConsumedPowerForCustomComponent(componentId0)) + .isWithin(PRECISION).of(27.77777); + assertThat(device.getConsumedPowerForCustomComponent(componentId1)) + .isWithin(PRECISION).of(55.55555); + + UidBatteryConsumer uid = stats.getUidBatteryConsumers().get(0); + assertThat(uid.getConsumedPowerForCustomComponent(componentId0)) + .isWithin(PRECISION).of(8.33333); + assertThat(uid.getConsumedPowerForCustomComponent(componentId1)) + .isWithin(PRECISION).of(8.33333); + return null; + }).when(powerStatsStore).storeBatteryUsageStats(anyLong(), any()); + + mStatsRule.getBatteryStats().saveBatteryUsageStatsOnReset(provider, powerStatsStore); + + // Make an incompatible change of supported energy components. This will trigger + // a BatteryStats reset, which will generate a snapshot of battery stats. + mStatsRule.initMeasuredEnergyStatsLocked( + new String[]{"COMPONENT1"}); + + mStatsRule.waitForBackgroundThread(); + + verify(powerStatsStore).storeBatteryUsageStats(anyLong(), any()); + } + + @Test public void testAggregateBatteryStats_incompatibleSnapshot() { MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java index 8bdb0292bf00..296ad0e939de 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java @@ -16,6 +16,8 @@ package com.android.server.power.stats; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.anyDouble; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -28,11 +30,11 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; +import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; -import android.platform.test.ravenwood.RavenwoodRule; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; @@ -47,6 +49,8 @@ import org.junit.runners.model.Statement; import org.mockito.stubbing.Answer; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.Arrays; @SuppressWarnings("SynchronizeOnNonFinalField") @@ -59,7 +63,9 @@ public class BatteryUsageStatsRule implements TestRule { private final PowerProfile mPowerProfile; private final MockClock mMockClock = new MockClock(); - private final File mHistoryDir; + private String mTestName; + private boolean mCreateTempDirectory; + private File mHistoryDir; private MockBatteryStatsImpl mBatteryStats; private Handler mHandler; @@ -74,34 +80,33 @@ public class BatteryUsageStatsRule implements TestRule { private NetworkStats mNetworkStats; private boolean[] mSupportedStandardBuckets; private String[] mCustomPowerComponentNames; + private Throwable mThrowable; public BatteryUsageStatsRule() { - this(0, null); + this(0); } public BatteryUsageStatsRule(long currentTime) { - this(currentTime, null); - } - - public BatteryUsageStatsRule(long currentTime, File historyDir) { mHandler = mock(Handler.class); mPowerProfile = spy(new PowerProfile()); mMockClock.currentTime = currentTime; - mHistoryDir = historyDir; - - if (!RavenwoodRule.isUnderRavenwood()) { - lateInitBatteryStats(); - } - mCpusByPolicy.put(0, new int[]{0, 1, 2, 3}); mCpusByPolicy.put(4, new int[]{4, 5, 6, 7}); mFreqsByPolicy.put(0, new int[]{300000, 1000000, 2000000}); mFreqsByPolicy.put(4, new int[]{300000, 1000000, 2500000, 3000000}); } - private void lateInitBatteryStats() { + private void initBatteryStats() { if (mBatteryStats != null) return; + if (mCreateTempDirectory) { + try { + mHistoryDir = Files.createTempDirectory(mTestName).toFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + clearDirectory(); + } mBatteryStats = new MockBatteryStatsImpl(mMockClock, mHistoryDir, mHandler); mBatteryStats.setPowerProfile(mPowerProfile); mBatteryStats.setCpuScalingPolicies(new CpuScalingPolicies(mCpusByPolicy, mFreqsByPolicy)); @@ -134,6 +139,15 @@ public class BatteryUsageStatsRule implements TestRule { return mHandler; } + public File getHistoryDir() { + return mHistoryDir; + } + + public BatteryUsageStatsRule createTempDirectory() { + mCreateTempDirectory = true; + return this; + } + public BatteryUsageStatsRule setTestPowerProfile(@XmlRes int xmlId) { mPowerProfile.forceInitForTesting(InstrumentationRegistry.getContext(), xmlId); return this; @@ -265,18 +279,23 @@ public class BatteryUsageStatsRule implements TestRule { @Override public Statement apply(Statement base, Description description) { + mTestName = description.getClassName() + "#" + description.getMethodName(); return new Statement() { @Override public void evaluate() throws Throwable { before(); base.evaluate(); + after(); } }; } private void before() { - lateInitBatteryStats(); + initBatteryStats(); HandlerThread bgThread = new HandlerThread("bg thread"); + bgThread.setUncaughtExceptionHandler((thread, throwable)-> { + mThrowable = throwable; + }); bgThread.start(); mHandler = new Handler(bgThread.getLooper()); mBatteryStats.setHandler(mHandler); @@ -285,6 +304,26 @@ public class BatteryUsageStatsRule implements TestRule { mBatteryStats.getOnBatteryScreenOffTimeBase().setRunning(!mScreenOn, 0, 0); } + private void after() throws Throwable { + if (mHandler != null) { + waitForBackgroundThread(); + } + } + + public void waitForBackgroundThread() throws Throwable { + if (mThrowable != null) { + throw mThrowable; + } + + ConditionVariable done = new ConditionVariable(); + mHandler.post(done::open); + assertThat(done.block(10000)).isTrue(); + + if (mThrowable != null) { + throw mThrowable; + } + } + public PowerProfile getPowerProfile() { return mPowerProfile; } @@ -296,6 +335,9 @@ public class BatteryUsageStatsRule implements TestRule { } public MockBatteryStatsImpl getBatteryStats() { + if (mBatteryStats == null) { + initBatteryStats(); + } return mBatteryStats; } @@ -369,4 +411,19 @@ public class BatteryUsageStatsRule implements TestRule { } return null; } + + public void clearDirectory() { + clearDirectory(mHistoryDir); + } + + private void clearDirectory(File dir) { + if (dir.exists()) { + for (File child : dir.listFiles()) { + if (child.isDirectory()) { + clearDirectory(child); + } + child.delete(); + } + } + } } diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java index af5b462e017d..2ea86a4527eb 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java @@ -58,7 +58,7 @@ public class PowerStatsAggregatorTest { @Before public void setup() throws ParseException { - mHistory = new BatteryStatsHistory(32, 1024, + mHistory = new BatteryStatsHistory(1024, mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock, mMonotonicClock, mock(BatteryStatsHistory.TraceDelegate.class), null); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt index 52c7d8d2bd2e..e6c94c51d1b1 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt @@ -17,31 +17,39 @@ package com.android.server.accessibility import android.hardware.display.DisplayManagerGlobal import android.os.SystemClock +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.DisplayAdjustments import android.view.DisplayInfo import android.view.IInputFilterHost +import android.view.InputDevice.SOURCE_JOYSTICK +import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputEvent import android.view.MotionEvent +import android.view.MotionEvent.ACTION_CANCEL import android.view.MotionEvent.ACTION_DOWN -import android.view.MotionEvent.ACTION_MOVE -import android.view.MotionEvent.ACTION_UP import android.view.MotionEvent.ACTION_HOVER_ENTER import android.view.MotionEvent.ACTION_HOVER_EXIT import android.view.MotionEvent.ACTION_HOVER_MOVE +import android.view.MotionEvent.ACTION_MOVE +import android.view.MotionEvent.ACTION_UP import android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.android.cts.input.inputeventmatchers.withDeviceId import com.android.cts.input.inputeventmatchers.withMotionAction +import com.android.cts.input.inputeventmatchers.withSource import com.android.server.LocalServices import com.android.server.accessibility.magnification.MagnificationProcessor import com.android.server.wm.WindowManagerInternal import java.util.concurrent.LinkedBlockingQueue import org.hamcrest.Matchers.allOf import org.junit.After +import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test @@ -92,12 +100,17 @@ class AccessibilityInputFilterInputTest { or AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER or AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS or AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS) + const val STYLUS_SOURCE = SOURCE_STYLUS or SOURCE_TOUCHSCREEN } @Rule @JvmField val mocks: MockitoRule = MockitoJUnit.rule() + @Rule + @JvmField + val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + @Mock private lateinit var mockA11yController: WindowManagerInternal.AccessibilityControllerInternal @@ -115,6 +128,11 @@ class AccessibilityInputFilterInputTest { private lateinit var ams: AccessibilityManagerService private lateinit var a11yInputFilter: AccessibilityInputFilter private val touchDeviceId = 1 + private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) + private val stylusDeviceId = 2 + private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) + private val joystickDeviceId = 3 + private val fromJoystick = allOf(withDeviceId(joystickDeviceId), withSource(SOURCE_JOYSTICK)) @Before fun setUp() { @@ -156,23 +174,14 @@ class AccessibilityInputFilterInputTest { enableFeatures(0) val downTime = SystemClock.uptimeMillis() - val downEvent = createMotionEvent( - ACTION_DOWN, downTime, downTime, SOURCE_TOUCHSCREEN, touchDeviceId) - send(downEvent) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_DOWN), withDeviceId(touchDeviceId))) - - val moveEvent = createMotionEvent( - ACTION_MOVE, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(moveEvent) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_MOVE), withDeviceId(touchDeviceId))) - - val upEvent = createMotionEvent( - ACTION_UP, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(upEvent) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_UP), withDeviceId(touchDeviceId))) + sendTouchEvent(ACTION_DOWN, downTime, downTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_DOWN))) + + sendTouchEvent(ACTION_MOVE, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_MOVE))) + + sendTouchEvent(ACTION_UP, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_UP))) verifier.assertNoEvents() } @@ -186,28 +195,91 @@ class AccessibilityInputFilterInputTest { enableFeatures(ALL_A11Y_FEATURES) val downTime = SystemClock.uptimeMillis() - val downEvent = createMotionEvent( - ACTION_DOWN, downTime, downTime, SOURCE_TOUCHSCREEN, touchDeviceId) - send(MotionEvent.obtain(downEvent)) - + sendTouchEvent(ACTION_DOWN, downTime, downTime) // DOWN event gets transformed to HOVER_ENTER - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_HOVER_ENTER), withDeviceId(touchDeviceId))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) // MOVE becomes HOVER_MOVE - val moveEvent = createMotionEvent( - ACTION_MOVE, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(moveEvent) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_HOVER_MOVE), withDeviceId(touchDeviceId))) + sendTouchEvent(ACTION_MOVE, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_MOVE))) // UP becomes HOVER_EXIT - val upEvent = createMotionEvent( - ACTION_UP, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(upEvent) + sendTouchEvent(ACTION_UP, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_EXIT))) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_HOVER_EXIT), withDeviceId(touchDeviceId))) + verifier.assertNoEvents() + } + + /** + * Enable all a11y features and send a touchscreen stream of DOWN -> CANCEL -> DOWN events. + * These get converted into HOVER_ENTER -> HOVER_EXIT -> HOVER_ENTER events by the input filter. + */ + @Test + fun testTouchDownCancelDownWithAllA11yFeatures() { + enableFeatures(ALL_A11Y_FEATURES) + + val downTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, downTime, downTime) + // DOWN event gets transformed to HOVER_ENTER + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) + + // CANCEL becomes HOVER_EXIT + sendTouchEvent(ACTION_CANCEL, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_EXIT))) + + // DOWN again! New hover is expected + val newDownTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, newDownTime, newDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) + + verifier.assertNoEvents() + } + + /** + * Enable all a11y features and send a stylus stream of DOWN -> CANCEL -> DOWN events. + * These get converted into HOVER_ENTER -> HOVER_EXIT -> HOVER_ENTER events by the input filter. + * This test is the same as above, but for stylus events. + */ + @Test + fun testStylusDownCancelDownWithAllA11yFeatures() { + enableFeatures(ALL_A11Y_FEATURES) + + val downTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, downTime, downTime) + // DOWN event gets transformed to HOVER_ENTER + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + // CANCEL becomes HOVER_EXIT + sendStylusEvent(ACTION_CANCEL, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_EXIT))) + + // DOWN again! New hover is expected + val newDownTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, newDownTime, newDownTime) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + verifier.assertNoEvents() + } + + /** + * Enable all a11y features and send a stylus stream and then a touch stream. + */ + @Test + fun testStylusThenTouch() { + enableFeatures(ALL_A11Y_FEATURES) + + val downTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, downTime, downTime) + // DOWN event gets transformed to HOVER_ENTER + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + // CANCEL becomes HOVER_EXIT + sendStylusEvent(ACTION_CANCEL, downTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_EXIT))) + + val newDownTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, newDownTime, newDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) verifier.assertNoEvents() } @@ -223,26 +295,18 @@ class AccessibilityInputFilterInputTest { enableFeatures(ALL_A11Y_FEATURES) val downTime = SystemClock.uptimeMillis() - val downEvent = createMotionEvent( - ACTION_DOWN, downTime, downTime, SOURCE_TOUCHSCREEN, touchDeviceId) - send(MotionEvent.obtain(downEvent)) + sendTouchEvent(ACTION_DOWN, downTime, downTime) // DOWN event gets transformed to HOVER_ENTER - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_HOVER_ENTER), withDeviceId(touchDeviceId))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) verifier.assertNoEvents() enableFeatures(0) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_HOVER_EXIT), withDeviceId(touchDeviceId))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_EXIT))) verifier.assertNoEvents() - val moveEvent = createMotionEvent( - ACTION_MOVE, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(moveEvent) - val upEvent = createMotionEvent( - ACTION_UP, downTime, SystemClock.uptimeMillis(), SOURCE_TOUCHSCREEN, touchDeviceId) - send(upEvent) + sendTouchEvent(ACTION_MOVE, downTime, SystemClock.uptimeMillis()) + sendTouchEvent(ACTION_UP, downTime, SystemClock.uptimeMillis()) // As the original gesture continues, no additional events should be getting sent by the // filter because the HOVER_EXIT above already effectively finished the current gesture and // the DOWN event was never sent to the host. @@ -250,20 +314,194 @@ class AccessibilityInputFilterInputTest { // Bug: the down event was swallowed, so the remainder of the gesture should be swallowed // too. However, the MOVE and UP events are currently passed back to the dispatcher. // TODO(b/310014874) - ensure a11y sends consistent input streams to the dispatcher - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_MOVE), withDeviceId(touchDeviceId))) - verifier.assertReceivedMotion( - allOf(withMotionAction(ACTION_UP), withDeviceId(touchDeviceId))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_MOVE))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_UP))) + + verifier.assertNoEvents() + } + + /** + * Check multi-device behaviour when all a11y features are disabled. The events should pass + * through unmodified, but only from the active (first) device. + * The events from the inactive device should be dropped. + * In this test, we are injecting a touchscreen event stream and a stylus event stream, + * interleaved. + */ + @Test + @RequiresFlagsEnabled(Flags.FLAG_HANDLE_MULTI_DEVICE_INPUT) + fun testMultiDeviceEventsWithoutA11yFeatures() { + enableFeatures(0) + + val touchDownTime = SystemClock.uptimeMillis() + + // Touch device - ACTION_DOWN + sendTouchEvent(ACTION_DOWN, touchDownTime, touchDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_DOWN))) + + // Stylus device - ACTION_DOWN + val stylusDownTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, stylusDownTime, stylusDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_CANCEL))) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_DOWN))) + + // Touch device - ACTION_MOVE + sendTouchEvent(ACTION_MOVE, touchDownTime, SystemClock.uptimeMillis()) + // Touch event is dropped + verifier.assertNoEvents() + + // Stylus device - ACTION_MOVE + sendStylusEvent(ACTION_MOVE, stylusDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_MOVE))) + + // Touch device - ACTION_UP + sendTouchEvent(ACTION_UP, touchDownTime, SystemClock.uptimeMillis()) + // Touch event is dropped + verifier.assertNoEvents() + + // Stylus device - ACTION_UP + sendStylusEvent(ACTION_UP, stylusDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_UP))) verifier.assertNoEvents() } + /** + * Check multi-device behaviour when all a11y features are enabled. The events should be + * modified accordingly, like DOWN events getting converted to hovers. + * Only a single device should be active (the latest device to start a new gesture). + * In this test, we are injecting a touchscreen event stream and a stylus event stream, + * interleaved. + */ + @Test + @RequiresFlagsEnabled(Flags.FLAG_HANDLE_MULTI_DEVICE_INPUT) + fun testMultiDeviceEventsWithAllA11yFeatures() { + enableFeatures(ALL_A11Y_FEATURES) + + // Touch device - ACTION_DOWN + val touchDownTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, touchDownTime, touchDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) + + // Stylus device - ACTION_DOWN + val stylusDownTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, stylusDownTime, stylusDownTime) + // Touch is canceled and stylus is started + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_EXIT))) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + // Touch device - ACTION_MOVE + sendTouchEvent(ACTION_MOVE, touchDownTime, SystemClock.uptimeMillis()) + // Stylus is active now; touch is ignored + verifier.assertNoEvents() + + // Stylus device - ACTION_MOVE + sendStylusEvent(ACTION_MOVE, stylusDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_MOVE))) + + // Touch device - ACTION_UP + sendTouchEvent(ACTION_UP, touchDownTime, SystemClock.uptimeMillis()) + // Stylus is still active; touch is ignored + verifier.assertNoEvents() + + sendStylusEvent(ACTION_UP, stylusDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_EXIT))) + + // Now stylus is done, and a new touch gesture will work! + val newTouchDownTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, newTouchDownTime, newTouchDownTime) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) + + verifier.assertNoEvents() + } + + /** + * Check multi-device behaviour when all a11y features are enabled. The events should be + * modified accordingly, like DOWN events getting converted to hovers. + * Only a single device should be active at a given time. The touch events start and end + * while stylus is active. Check that the latest device is always given preference. + */ + @Test + @RequiresFlagsEnabled(Flags.FLAG_HANDLE_MULTI_DEVICE_INPUT) + fun testStylusWithTouchInTheMiddle() { + enableFeatures(ALL_A11Y_FEATURES) + + // Stylus device - ACTION_DOWN + val stylusDownTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, stylusDownTime, stylusDownTime) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + // Touch device - ACTION_DOWN + val touchDownTime = SystemClock.uptimeMillis() + sendTouchEvent(ACTION_DOWN, touchDownTime, touchDownTime) + // Touch DOWN causes stylus to get canceled + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_EXIT))) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_ENTER))) + + // Touch device - ACTION_MOVE + sendTouchEvent(ACTION_MOVE, touchDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_MOVE))) + + sendStylusEvent(ACTION_MOVE, stylusDownTime, SystemClock.uptimeMillis()) + // Stylus is ignored because touch is active now + verifier.assertNoEvents() + + sendTouchEvent(ACTION_UP, touchDownTime, SystemClock.uptimeMillis()) + verifier.assertReceivedMotion(allOf(fromTouchScreen, withMotionAction(ACTION_HOVER_EXIT))) + + sendStylusEvent(ACTION_UP, stylusDownTime, SystemClock.uptimeMillis()) + // The UP stylus event is also ignored + verifier.assertNoEvents() + + // Now stylus works again, because touch gesture is finished + val newStylusDownTime = SystemClock.uptimeMillis() + sendStylusEvent(ACTION_DOWN, newStylusDownTime, newStylusDownTime) + verifier.assertReceivedMotion(allOf(fromStylus, withMotionAction(ACTION_HOVER_ENTER))) + + verifier.assertNoEvents() + } + + /** + * Send some joystick events and ensure they pass through normally. + */ + @Test + fun testJoystickEvents() { + enableFeatures(ALL_A11Y_FEATURES) + + sendJoystickEvent() + verifier.assertReceivedMotion(fromJoystick) + + sendJoystickEvent() + verifier.assertReceivedMotion(fromJoystick) + + sendJoystickEvent() + verifier.assertReceivedMotion(fromJoystick) + } + private fun createStubDisplay(displayId: Int, displayInfo: DisplayInfo): Display { val display = Display(DisplayManagerGlobal.getInstance(), displayId, displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) return display } + private fun sendTouchEvent(action: Int, downTime: Long, eventTime: Long) { + if (action == ACTION_DOWN) { + assertEquals(downTime, eventTime) + } + send(createMotionEvent(action, downTime, eventTime, SOURCE_TOUCHSCREEN, touchDeviceId)) + } + + private fun sendStylusEvent(action: Int, downTime: Long, eventTime: Long) { + if (action == ACTION_DOWN) { + assertEquals(downTime, eventTime) + } + send(createMotionEvent(action, downTime, eventTime, STYLUS_SOURCE, stylusDeviceId)) + } + + private fun sendJoystickEvent() { + val time = SystemClock.uptimeMillis() + send(createMotionEvent(ACTION_MOVE, time, time, SOURCE_JOYSTICK, joystickDeviceId)) + } + private fun send(event: InputEvent) { // We need to make a copy of the event before sending it to the filter, because the filter // will recycle it, but the caller of this function might want to still be able to use diff --git a/services/tests/servicestests/src/com/android/server/accessibility/BrailleDisplayConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/BrailleDisplayConnectionTest.java index b322dd709c2d..aec3f451fac6 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/BrailleDisplayConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/BrailleDisplayConnectionTest.java @@ -17,6 +17,7 @@ package com.android.server.accessibility; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.anyInt; @@ -33,17 +34,24 @@ import android.testing.DexmakerShareClassLoaderRule; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.util.HexDump; + import com.google.common.truth.Expect; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.io.File; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -51,184 +59,265 @@ import java.util.List; * * <p>Prefer adding new tests in CTS where possible. */ +@RunWith(Enclosed.class) public class BrailleDisplayConnectionTest { - private static final Path NULL_PATH = Path.of("/dev/null"); - - private BrailleDisplayConnection mBrailleDisplayConnection; - @Mock - private BrailleDisplayConnection.NativeInterface mNativeInterface; - @Mock - private AccessibilityServiceConnection mServiceConnection; - - @Rule - public final Expect expect = Expect.create(); - - private Context mContext; - - // To mock package-private class - @Rule - public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = - new DexmakerShareClassLoaderRule(); - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mContext = InstrumentationRegistry.getInstrumentation().getContext(); - when(mServiceConnection.isConnectedLocked()).thenReturn(true); - mBrailleDisplayConnection = - spy(new BrailleDisplayConnection(new Object(), mServiceConnection)); - } - @Test - public void defaultNativeScanner_getHidrawNodePaths_returnsHidrawPaths() throws Exception { - File testDir = mContext.getFilesDir(); - Path hidrawNode0 = Path.of(testDir.getPath(), "hidraw0"); - Path hidrawNode1 = Path.of(testDir.getPath(), "hidraw1"); - Path otherDevice = Path.of(testDir.getPath(), "otherDevice"); - Path[] nodePaths = {hidrawNode0, hidrawNode1, otherDevice}; - try { - for (Path node : nodePaths) { - assertThat(node.toFile().createNewFile()).isTrue(); + public static class ScannerTest { + private static final Path NULL_PATH = Path.of("/dev/null"); + + private BrailleDisplayConnection mBrailleDisplayConnection; + @Mock + private BrailleDisplayConnection.NativeInterface mNativeInterface; + @Mock + private AccessibilityServiceConnection mServiceConnection; + + @Rule + public final Expect expect = Expect.create(); + + private Context mContext; + + // To mock package-private class + @Rule + public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = + new DexmakerShareClassLoaderRule(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + when(mServiceConnection.isConnectedLocked()).thenReturn(true); + mBrailleDisplayConnection = + spy(new BrailleDisplayConnection(new Object(), mServiceConnection)); + } + + @Test + public void defaultNativeScanner_getHidrawNodePaths_returnsHidrawPaths() throws Exception { + File testDir = mContext.getFilesDir(); + Path hidrawNode0 = Path.of(testDir.getPath(), "hidraw0"); + Path hidrawNode1 = Path.of(testDir.getPath(), "hidraw1"); + Path otherDevice = Path.of(testDir.getPath(), "otherDevice"); + Path[] nodePaths = {hidrawNode0, hidrawNode1, otherDevice}; + try { + for (Path node : nodePaths) { + assertThat(node.toFile().createNewFile()).isTrue(); + } + + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + + assertThat(scanner.getHidrawNodePaths(testDir.toPath())) + .containsExactly(hidrawNode0, hidrawNode1); + } finally { + for (Path node : nodePaths) { + node.toFile().delete(); + } } + } + + @Test + public void defaultNativeScanner_getReportDescriptor_returnsDescriptor() { + int descriptorSize = 4; + byte[] descriptor = {0xB, 0xE, 0xE, 0xF}; + when(mNativeInterface.getHidrawDescSize(anyInt())).thenReturn(descriptorSize); + when(mNativeInterface.getHidrawDesc(anyInt(), eq(descriptorSize))).thenReturn( + descriptor); BrailleDisplayConnection.BrailleDisplayScanner scanner = mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); - assertThat(scanner.getHidrawNodePaths(testDir.toPath())) - .containsExactly(hidrawNode0, hidrawNode1); - } finally { - for (Path node : nodePaths) { - node.toFile().delete(); - } + assertThat(scanner.getDeviceReportDescriptor(NULL_PATH)).isEqualTo(descriptor); } - } - @Test - public void defaultNativeScanner_getReportDescriptor_returnsDescriptor() { - int descriptorSize = 4; - byte[] descriptor = {0xB, 0xE, 0xE, 0xF}; - when(mNativeInterface.getHidrawDescSize(anyInt())).thenReturn(descriptorSize); - when(mNativeInterface.getHidrawDesc(anyInt(), eq(descriptorSize))).thenReturn(descriptor); + @Test + public void defaultNativeScanner_getReportDescriptor_invalidSize_returnsNull() { + when(mNativeInterface.getHidrawDescSize(anyInt())).thenReturn(0); - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); - assertThat(scanner.getDeviceReportDescriptor(NULL_PATH)).isEqualTo(descriptor); - } + assertThat(scanner.getDeviceReportDescriptor(NULL_PATH)).isNull(); + } - @Test - public void defaultNativeScanner_getReportDescriptor_invalidSize_returnsNull() { - when(mNativeInterface.getHidrawDescSize(anyInt())).thenReturn(0); + @Test + public void defaultNativeScanner_getUniqueId_returnsUniq() { + String macAddress = "12:34:56:78"; + when(mNativeInterface.getHidrawUniq(anyInt())).thenReturn(macAddress); - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); - assertThat(scanner.getDeviceReportDescriptor(NULL_PATH)).isNull(); - } + assertThat(scanner.getUniqueId(NULL_PATH)).isEqualTo(macAddress); + } + + @Test + public void defaultNativeScanner_getDeviceBusType_busUsb() { + when(mNativeInterface.getHidrawBusType(anyInt())) + .thenReturn(BrailleDisplayConnection.BUS_USB); - @Test - public void defaultNativeScanner_getUniqueId_returnsUniq() { - String macAddress = "12:34:56:78"; - when(mNativeInterface.getHidrawUniq(anyInt())).thenReturn(macAddress); + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + assertThat(scanner.getDeviceBusType(NULL_PATH)) + .isEqualTo(BrailleDisplayConnection.BUS_USB); + } - assertThat(scanner.getUniqueId(NULL_PATH)).isEqualTo(macAddress); - } + @Test + public void defaultNativeScanner_getDeviceBusType_busBluetooth() { + when(mNativeInterface.getHidrawBusType(anyInt())) + .thenReturn(BrailleDisplayConnection.BUS_BLUETOOTH); - @Test - public void defaultNativeScanner_getDeviceBusType_busUsb() { - when(mNativeInterface.getHidrawBusType(anyInt())) - .thenReturn(BrailleDisplayConnection.BUS_USB); + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + assertThat(scanner.getDeviceBusType(NULL_PATH)) + .isEqualTo(BrailleDisplayConnection.BUS_BLUETOOTH); + } - assertThat(scanner.getDeviceBusType(NULL_PATH)) - .isEqualTo(BrailleDisplayConnection.BUS_USB); - } + @Test + public void write_bypassesServiceSideCheckWithLargeBuffer_disconnects() { + Mockito.doNothing().when(mBrailleDisplayConnection).disconnect(); + mBrailleDisplayConnection.write( + new byte[IBinder.getSuggestedMaxIpcSizeBytes() * 2]); - @Test - public void defaultNativeScanner_getDeviceBusType_busBluetooth() { - when(mNativeInterface.getHidrawBusType(anyInt())) - .thenReturn(BrailleDisplayConnection.BUS_BLUETOOTH); + verify(mBrailleDisplayConnection).disconnect(); + } - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.getDefaultNativeScanner(mNativeInterface); + @Test + public void write_notConnected_throwsIllegalStateException() { + when(mServiceConnection.isConnectedLocked()).thenReturn(false); - assertThat(scanner.getDeviceBusType(NULL_PATH)) - .isEqualTo(BrailleDisplayConnection.BUS_BLUETOOTH); - } + assertThrows(IllegalStateException.class, + () -> mBrailleDisplayConnection.write(new byte[1])); + } - @Test - public void write_bypassesServiceSideCheckWithLargeBuffer_disconnects() { - Mockito.doNothing().when(mBrailleDisplayConnection).disconnect(); - mBrailleDisplayConnection.write( - new byte[IBinder.getSuggestedMaxIpcSizeBytes() * 2]); + @Test + public void write_unableToCreateWriteStream_disconnects() { + Mockito.doNothing().when(mBrailleDisplayConnection).disconnect(); + // mBrailleDisplayConnection#connectLocked was never called so the + // connection's mHidrawNode is still null. This will throw an exception + // when attempting to create FileOutputStream on the node. + mBrailleDisplayConnection.write(new byte[1]); - verify(mBrailleDisplayConnection).disconnect(); - } + verify(mBrailleDisplayConnection).disconnect(); + } - @Test - public void write_notConnected_throwsIllegalStateException() { - when(mServiceConnection.isConnectedLocked()).thenReturn(false); + // BrailleDisplayConnection#setTestData() is used to enable CTS testing with + // test Braille display data, but its own implementation should also be tested + // so that issues in this helper don't cause confusing failures in CTS. + + @Test + public void setTestData_scannerReturnsTestData() { + Bundle bd1 = new Bundle(), bd2 = new Bundle(); + + Path path1 = Path.of("/dev/path1"), path2 = Path.of("/dev/path2"); + bd1.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_HIDRAW_PATH, + path1.toString()); + bd2.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_HIDRAW_PATH, + path2.toString()); + byte[] desc1 = {0xB, 0xE}, desc2 = {0xE, 0xF}; + bd1.putByteArray(BrailleDisplayController.TEST_BRAILLE_DISPLAY_DESCRIPTOR, desc1); + bd2.putByteArray(BrailleDisplayController.TEST_BRAILLE_DISPLAY_DESCRIPTOR, desc2); + String uniq1 = "uniq1", uniq2 = "uniq2"; + bd1.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_UNIQUE_ID, uniq1); + bd2.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_UNIQUE_ID, uniq2); + int bus1 = BrailleDisplayConnection.BUS_USB, bus2 = + BrailleDisplayConnection.BUS_BLUETOOTH; + bd1.putBoolean(BrailleDisplayController.TEST_BRAILLE_DISPLAY_BUS_BLUETOOTH, + bus1 == BrailleDisplayConnection.BUS_BLUETOOTH); + bd2.putBoolean(BrailleDisplayController.TEST_BRAILLE_DISPLAY_BUS_BLUETOOTH, + bus2 == BrailleDisplayConnection.BUS_BLUETOOTH); - assertThrows(IllegalStateException.class, - () -> mBrailleDisplayConnection.write(new byte[1])); - } + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.setTestData(List.of(bd1, bd2)); + + expect.that(scanner.getHidrawNodePaths(Path.of("/dev"))).containsExactly(path1, path2); + expect.that(scanner.getDeviceReportDescriptor(path1)).isEqualTo(desc1); + expect.that(scanner.getDeviceReportDescriptor(path2)).isEqualTo(desc2); + expect.that(scanner.getUniqueId(path1)).isEqualTo(uniq1); + expect.that(scanner.getUniqueId(path2)).isEqualTo(uniq2); + expect.that(scanner.getDeviceBusType(path1)).isEqualTo(bus1); + expect.that(scanner.getDeviceBusType(path2)).isEqualTo(bus2); + } - @Test - public void write_unableToCreateWriteStream_disconnects() { - Mockito.doNothing().when(mBrailleDisplayConnection).disconnect(); - // mBrailleDisplayConnection#connectLocked was never called so the - // connection's mHidrawNode is still null. This will throw an exception - // when attempting to create FileOutputStream on the node. - mBrailleDisplayConnection.write(new byte[1]); + @Test + public void setTestData_emptyTestData_returnsNullNodePaths() { + BrailleDisplayConnection.BrailleDisplayScanner scanner = + mBrailleDisplayConnection.setTestData(List.of()); - verify(mBrailleDisplayConnection).disconnect(); + expect.that(scanner.getHidrawNodePaths(Path.of("/dev"))).isNull(); + } } - // BrailleDisplayConnection#setTestData() is used to enable CTS testing with - // test Braille display data, but its own implementation should also be tested - // so that issues in this helper don't cause confusing failures in CTS. - - @Test - public void setTestData_scannerReturnsTestData() { - Bundle bd1 = new Bundle(), bd2 = new Bundle(); - - Path path1 = Path.of("/dev/path1"), path2 = Path.of("/dev/path2"); - bd1.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_HIDRAW_PATH, path1.toString()); - bd2.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_HIDRAW_PATH, path2.toString()); - byte[] desc1 = {0xB, 0xE}, desc2 = {0xE, 0xF}; - bd1.putByteArray(BrailleDisplayController.TEST_BRAILLE_DISPLAY_DESCRIPTOR, desc1); - bd2.putByteArray(BrailleDisplayController.TEST_BRAILLE_DISPLAY_DESCRIPTOR, desc2); - String uniq1 = "uniq1", uniq2 = "uniq2"; - bd1.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_UNIQUE_ID, uniq1); - bd2.putString(BrailleDisplayController.TEST_BRAILLE_DISPLAY_UNIQUE_ID, uniq2); - int bus1 = BrailleDisplayConnection.BUS_USB, bus2 = BrailleDisplayConnection.BUS_BLUETOOTH; - bd1.putBoolean(BrailleDisplayController.TEST_BRAILLE_DISPLAY_BUS_BLUETOOTH, - bus1 == BrailleDisplayConnection.BUS_BLUETOOTH); - bd2.putBoolean(BrailleDisplayController.TEST_BRAILLE_DISPLAY_BUS_BLUETOOTH, - bus2 == BrailleDisplayConnection.BUS_BLUETOOTH); - - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.setTestData(List.of(bd1, bd2)); - - expect.that(scanner.getHidrawNodePaths(Path.of("/dev"))).containsExactly(path1, path2); - expect.that(scanner.getDeviceReportDescriptor(path1)).isEqualTo(desc1); - expect.that(scanner.getDeviceReportDescriptor(path2)).isEqualTo(desc2); - expect.that(scanner.getUniqueId(path1)).isEqualTo(uniq1); - expect.that(scanner.getUniqueId(path2)).isEqualTo(uniq2); - expect.that(scanner.getDeviceBusType(path1)).isEqualTo(bus1); - expect.that(scanner.getDeviceBusType(path2)).isEqualTo(bus2); - } + @RunWith(Parameterized.class) + public static class BrailleDisplayDescriptorTest { + @Parameterized.Parameters(name = "{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][]{ + {"match_BdPage", new byte[]{ + // Just one item, defines the BD page + 0x05, 0x41}}, + {"match_BdPageAfterAnotherPage", new byte[]{ + // One item defines another page + 0x05, 0x01, + // Next item defines BD page + 0x05, 0x41}}, + {"match_BdPageAfterSizeZeroItem", new byte[]{ + // Size-zero item (last 2 bits are 00) + 0x00, + // Next item defines BD page + 0x05, 0x41}}, + {"match_BdPageAfterSizeOneItem", new byte[]{ + // Size-one item (last 2 bits are 01) + 0x01, 0x7F, + // Next item defines BD page + 0x05, 0x41}}, + {"match_BdPageAfterSizeTwoItem", new byte[]{ + // Size-two item (last 2 bits are 10) + 0x02, 0x7F, 0x7F, + 0x05, 0x41}}, + {"match_BdPageAfterSizeFourItem", new byte[]{ + // Size-four item (last 2 bits are 11) + 0x03, 0x7F, 0x7F, 0x7F, 0x7F, + 0x05, 0x41}}, + {"match_BdPageInBetweenOtherPages", new byte[]{ + // One item defines another page + 0x05, 0x01, + // Next item defines BD page + 0x05, 0x41, + // Next item defines another page + 0x05, 0x02}}, + {"fail_OtherPage", new byte[]{ + // Just one item, defines another page + 0x05, 0x01}}, + {"fail_BdPageBeforeMissingData", new byte[]{ + // This item defines BD page + 0x05, 0x41, + // Next item specifies size-one item (last 2 bits are 01) but + // that one data byte is missing; this descriptor is malformed. + 0x01}}, + {"fail_BdPageWithWrongDataSize", new byte[]{ + // This item defines a page with two-byte ID 0x41 0x7F, not 0x41. + 0x06, 0x41, 0x7F}}, + {"fail_LongItem", new byte[]{ + // Item has type bits 1111, indicating Long Item. + (byte) 0xF0}}, + }); + } - @Test - public void setTestData_emptyTestData_returnsNullNodePaths() { - BrailleDisplayConnection.BrailleDisplayScanner scanner = - mBrailleDisplayConnection.setTestData(List.of()); - expect.that(scanner.getHidrawNodePaths(Path.of("/dev"))).isNull(); + @Parameterized.Parameter(0) + public String mTestName; + @Parameterized.Parameter(1) + public byte[] mDescriptor; + + @Test + public void isBrailleDisplay() { + final boolean expectedMatch = mTestName.startsWith("match_"); + assertWithMessage( + "Expected isBrailleDisplay==" + expectedMatch + + " for descriptor " + HexDump.toHexString(mDescriptor)) + .that(BrailleDisplayConnection.isBrailleDisplay(mDescriptor)) + .isEqualTo(expectedMatch); + } } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java index 009bfb7efca6..87fe6cf8f283 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java @@ -813,6 +813,18 @@ public class MagnificationConnectionManagerTest { anyBoolean()); } + @Test + public void onFullscreenMagnificationActivationChanged_hasConnection_notifyActivatedState() + throws RemoteException { + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + + mMagnificationConnectionManager + .onFullscreenMagnificationActivationChanged(TEST_DISPLAY, /* activated= */ true); + + verify(mMockConnection.getConnection()) + .onFullscreenMagnificationActivationChanged(eq(TEST_DISPLAY), eq(true)); + } + private MotionEvent generatePointersDownEvent(PointF[] pointersLocation) { final int len = pointersLocation.length; diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java index 07f3036410a0..2120b2e8e1f3 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java @@ -131,6 +131,14 @@ public class MagnificationConnectionWrapperTest { } @Test + public void onFullscreenMagnificationActivationChanged() throws RemoteException { + mConnectionWrapper + .onFullscreenMagnificationActivationChanged(TEST_DISPLAY, /* activated= */ true); + verify(mConnection) + .onFullscreenMagnificationActivationChanged(eq(TEST_DISPLAY), eq(true)); + } + + @Test public void setMirrorWindowCallback() throws RemoteException { mConnectionWrapper.setConnectionCallback(mCallback); verify(mConnection).setConnectionCallback(mCallback); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java index a0c4b5e26c3f..1a51c45e2ef6 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java @@ -53,6 +53,10 @@ import android.hardware.display.DisplayManagerInternal; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.testing.DexmakerShareClassLoaderRule; @@ -73,6 +77,7 @@ import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accessibility.AccessibilityTraceManager; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.wm.WindowManagerInternal; +import com.android.window.flags.Flags; import org.junit.After; import org.junit.Before; @@ -91,6 +96,9 @@ import org.mockito.stubbing.Answer; @RunWith(AndroidJUnit4.class) public class MagnificationControllerTest { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private static final int TEST_SERVICE_ID = 1; private static final Region INITIAL_SCREEN_MAGNIFICATION_REGION = @@ -1263,6 +1271,27 @@ public class MagnificationControllerTest { verify(mService).changeMagnificationMode(TEST_DISPLAY, MODE_WINDOW); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_MAGNIFICATION_ALWAYS_DRAW_FULLSCREEN_BORDER) + public void onFullscreenMagnificationActivationState_systemUiBorderFlagOn_notifyConnection() { + mMagnificationController.onFullScreenMagnificationActivationState( + TEST_DISPLAY, /* activated= */ true); + + verify(mMagnificationConnectionManager) + .onFullscreenMagnificationActivationChanged(TEST_DISPLAY, /* activated= */ true); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_MAGNIFICATION_ALWAYS_DRAW_FULLSCREEN_BORDER) + public void + onFullscreenMagnificationActivationState_systemUiBorderFlagOff_neverNotifyConnection() { + mMagnificationController.onFullScreenMagnificationActivationState( + TEST_DISPLAY, /* activated= */ true); + + verify(mMagnificationConnectionManager, never()) + .onFullscreenMagnificationActivationChanged(TEST_DISPLAY, /* activated= */ true); + } + private void setMagnificationEnabled(int mode) throws RemoteException { setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y); } diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 5c6f3c92204a..b1e62f9c9a82 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -149,6 +149,7 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; @@ -205,6 +206,7 @@ import libcore.io.Streams; import org.junit.After; import org.junit.Assume; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.MethodRule; @@ -1619,6 +1621,12 @@ public class NetworkPolicyManagerServiceTest { verify(mActivityManagerInternal).notifyNetworkPolicyRulesUpdated(UID_A, procStateSeq); } + private void callAndWaitOnUidGone(int uid) throws Exception { + // The disabled argument is used only for ephemeral apps and does not matter here. + mUidObserver.onUidGone(uid, false /* disabled */); + waitForUidEventHandlerIdle(); + } + private void callAndWaitOnUidStateChanged(int uid, int procState, long procStateSeq) throws Exception { callAndWaitOnUidStateChanged(uid, procState, procStateSeq, @@ -2143,12 +2151,14 @@ public class NetworkPolicyManagerServiceTest { assertFalse(mService.isUidNetworkingBlocked(UID_E, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainEnabled() throws Exception { verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnProcStateChange() throws Exception { @@ -2178,6 +2188,7 @@ public class NetworkPolicyManagerServiceTest { assertTrue(mService.isUidNetworkingBlocked(UID_A, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnAllowlistChange() throws Exception { @@ -2216,6 +2227,7 @@ public class NetworkPolicyManagerServiceTest { assertFalse(mService.isUidNetworkingBlocked(UID_B, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnTempAllowlistChange() throws Exception { @@ -2245,6 +2257,16 @@ public class NetworkPolicyManagerServiceTest { assertTrue(mService.isUidNetworkingBlocked(UID_A, false)); } + private boolean isUidState(int uid, int procState, int procStateSeq, int capability) { + final NetworkPolicyManager.UidState uidState = mService.getUidStateForTest(uid); + if (uidState == null) { + return false; + } + return uidState.uid == uid && uidState.procStateSeq == procStateSeq + && uidState.procState == procState && uidState.capability == capability; + } + + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testUidObserverFiltersProcStateChanges() throws Exception { @@ -2307,6 +2329,7 @@ public class NetworkPolicyManagerServiceTest { waitForUidEventHandlerIdle(); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testUidObserverFiltersStaleChanges() throws Exception { @@ -2327,6 +2350,7 @@ public class NetworkPolicyManagerServiceTest { waitForUidEventHandlerIdle(); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testUidObserverFiltersCapabilityChanges() throws Exception { @@ -2363,6 +2387,31 @@ public class NetworkPolicyManagerServiceTest { } @Test + public void testUidStateChangeAfterUidGone() throws Exception { + final int testProcStateSeq = 51; + final int testProcState = PROCESS_STATE_IMPORTANT_FOREGROUND; + + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // First callback for uid. + callOnUidStatechanged(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + assertTrue(isUidState(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE)); + + callAndWaitOnUidGone(UID_B); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Even though the procState is the same, the uid had exited - so this should be + // processed as a fresh callback. + callOnUidStatechanged(UID_B, testProcState, testProcStateSeq + 1, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + assertTrue(isUidState(UID_B, testProcState, testProcStateSeq + 1, PROCESS_CAPABILITY_NONE)); + } + + @Test public void testLowPowerStandbyAllowlist() throws Exception { // Chain background is also enabled but these procstates are important enough to be exempt. callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_TOP, 0); diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index 81df597f3f33..3e748ffb37e9 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -75,6 +75,7 @@ import android.content.pm.SigningDetails; import android.content.pm.SigningInfo; import android.content.pm.UserInfo; import android.content.pm.UserPackage; +import android.content.pm.UserProperties; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.drawable.Icon; @@ -776,6 +777,15 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { new UserInfo(USER_P1, "userP1", UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE), 0); + protected static final UserProperties USER_PROPERTIES_0 = + new UserProperties.Builder().setItemsRestrictedOnHomeScreen(false).build(); + + protected static final UserProperties USER_PROPERTIES_10 = + new UserProperties.Builder().setItemsRestrictedOnHomeScreen(false).build(); + + protected static final UserProperties USER_PROPERTIES_11 = + new UserProperties.Builder().setItemsRestrictedOnHomeScreen(true).build(); + protected BiPredicate<String, Integer> mDefaultLauncherChecker = (callingPackage, userId) -> LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage) @@ -817,6 +827,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { = new HashMap<>(); protected final Map<Integer, UserInfo> mUserInfos = new HashMap<>(); + protected final Map<Integer, UserProperties> mUserProperties = new HashMap<>(); protected final Map<Integer, Boolean> mRunningUsers = new HashMap<>(); protected final Map<Integer, Boolean> mUnlockedUsers = new HashMap<>(); @@ -911,6 +922,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { mUserInfos.put(USER_11, USER_INFO_11); mUserInfos.put(USER_P0, USER_INFO_P0); mUserInfos.put(USER_P1, USER_INFO_P1); + mUserProperties.put(USER_0, USER_PROPERTIES_0); + mUserProperties.put(USER_10, USER_PROPERTIES_10); + mUserProperties.put(USER_11, USER_PROPERTIES_11); when(mMockUserManagerInternal.isUserUnlockingOrUnlocked(anyInt())) .thenAnswer(inv -> { @@ -959,6 +973,15 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { inv -> mUserInfos.get((Integer) inv.getArguments()[0]))); when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn( ActivityManager.PROCESS_STATE_CACHED_EMPTY); + when(mMockUserManagerInternal.getUserProperties(anyInt())) + .thenAnswer(inv -> { + final int userId = (Integer) inv.getArguments()[0]; + final UserProperties userProperties = mUserProperties.get(userId); + if (userProperties == null) { + return new UserProperties.Builder().build(); + } + return userProperties; + }); // User 0 and P0 are always running mRunningUsers.put(USER_0, true); diff --git a/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java b/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java index f5c6795484fa..771a76517b22 100644 --- a/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java +++ b/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java @@ -92,7 +92,7 @@ public class SearchablesTest { public void testNonSearchable() { // test basic array & hashmap Searchables searchables = new Searchables(mContext, 0); - searchables.updateSearchableList(); + searchables.updateSearchableListIfNeeded(); // confirm that we return null for non-searchy activities ComponentName nonActivity = new ComponentName("com.android.frameworks.servicestests", @@ -121,7 +121,7 @@ public class SearchablesTest { doReturn(true).when(mPackageManagerInternal).canAccessComponent(anyInt(), any(), anyInt()); Searchables searchables = new Searchables(mContext, 0); - searchables.updateSearchableList(); + searchables.updateSearchableListIfNeeded(); // tests with "real" searchables (deprecate, this should be a unit test) ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList(); int count = searchablesList.size(); @@ -139,7 +139,7 @@ public class SearchablesTest { doReturn(false).when(mPackageManagerInternal).canAccessComponent(anyInt(), any(), anyInt()); Searchables searchables = new Searchables(mContext, 0); - searchables.updateSearchableList(); + searchables.updateSearchableListIfNeeded(); ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList(); assertNotNull(searchablesList); MoreAsserts.assertEmpty(searchablesList); diff --git a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java index 65662d6b30b8..2039f93b9c40 100644 --- a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java +++ b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java @@ -83,6 +83,13 @@ public class TestSystemImpl implements SystemInterface { } } + @Override + public void installExistingPackageForAllUsers(Context context, String packageName) { + for (int userId : mUsers) { + installPackageForUser(packageName, userId); + } + } + private void enablePackageForUser(String packageName, boolean enable, int userId) { Map<Integer, PackageInfo> userPackages = mPackages.get(packageName); if (userPackages == null) { @@ -93,6 +100,17 @@ public class TestSystemImpl implements SystemInterface { setPackageInfoForUser(userId, packageInfo); } + private void installPackageForUser(String packageName, int userId) { + Map<Integer, PackageInfo> userPackages = mPackages.get(packageName); + if (userPackages == null) { + return; + } + PackageInfo packageInfo = userPackages.get(userId); + packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; + packageInfo.applicationInfo.privateFlags &= (~ApplicationInfo.PRIVATE_FLAG_HIDDEN); + setPackageInfoForUser(userId, packageInfo); + } + @Override public boolean systemIsDebuggable() { return mIsDebuggable; } diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java index 5a06327fdde3..53c172a191b6 100644 --- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java @@ -1549,6 +1549,31 @@ public class WebViewUpdateServiceTest { Matchers.anyObject(), Mockito.eq(testPackage), Mockito.eq(true)); } + @Test + @RequiresFlagsEnabled("android.webkit.update_service_v2") + public void testDefaultWebViewPackageInstalling() { + String testPackage = "testDefault"; + WebViewProviderInfo[] packages = + new WebViewProviderInfo[] { + new WebViewProviderInfo( + testPackage, + "", + true /* default available */, + false /* fallback */, + null) + }; + setupWithPackages(packages); + mTestSystemImpl.setPackageInfo( + createPackageInfo( + testPackage, true /* enabled */, true /* valid */, false /* installed */)); + + // Check that the boot time logic tries to install the default package. + runWebViewBootPreparationOnMainSync(); + Mockito.verify(mTestSystemImpl) + .installExistingPackageForAllUsers( + Matchers.anyObject(), Mockito.eq(testPackage)); + } + private void testDefaultPackageChosen(PackageInfo packageInfo) { WebViewProviderInfo[] packages = new WebViewProviderInfo[] { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 92dad2598538..715c9d4081b2 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -5842,6 +5842,30 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testStats_DirectReplyLifetimeExtendedPostsUpdate() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(r); + + mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); + waitForIdle(); + + assertThat(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()) + .isTrue(); + // Checks that a post update is sent. + verify(mWorkerHandler, times(1)) + .post(any(NotificationManagerService.PostNotificationRunnable.class)); + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(), + anyBoolean()); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo( + FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY); + } + + @Test public void testStats_updatedOnUserExpansion() throws Exception { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); @@ -8507,6 +8531,36 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testStats_SmartReplyAlreadyLifetimeExtendedPostsUpdate() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final int replyIndex = 2; + final String reply = "Hello"; + final boolean modifiedBeforeSending = true; + final boolean generatedByAssistant = true; + + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + r.setSuggestionsGeneratedByAssistant(generatedByAssistant); + mService.addNotification(r); + + mService.mNotificationDelegate.onNotificationSmartReplySent( + r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, + modifiedBeforeSending); + waitForIdle(); + + // Checks that a post update is sent. + verify(mWorkerHandler, times(1)) + .post(any(NotificationManagerService.PostNotificationRunnable.class)); + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(), + anyBoolean()); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo( + FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY); + } + + @Test public void testOnNotificationActionClick() { final int actionIndex = 2; final Notification.Action action = @@ -8537,6 +8591,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final Notification.Action action = new Notification.Action.Builder(null, "text", PendingIntent.getActivity( mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); + final boolean generatedByAssistant = false; + // Creates a notification marked as being lifetime extended. NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; @@ -8550,6 +8606,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // The flag is removed, so the notification is no longer lifetime extended. assertThat(r.getSbn().getNotification().flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0); + + // The record is sent out without the flag. + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mAssistants, times(1)).notifyAssistantActionClicked( + captor.capture(), eq(action), eq(generatedByAssistant)); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0); } @Test @@ -11944,7 +12008,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // style + self managed call - bypasses block when(mTelecomManager.isInSelfManagedCall( - r.getSbn().getPackageName(), r.getUser(), true)).thenReturn(true); + r.getSbn().getPackageName(), true)).thenReturn(true); assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue(); @@ -12027,7 +12091,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // style + self managed call - bypasses block mService.clearNotifications(); reset(mUsageStats); - when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser(), true)) + when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), true)) .thenReturn(true); mService.addEnqueuedNotification(r); 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 8c50ef406ec6..8c2fd1013056 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -4420,13 +4420,13 @@ public class ZenModeHelperTest extends UiServiceTestCase { @EnableFlags(Flags.FLAG_MODES_API) public void updateAutomaticZenRule_nullDeviceEffectsUpdate() { // Adds a starting rule with empty zen policies and device effects + ZenDeviceEffects zde = new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(); AutomaticZenRule azrBase = new AutomaticZenRule.Builder(NAME, CONDITION_ID) - .setDeviceEffects(new ZenDeviceEffects.Builder().build()) + .setDeviceEffects(zde) .build(); // Adds the rule using the app, to avoid having any user modified bits set. String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), azrBase, UPDATE_ORIGIN_APP, "reason", Process.SYSTEM_UID); - AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId); AutomaticZenRule azr = new AutomaticZenRule.Builder(azrBase) // Sets Device Effects to null @@ -4437,10 +4437,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { // user modified, it can be updated. mZenModeHelper.updateAutomaticZenRule(ruleId, azr, UPDATE_ORIGIN_APP, "reason", Process.SYSTEM_UID); - rule = mZenModeHelper.getAutomaticZenRule(ruleId); + AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId); - // When AZR's ZenDeviceEffects is null, the updated rule's device effects will be null. - assertThat(rule.getDeviceEffects()).isNull(); + // When AZR's ZenDeviceEffects is null, the updated rule's device effects are kept. + assertThat(rule.getDeviceEffects()).isEqualTo(zde); } @Test diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java index b431888a72fb..3e59878f9e1e 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java @@ -35,8 +35,8 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContextWrapper; import android.content.pm.PackageManagerInternal; +import android.os.ExternalVibrationScale; import android.os.Handler; -import android.os.IExternalVibratorService; import android.os.PowerManagerInternal; import android.os.UserHandle; import android.os.VibrationAttributes; @@ -49,6 +49,7 @@ import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibrationEffectSegment; +import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; @@ -119,29 +120,65 @@ public class VibrationScalerTest { public void testGetExternalVibrationScale() { setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); - assertEquals(IExternalVibratorService.SCALE_VERY_HIGH, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_VERY_HIGH, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM); - assertEquals(IExternalVibratorService.SCALE_HIGH, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_HIGH, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW); - assertEquals(IExternalVibratorService.SCALE_NONE, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_NONE, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM); - assertEquals(IExternalVibratorService.SCALE_LOW, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_LOW, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH); - assertEquals(IExternalVibratorService.SCALE_VERY_LOW, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_VERY_LOW, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF); // Vibration setting being bypassed will use default setting and not scale. - assertEquals(IExternalVibratorService.SCALE_NONE, - mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH)); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_NONE, + mVibrationScaler.getExternalVibrationScaleLevel(USAGE_TOUCH)); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + public void testAdaptiveHapticsScale_withAdaptiveHapticsAvailable() { + setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); + setDefaultIntensity(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_LOW); + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); + + mVibrationScaler.updateAdaptiveHapticsScale(USAGE_TOUCH, 0.5f); + mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.2f); + + assertEquals(0.5f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_TOUCH)); + assertEquals(0.2f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_RINGTONE)); + assertEquals(1f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_NOTIFICATION)); + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF); + // Vibration setting being bypassed will apply adaptive haptics scales. + assertEquals(0.2f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_RINGTONE)); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + public void testAdaptiveHapticsScale_flagDisabled_adaptiveHapticScaleAlwaysNone() { + setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); + setDefaultIntensity(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_LOW); + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); + + mVibrationScaler.updateAdaptiveHapticsScale(USAGE_TOUCH, 0.5f); + mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.2f); + + assertEquals(1f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_TOUCH)); + assertEquals(1f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_RINGTONE)); + assertEquals(1f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_NOTIFICATION)); } @Test diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java index 2823223e4859..0d5bf95d959d 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * 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. @@ -35,7 +35,6 @@ import static org.mockito.Mockito.when; import android.content.ComponentName; import android.content.pm.PackageManagerInternal; import android.frameworks.vibrator.ScaleParam; -import android.frameworks.vibrator.VibrationParam; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -55,8 +54,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -70,6 +67,7 @@ public class VibratorControlServiceTest { @Mock private PackageManagerInternal mPackageManagerInternalMock; + private TestLooper mTestLooper; private FakeVibratorController mFakeVibratorController; private VibratorControlService mVibratorControlService; private VibrationSettings mVibrationSettings; @@ -77,6 +75,7 @@ public class VibratorControlServiceTest { @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); LocalServices.removeServiceForTest(PackageManagerInternal.class); @@ -86,7 +85,7 @@ public class VibratorControlServiceTest { mVibrationSettings = new VibrationSettings( ApplicationProvider.getApplicationContext(), new Handler(testLooper.getLooper())); - mFakeVibratorController = new FakeVibratorController(); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); mVibratorControlService = new VibratorControlService(new VibratorControllerHolder(), mMockVibrationScaler, mVibrationSettings, mLock); } @@ -111,13 +110,13 @@ public class VibratorControlServiceTest { @Test public void testUnregisterVibratorController_providingAnInvalidController_ignoresRequest() throws RemoteException { - FakeVibratorController fakeController1 = new FakeVibratorController(); - FakeVibratorController fakeController2 = new FakeVibratorController(); - mVibratorControlService.registerVibratorController(fakeController1); - mVibratorControlService.unregisterVibratorController(fakeController2); + FakeVibratorController controller1 = new FakeVibratorController(mTestLooper.getLooper()); + FakeVibratorController controller2 = new FakeVibratorController(mTestLooper.getLooper()); + mVibratorControlService.registerVibratorController(controller1); + mVibratorControlService.unregisterVibratorController(controller2); verifyZeroInteractions(mMockVibrationScaler); - assertThat(fakeController1.isLinkedToDeath).isTrue(); + assertThat(controller1.isLinkedToDeath).isTrue(); } @Test @@ -135,7 +134,7 @@ public class VibratorControlServiceTest { vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); mVibratorControlService.onRequestVibrationParamsComplete(token, - generateVibrationParams(vibrationScales)); + VibrationParamGenerator.generateVibrationParams(vibrationScales)); verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_ALARM, 0.7f); verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_NOTIFICATION, 0.4f); @@ -162,7 +161,7 @@ public class VibratorControlServiceTest { vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); mVibratorControlService.onRequestVibrationParamsComplete(new Binder(), - generateVibrationParams(vibrationScales)); + VibrationParamGenerator.generateVibrationParams(vibrationScales)); verifyZeroInteractions(mMockVibrationScaler); } @@ -175,7 +174,8 @@ public class VibratorControlServiceTest { vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f); vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); - mVibratorControlService.setVibrationParams(generateVibrationParams(vibrationScales), + mVibratorControlService.setVibrationParams( + VibrationParamGenerator.generateVibrationParams(vibrationScales), mFakeVibratorController); verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_ALARM, 0.7f); @@ -193,7 +193,8 @@ public class VibratorControlServiceTest { vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f); vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); - mVibratorControlService.setVibrationParams(generateVibrationParams(vibrationScales), + mVibratorControlService.setVibrationParams( + VibrationParamGenerator.generateVibrationParams(vibrationScales), mFakeVibratorController); verifyZeroInteractions(mMockVibrationScaler); @@ -268,28 +269,6 @@ public class VibratorControlServiceTest { } } - private VibrationParam[] generateVibrationParams(SparseArray<Float> vibrationScales) { - List<VibrationParam> vibrationParamList = new ArrayList<>(); - for (int i = 0; i < vibrationScales.size(); i++) { - int type = vibrationScales.keyAt(i); - float scale = vibrationScales.valueAt(i); - - vibrationParamList.add(generateVibrationParam(type, scale)); - } - - return vibrationParamList.toArray(new VibrationParam[0]); - } - - private VibrationParam generateVibrationParam(int type, float scale) { - ScaleParam scaleParam = new ScaleParam(); - scaleParam.typesMask = type; - scaleParam.scale = scale; - VibrationParam vibrationParam = new VibrationParam(); - vibrationParam.setScale(scaleParam); - - return vibrationParam; - } - private int buildVibrationTypesMask(int... types) { int typesMask = 0; for (int type : types) { diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java index 79abe21a301d..db823d649cb6 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java @@ -18,23 +18,26 @@ package com.android.server.vibrator; import static com.google.common.truth.Truth.assertThat; -import android.os.RemoteException; +import android.os.test.TestLooper; import org.junit.Before; import org.junit.Test; public class VibratorControllerHolderTest { - private final FakeVibratorController mFakeVibratorController = new FakeVibratorController(); + private TestLooper mTestLooper; + private FakeVibratorController mFakeVibratorController; private VibratorControllerHolder mVibratorControllerHolder; @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); mVibratorControllerHolder = new VibratorControllerHolder(); } @Test - public void testSetVibratorController_linksVibratorControllerToDeath() throws RemoteException { + public void testSetVibratorController_linksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); assertThat(mVibratorControllerHolder.getVibratorController()) .isEqualTo(mFakeVibratorController); @@ -42,8 +45,7 @@ public class VibratorControllerHolderTest { } @Test - public void testSetVibratorController_setControllerToNull_unlinksVibratorControllerToDeath() - throws RemoteException { + public void testSetVibratorController_setControllerToNull_unlinksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); mVibratorControllerHolder.setVibratorController(null); assertThat(mFakeVibratorController.isLinkedToDeath).isFalse(); @@ -51,8 +53,7 @@ public class VibratorControllerHolderTest { } @Test - public void testBinderDied_withValidController_unlinksVibratorControllerToDeath() - throws RemoteException { + public void testBinderDied_withValidController_unlinksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); mVibratorControllerHolder.binderDied(mFakeVibratorController); assertThat(mFakeVibratorController.isLinkedToDeath).isFalse(); @@ -60,10 +61,10 @@ public class VibratorControllerHolderTest { } @Test - public void testBinderDied_withInvalidController_ignoresRequest() - throws RemoteException { + public void testBinderDied_withInvalidController_ignoresRequest() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); - FakeVibratorController imposterVibratorController = new FakeVibratorController(); + FakeVibratorController imposterVibratorController = + new FakeVibratorController(mTestLooper.getLooper()); mVibratorControllerHolder.binderDied(imposterVibratorController); assertThat(mFakeVibratorController.isLinkedToDeath).isTrue(); assertThat(mVibratorControllerHolder.getVibratorController()) diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index 7db707a42ff0..d2ad61f2ba9f 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -50,6 +50,7 @@ import android.content.ContextWrapper; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.res.Resources; +import android.frameworks.vibrator.ScaleParam; import android.hardware.input.IInputManager; import android.hardware.input.InputManager; import android.hardware.input.InputManagerGlobal; @@ -59,16 +60,17 @@ import android.media.AudioAttributes; import android.media.AudioManager; import android.os.CombinedVibration; import android.os.ExternalVibration; +import android.os.ExternalVibrationScale; import android.os.Handler; import android.os.IBinder; import android.os.IExternalVibrationController; -import android.os.IExternalVibratorService; import android.os.IVibratorStateListener; import android.os.Looper; import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.Process; +import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.VibrationAttributes; @@ -82,6 +84,10 @@ import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibrationEffectSegment; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.util.SparseArray; @@ -91,7 +97,6 @@ import android.view.InputDevice; import android.view.flags.Flags; import androidx.test.InstrumentationRegistry; -import androidx.test.filters.FlakyTest; import com.android.internal.app.IBatteryStats; import com.android.internal.util.FrameworkStatsLog; @@ -111,6 +116,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -122,9 +128,7 @@ import java.util.function.Predicate; public class VibratorManagerServiceTest { private static final int TEST_TIMEOUT_MILLIS = 1_000; - // Time to allow for a cancellation to complete (notably including system ramp down), but not so - // long that tests easily get really slow or flaky. If a vibration is close to this, it should - // be cancelled in the body of the individual test. + // Time to allow for a cancellation to complete and the vibrators to become idle. private static final int CLEANUP_TIMEOUT_MILLIS = 100; private static final int UID = Process.ROOT_UID; private static final int VIRTUAL_DEVICE_ID = 1; @@ -153,6 +157,8 @@ public class VibratorManagerServiceTest { public MockitoRule rule = MockitoJUnit.rule(); @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -178,15 +184,17 @@ public class VibratorManagerServiceTest { private AudioManager mAudioManagerMock; private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>(); - - private SparseArray<VibrationEffect> mHapticFeedbackVibrationMap = new SparseArray<>(); + private final SparseArray<VibrationEffect> mHapticFeedbackVibrationMap = new SparseArray<>(); + private final List<HalVibration> mPendingVibrations = new ArrayList<>(); private VibratorManagerService mService; private Context mContextSpy; private TestLooper mTestLooper; private FakeVibrator mVibrator; + private FakeVibratorController mFakeVibratorController; private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener; private VibratorManagerService.ExternalVibratorService mExternalVibratorService; + private VibratorControlService mVibratorControlService; private VibrationConfig mVibrationConfig; private InputManagerGlobal.TestSession mInputManagerGlobalSession; private InputManager mInputManager; @@ -197,6 +205,7 @@ public class VibratorManagerServiceTest { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock); mVibrationConfig = new VibrationConfig(mContextSpy.getResources()); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); when(mContextSpy.getContentResolver()).thenReturn(contentResolver); @@ -242,12 +251,15 @@ public class VibratorManagerServiceTest { @After public void tearDown() throws Exception { if (mService != null) { - // Wait until all vibrators have stopped vibrating, with a bit of flexibility for tests - // that just do a click or have cancelled at the end (waiting for ramp-down). - // - // Note: if a test is flaky here, check whether a VibrationEffect duration is close to - // CLEANUP_TIMEOUT_MILLIS - in which case it's probably best to just cancel that effect - // explicitly at the end of the test case (rather than letting it run and race flakily). + if (!mPendingVibrations.stream().allMatch(HalVibration::hasEnded)) { + // Cancel any pending vibration from tests. + cancelVibrate(mService); + for (HalVibration vibration : mPendingVibrations) { + vibration.waitForEnd(); + } + } + // Wait until all vibrators have stopped vibrating, waiting for ramp-down. + // Note: if a test is flaky here something is wrong with the vibration finalization. assertTrue(waitUntil(s -> { for (int vibratorId : mService.getVibratorIds()) { if (s.isVibrating(vibratorId)) { @@ -255,7 +267,7 @@ public class VibratorManagerServiceTest { } } return true; - }, mService, CLEANUP_TIMEOUT_MILLIS)); + }, mService, mVibrationConfig.getRampDownDurationMs() + CLEANUP_TIMEOUT_MILLIS)); } LocalServices.removeServiceForTest(PackageManagerInternal.class); @@ -310,20 +322,31 @@ public class VibratorManagerServiceTest { if (service instanceof VibratorManagerService.ExternalVibratorService) { mExternalVibratorService = (VibratorManagerService.ExternalVibratorService) service; + } else if (service instanceof VibratorControlService) { + mVibratorControlService = (VibratorControlService) service; + mFakeVibratorController.setVibratorControlService( + mVibratorControlService); } } + @Override HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider( Resources resources, VibratorInfo vibratorInfo) { return new HapticFeedbackVibrationProvider( resources, vibratorInfo, mHapticFeedbackVibrationMap); } + @Override VibratorControllerHolder createVibratorControllerHolder() { VibratorControllerHolder holder = new VibratorControllerHolder(); - holder.setVibratorController(new FakeVibratorController()); + holder.setVibratorController(mFakeVibratorController); return holder; } + + @Override + boolean isServiceDeclared(String name) { + return true; + } }); return mService; } @@ -469,8 +492,9 @@ public class VibratorManagerServiceTest { InOrder inOrderVerifier = inOrder(listenerMock); // First notification done when listener is registered. inOrderVerifier.verify(listenerMock).onVibrating(eq(false)); + // Vibrator on notification done before vibration ended, no need to wait. inOrderVerifier.verify(listenerMock).onVibrating(eq(true)); - // The last notification is after the vibration has completed. + // Vibrator off notification done after vibration completed, wait for notification. inOrderVerifier.verify(listenerMock, timeout(TEST_TIMEOUT_MILLIS)).onVibrating(eq(false)); inOrderVerifier.verifyNoMoreInteractions(); @@ -500,6 +524,7 @@ public class VibratorManagerServiceTest { InOrder inOrderVerifier = inOrder(listenerMock); // First notification done when listener is registered. inOrderVerifier.verify(listenerMock).onVibrating(eq(false)); + // Vibrator on notification done before vibration ended, no need to wait. inOrderVerifier.verify(listenerMock).onVibrating(eq(true)); inOrderVerifier.verify(listenerMock, atLeastOnce()).asBinder(); // unregister inOrderVerifier.verifyNoMoreInteractions(); @@ -524,7 +549,6 @@ public class VibratorManagerServiceTest { verify(listeners[0]).onVibrating(eq(true)); verify(listeners[1]).onVibrating(eq(true)); verify(listeners[2], never()).onVibrating(eq(true)); - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -872,21 +896,24 @@ public class VibratorManagerServiceTest { eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); } - @FlakyTest @Test public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); - vibrate(service, repeatingEffect, new VibrationAttributes.Builder().setUsage( - VibrationAttributes.USAGE_UNKNOWN).build()); + new long[]{10, 10_000}, new int[]{128, 255}, 1); + vibrate(service, repeatingEffect, + new VibrationAttributes.Builder() + .setUsage(VibrationAttributes.USAGE_UNKNOWN) + .build()); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), HAPTIC_FEEDBACK_ATTRS); @@ -897,9 +924,8 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // No segment played is the prebaked CLICK from the second vibration. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up repeating effect. } @Test @@ -913,11 +939,13 @@ public class VibratorManagerServiceTest { VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until the off waveform step. - assertTrue(waitUntil(s -> fakeVibrator.getOffCount() > 0, service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); // Cancel vibration right before requesting a new one. // This should trigger slow IVibrator.off before setting the vibration status to cancelled. @@ -925,6 +953,8 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS); + // The second vibration should have recorded that the vibrators were turned on. + verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // Check that second vibration was played. assertTrue(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); @@ -934,45 +964,47 @@ public class VibratorManagerServiceTest { public void vibrate_withNewSameImportanceVibrationAndBothRepeating_cancelsOngoingEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{255, 128}, 1); vibrate(service, repeatingEffect2, ALARM_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2, - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 4, service, + TEST_TIMEOUT_MILLIS)); // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); - - cancelVibrate(service); // Clean up repeating effect. } - @FlakyTest @Test public void vibrate_withNewSameImportanceVibrationButOngoingIsRepeating_ignoreNewVibration() throws Exception { mockVibrators(1); FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(), service, + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -981,53 +1013,55 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withNewUnknownUsageVibrationAndRepeating_cancelsOngoingEffect() throws Exception { mockVibrators(1); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{255, 128}, 1); vibrate(service, repeatingEffect2, UNKNOWN_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2, - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 4, service, + TEST_TIMEOUT_MILLIS)); // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); - - cancelVibrate(service); // Clean up repeating effect. } - @FlakyTest @Test public void vibrate_withNewUnknownUsageVibrationAndNotRepeating_ignoreNewVibration() throws Exception { mockVibrators(1); FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect alarmEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, alarmEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(), service, + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -1036,23 +1070,24 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withOngoingHigherImportanceVibration_ignoresEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, effect, ALARM_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -1061,26 +1096,27 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withOngoingLowerImportanceVibration_cancelsOngoingEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS); @@ -1088,10 +1124,8 @@ public class VibratorManagerServiceTest { // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // One segment played is the prebaked CLICK from the second vibration. - assertEquals(1, - mVibratorProviders.get(1).getAllEffectSegments().stream() - .filter(PrebakedSegment.class::isInstance) - .count()); + assertEquals(1, fakeVibrator.getAllEffectSegments().stream() + .filter(PrebakedSegment.class::isInstance).count()); } @Test @@ -1108,12 +1142,13 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, controller, firstToken); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // The external vibration should have been cancelled verify(controller).mute(); assertEquals(Arrays.asList(false, true, false), @@ -1121,10 +1156,8 @@ public class VibratorManagerServiceTest { // The new vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // One segment played is the prebaked CLICK from the new vibration. - assertEquals(1, - mVibratorProviders.get(1).getAllEffectSegments().stream() - .filter(PrebakedSegment.class::isInstance) - .count()); + assertEquals(1, mVibratorProviders.get(1).getAllEffectSegments().stream() + .filter(PrebakedSegment.class::isInstance).count()); } @Test @@ -1135,8 +1168,9 @@ public class VibratorManagerServiceTest { .build(); mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( @@ -1155,7 +1189,7 @@ public class VibratorManagerServiceTest { verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // One step segment (with several amplitudes) and one click should have played. Notably // there is no primitive segment. - List<VibrationEffectSegment> played = mVibratorProviders.get(1).getAllEffectSegments(); + List<VibrationEffectSegment> played = fakeVibrator.getAllEffectSegments(); assertEquals(2, played.size()); assertEquals(1, played.stream().filter(StepSegment.class::isInstance).count()); assertEquals(1, played.stream().filter(PrebakedSegment.class::isInstance).count()); @@ -1164,8 +1198,9 @@ public class VibratorManagerServiceTest { @Test public void vibrate_withInputDevices_vibratesInputDevices() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); when(mIInputManagerMock.getVibratorIds(eq(1))).thenReturn(new int[]{1}); when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); @@ -1180,7 +1215,7 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS); verify(mIInputManagerMock).vibrateCombined(eq(1), eq(effect), any()); - assertTrue(mVibratorProviders.get(1).getAllEffectSegments().isEmpty()); + assertTrue(fakeVibrator.getAllEffectSegments().isEmpty()); } @Test @@ -1421,6 +1456,7 @@ public class VibratorManagerServiceTest { public void vibrate_withIntensitySettings_appliesSettingsToScaleVibrations() throws Exception { int defaultNotificationIntensity = mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION); + // This will scale up notification vibrations. setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH ? defaultNotificationIntensity + 1 @@ -1428,6 +1464,7 @@ public class VibratorManagerServiceTest { int defaultTouchIntensity = mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH); + // This will scale down touch vibrations. setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW ? defaultTouchIntensity - 1 @@ -1477,8 +1514,40 @@ public class VibratorManagerServiceTest { // Alarm vibration will be scaled with SCALE_NONE. assertEquals(1f, ((PrimitiveSegment) fakeVibrator.getAllEffectSegments().get(2)).getScale(), 1e-5); + } + + @Test + public void vibrate_withBypassScaleFlag_ignoresIntensitySettingsAndResolvesAmplitude() + throws Exception { + // Permission needed for bypassing user settings + grantPermission(android.Manifest.permission.MODIFY_PHONE_STATE); - cancelVibrate(service); // Clean up long-ish effect. + int defaultTouchIntensity = + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH); + // This will scale down touch vibrations. + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, + defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW + ? defaultTouchIntensity - 1 + : defaultTouchIntensity); + + int defaultAmplitude = mContextSpy.getResources().getInteger( + com.android.internal.R.integer.config_defaultVibrationAmplitude); + + mockVibrators(1); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + VibratorManagerService service = createSystemReadyService(); + + vibrateAndWaitUntilFinished(service, + VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE), + new VibrationAttributes.Builder() + .setUsage(VibrationAttributes.USAGE_TOUCH) + .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE) + .build()); + + assertEquals(1, fakeVibrator.getAllEffectSegments().size()); + + assertEquals(defaultAmplitude / 255f, fakeVibrator.getAmplitudes().get(0), 1e-5); } @Test @@ -1514,7 +1583,6 @@ public class VibratorManagerServiceTest { // Vibration is not stopped nearly after updating service. assertFalse(waitUntil(s -> !s.isVibrating(1), service, 50)); - cancelVibrate(service); // Clean up long effect. } @Test @@ -1540,8 +1608,6 @@ public class VibratorManagerServiceTest { HAPTIC_FEEDBACK_ATTRS); // Haptic feedback played normally when it's from the default device. assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS)); - - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -1670,13 +1736,14 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class), binderToken); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart( + externalVibration); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); when(mVirtualDeviceManagerInternalMock.isAppRunningOnAnyVirtualDevice(UID)) .thenReturn(true); scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); } @Test @@ -1689,10 +1756,11 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class), binderToken); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart( + externalVibration); mExternalVibratorService.onExternalVibrationStop(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); assertEquals(Arrays.asList(false, true, false), mVibratorProviders.get(1).getExternalControlStates()); @@ -1715,17 +1783,19 @@ public class VibratorManagerServiceTest { ExternalVibration firstVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, firstController, firstToken); - int firstScale = mExternalVibratorService.onExternalVibrationStart(firstVibration); + ExternalVibrationScale firstScale = + mExternalVibratorService.onExternalVibrationStart(firstVibration); AudioAttributes ringtoneAudioAttrs = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) .build(); ExternalVibration secondVibration = new ExternalVibration(UID, PACKAGE_NAME, ringtoneAudioAttrs, secondController, secondToken); - int secondScale = mExternalVibratorService.onExternalVibrationStart(secondVibration); + ExternalVibrationScale secondScale = + mExternalVibratorService.onExternalVibrationStart(secondVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, firstScale); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, secondScale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, firstScale.scaleLevel); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, secondScale.scaleLevel); verify(firstController).mute(); verify(secondController, never()).mute(); // Set external control called only once. @@ -1761,8 +1831,9 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class)); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is cancelled. assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS)); @@ -1787,14 +1858,13 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class)); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); // External vibration is ignored. - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is not cancelled. - assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS)); assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates()); - cancelVibrate(service); // Clean up long effect. } @Test @@ -1814,8 +1884,9 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class)); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is cancelled. assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS)); @@ -1841,14 +1912,13 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_NOTIFICATION_ATTRS, mock(IExternalVibrationController.class)); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); // New vibration is ignored. - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is not cancelled. - assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS)); assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates()); - cancelVibrate(service); // Clean up long effect. } @Test @@ -1863,22 +1933,26 @@ public class VibratorManagerServiceTest { setRingerMode(AudioManager.RINGER_MODE_SILENT); createSystemReadyService(); - int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); setRingerMode(AudioManager.RINGER_MODE_NORMAL); createSystemReadyService(); scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); createSystemReadyService(); scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); } @Test public void onExternalVibration_withBypassMuteAudioFlag_ignoresUserSettings() { + // Permission needed for bypassing user settings + grantPermission(android.Manifest.permission.MODIFY_PHONE_STATE); + mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, @@ -1892,16 +1966,16 @@ public class VibratorManagerServiceTest { .build(); createSystemReadyService(); - int scale = mExternalVibratorService.onExternalVibrationStart( - new ExternalVibration(UID, PACKAGE_NAME, audioAttrs, - mock(IExternalVibrationController.class))); - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibration vib = new ExternalVibration(UID, PACKAGE_NAME, audioAttrs, + mock(IExternalVibrationController.class)); + ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart(vib); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); - createSystemReadyService(); + mExternalVibratorService.onExternalVibrationStop(vib); scale = mExternalVibratorService.onExternalVibrationStart( new ExternalVibration(UID, PACKAGE_NAME, flaggedAudioAttrs, mock(IExternalVibrationController.class))); - assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); } @Test @@ -1912,14 +1986,94 @@ public class VibratorManagerServiceTest { Vibrator.VIBRATION_INTENSITY_OFF); AudioAttributes flaggedAudioAttrs = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_UNKNOWN) - .setFlags(AudioAttributes.FLAG_BYPASS_MUTE) .build(); createSystemReadyService(); - int scale = mExternalVibratorService.onExternalVibrationStart( - new ExternalVibration(/* uid= */ 123, PACKAGE_NAME, flaggedAudioAttrs, - mock(IExternalVibrationController.class))); - assertEquals(IExternalVibratorService.SCALE_MUTE, scale); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart( + new ExternalVibration(/* uid= */ 123, PACKAGE_NAME, flaggedAudioAttrs, + mock(IExternalVibrationController.class))); + assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); + } + + @Test + @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + public void onExternalVibration_withAdaptiveHaptics_returnsCorrectAdaptiveScales() + throws RemoteException { + mockVibrators(1); + mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL, + IVibrator.CAP_AMPLITUDE_CONTROL); + createSystemReadyService(); + + SparseArray<Float> vibrationScales = new SparseArray<>(); + vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f); + vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); + + mVibratorControlService.setVibrationParams( + VibrationParamGenerator.generateVibrationParams(vibrationScales), + mFakeVibratorController); + ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + AUDIO_ALARM_ATTRS, + mock(IExternalVibrationController.class)); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); + mExternalVibratorService.onExternalVibrationStop(externalVibration); + + assertEquals(scale.adaptiveHapticsScale, 0.7f, 0); + + externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + AUDIO_NOTIFICATION_ATTRS, + mock(IExternalVibrationController.class)); + scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + mExternalVibratorService.onExternalVibrationStop(externalVibration); + + assertEquals(scale.adaptiveHapticsScale, 0.4f, 0); + + AudioAttributes ringtoneAudioAttrs = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .build(); + externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + ringtoneAudioAttrs, + mock(IExternalVibrationController.class)); + scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + + assertEquals(scale.adaptiveHapticsScale, 1f, 0); + } + + @Test + @RequiresFlagsDisabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + public void onExternalVibration_withAdaptiveHapticsFlagDisabled_alwaysReturnScaleNone() + throws RemoteException { + mockVibrators(1); + mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL, + IVibrator.CAP_AMPLITUDE_CONTROL); + createSystemReadyService(); + + SparseArray<Float> vibrationScales = new SparseArray<>(); + vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f); + vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f); + + mVibratorControlService.setVibrationParams( + VibrationParamGenerator.generateVibrationParams(vibrationScales), + mFakeVibratorController); + ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + AUDIO_ALARM_ATTRS, + mock(IExternalVibrationController.class)); + ExternalVibrationScale scale = + mExternalVibratorService.onExternalVibrationStart(externalVibration); + mExternalVibratorService.onExternalVibrationStop(externalVibration); + + assertEquals(scale.adaptiveHapticsScale, 1f, 0); + + mVibratorControlService.setVibrationParams( + VibrationParamGenerator.generateVibrationParams(vibrationScales), + mFakeVibratorController); + externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + AUDIO_NOTIFICATION_ATTRS, + mock(IExternalVibrationController.class)); + scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); + + assertEquals(scale.adaptiveHapticsScale, 1f, 0); } @Test @@ -2388,29 +2542,29 @@ public class VibratorManagerServiceTest { private HalVibration vibrateAndWaitUntilFinished(VibratorManagerService service, CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException { - HalVibration vib = - service.vibrateWithPermissionCheck(UID, Context.DEVICE_ID_DEFAULT, PACKAGE_NAME, - effect, attrs, "some reason", service); + HalVibration vib = vibrate(service, effect, attrs); if (vib != null) { vib.waitForEnd(); } - return vib; } - private void vibrate(VibratorManagerService service, VibrationEffect effect, + private HalVibration vibrate(VibratorManagerService service, VibrationEffect effect, VibrationAttributes attrs) { - vibrate(service, CombinedVibration.createParallel(effect), attrs); + return vibrate(service, CombinedVibration.createParallel(effect), attrs); } - private void vibrate(VibratorManagerService service, CombinedVibration effect, + private HalVibration vibrate(VibratorManagerService service, CombinedVibration effect, VibrationAttributes attrs) { - vibrateWithDevice(service, Context.DEVICE_ID_DEFAULT, effect, attrs); + return vibrateWithDevice(service, Context.DEVICE_ID_DEFAULT, effect, attrs); } - private void vibrateWithDevice(VibratorManagerService service, int deviceId, + private HalVibration vibrateWithDevice(VibratorManagerService service, int deviceId, CombinedVibration effect, VibrationAttributes attrs) { - service.vibrate(UID, deviceId, PACKAGE_NAME, effect, attrs, "some reason", service); + HalVibration vib = service.vibrateWithPermissionCheck(UID, deviceId, PACKAGE_NAME, effect, + attrs, "some reason", service); + mPendingVibrations.add(vib); + return vib; } private boolean waitUntil(Predicate<VibratorManagerService> predicate, diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java index 391220669f2f..2a010f0a82a9 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java @@ -18,7 +18,10 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.frameworks.vibrator.IVibratorController; +import android.frameworks.vibrator.VibrationParam; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.VibrationAttributes; @@ -28,17 +31,42 @@ import android.os.VibrationAttributes; */ public final class FakeVibratorController extends IVibratorController.Stub { + private final Handler mHandler; + private VibratorControlService mVibratorControlService; + private VibrationParam[] mRequestResult = new VibrationParam[0]; + public boolean isLinkedToDeath = false; public boolean didRequestVibrationParams = false; public int requestVibrationType = VibrationAttributes.USAGE_UNKNOWN; public long requestTimeoutInMillis = 0; + public FakeVibratorController(Looper looper) { + mHandler = new Handler(looper); + } + + public void setVibratorControlService(VibratorControlService service) { + mVibratorControlService = service; + } + + public void setRequestResult(VibrationParam... params) { + mRequestResult = params; + } + @Override - public void requestVibrationParams(int vibrationType, long timeoutInMillis, IBinder iBinder) + public void requestVibrationParams(int vibrationType, long timeoutInMillis, IBinder token) throws RemoteException { didRequestVibrationParams = true; requestVibrationType = vibrationType; requestTimeoutInMillis = timeoutInMillis; + mHandler.post(() -> { + if (mVibratorControlService != null) { + try { + mVibratorControlService.onRequestVibrationParamsComplete(token, mRequestResult); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + }); } @Override diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java b/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java new file mode 100644 index 000000000000..a606388da190 --- /dev/null +++ b/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.vibrator; + +import android.frameworks.vibrator.ScaleParam; +import android.frameworks.vibrator.VibrationParam; +import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; + +/** + * A helper class that can be used to generate arrays of {@link VibrationParam}. + */ +public final class VibrationParamGenerator { + /** + * Generates an array of {@link VibrationParam}. + */ + public static VibrationParam[] generateVibrationParams(SparseArray<Float> vibrationScales) { + List<VibrationParam> vibrationParamList = new ArrayList<>(); + for (int i = 0; i < vibrationScales.size(); i++) { + int type = vibrationScales.keyAt(i); + float scale = vibrationScales.valueAt(i); + + vibrationParamList.add(generateVibrationParam(type, scale)); + } + + return vibrationParamList.toArray(new VibrationParam[0]); + } + + private static VibrationParam generateVibrationParam(int type, float scale) { + ScaleParam scaleParam = new ScaleParam(); + scaleParam.typesMask = type; + scaleParam.scale = scale; + VibrationParam vibrationParam = new VibrationParam(); + vibrationParam.setScale(scaleParam); + + return vibrationParam; + } +} diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index e83f03d155aa..b2922945aff9 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -22,16 +22,21 @@ filegroup { genrule { name: "wmtests.protologsrc", srcs: [ + ":protolog-impl", ":protolog-groups", ":wmtests-sources", ], tools: ["protologtool"], cmd: "$(location protologtool) transform-protolog-calls " + "--protolog-class com.android.internal.protolog.common.ProtoLog " + - "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " + - "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + "--loggroups-jar $(location :protolog-groups) " + + // Used for the ProtoLogIntegrationTest, where don't test decoding or writing to file + // so the parameters below are irrelevant. + "--viewer-config-file-path /some/unused/file/path.pb " + + "--legacy-viewer-config-file-path /some/unused/file/path.json.gz " + + "--legacy-output-file-path /some/unused/file/path.winscope " + + // END of irrelevant params. "--output-srcjar $(out) " + "$(locations :wmtests-sources)", out: ["wmtests.protolog.srcjar"], @@ -42,7 +47,7 @@ android_test { // We only want this apk build for tests. srcs: [ - ":wmtests.protologsrc", + ":wmtests-sources", "src/**/*.aidl", ], diff --git a/services/tests/wmtests/AndroidTest.xml b/services/tests/wmtests/AndroidTest.xml index 46e87dceb8d4..2512ee592ef3 100644 --- a/services/tests/wmtests/AndroidTest.xml +++ b/services/tests/wmtests/AndroidTest.xml @@ -34,4 +34,11 @@ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> <option name="run-command" value="settings put secure immersive_mode_confirmations confirmed" /> </target_preparer> + + <!-- Collect the dumped files for debugging --> + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="directory-keys" value="/storage/emulated/0/ScreenshotTests" /> + <option name="clean-up" value="true" /> + <option name="collect-on-run-ended-only" value="true" /> + </metrics_collector> </configuration> diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java index dc4e47dfea30..ef36bff91a67 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; -import static android.util.DisplayMetrics.DENSITY_DEFAULT; +import static com.android.server.wm.DesktopModeLaunchParamsModifier.DESKTOP_MODE_INITIAL_BOUNDS_SCALE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE; @@ -30,6 +30,7 @@ import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier. import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -113,9 +114,14 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase { public void testUsesDefaultBounds() { final Task task = new TaskBuilder(mSupervisor).setActivityType( ACTIVITY_TYPE_STANDARD).build(); + final int displayHeight = 1600; + final int displayWidth = 2560; + task.getDisplayArea().setBounds(new Rect(0, 0, displayWidth, displayHeight)); + final int desiredWidth = (int) (displayWidth * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (displayHeight * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate()); - assertEquals(dpiToPx(task, 840), mResult.mBounds.width()); - assertEquals(dpiToPx(task, 630), mResult.mBounds.height()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); } @Test @@ -131,11 +137,6 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase { assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode); } - private int dpiToPx(Task task, int dpi) { - float density = (float) task.getConfiguration().densityDpi / DENSITY_DEFAULT; - return (int) (dpi * density + 0.5f); - } - private class CalculateRequestBuilder { private Task mTask; private int mPhase = PHASE_BOUNDS; diff --git a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java index af0d32c764a4..c5bf78bb60b5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java @@ -27,6 +27,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.common.IProtoLog; +import com.android.internal.protolog.common.LogLevel; import com.android.internal.protolog.common.ProtoLog; import org.junit.After; @@ -47,9 +49,9 @@ public class ProtoLogIntegrationTest { @Ignore("b/163095037") @Test public void testProtoLogToolIntegration() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); runWith(mockedProtoLog, this::testProtoLog); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP), + verify(mockedProtoLog).log(eq(LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP), anyInt(), eq(0b0010010111), eq(com.android.internal.protolog.ProtoLogGroup.TEST_GROUP.isLogToLogcat() ? "Test completed successfully: %b %d %x %f %% %s" @@ -66,18 +68,13 @@ public class ProtoLogIntegrationTest { /** * Starts protolog for the duration of {@code runnable}, with a ProtoLogImpl instance installed. */ - private void runWith(ProtoLogImpl mockInstance, Runnable runnable) { - ProtoLogImpl original = ProtoLogImpl.getSingleInstance(); - original.startProtoLog(null); + private void runWith(IProtoLog mockInstance, Runnable runnable) { + IProtoLog original = ProtoLog.getSingleInstance(); + ProtoLogImpl.setSingleInstance(mockInstance); try { - ProtoLogImpl.setSingleInstance(mockInstance); - try { - runnable.run(); - } finally { - ProtoLogImpl.setSingleInstance(original); - } + runnable.run(); } finally { - original.stopProtoLog(null, false); + ProtoLogImpl.setSingleInstance(original); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 9930c88b1e48..f7c253d9df03 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -46,7 +46,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; @@ -73,6 +72,7 @@ import android.os.SystemClock; import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; +import android.util.IntArray; import android.util.SparseBooleanArray; import android.view.Surface; import android.window.TaskSnapshot; @@ -527,20 +527,20 @@ public class RecentTasksTest extends WindowTestsBase { mTaskPersister.mUserTaskIdsOverride.put(1, true); mTaskPersister.mUserTaskIdsOverride.put(2, true); mTaskPersister.mUserTasksOverride = new ArrayList<>(); - mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask1").build()); - mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask2").build()); + mTaskPersister.mUserTasksOverride.add(mTasks.get(0)); + mTaskPersister.mUserTasksOverride.add(mTasks.get(1)); // Assert no user tasks are initially loaded assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).hasLength(0); // Load user 0 tasks - mRecentTasks.loadUserRecentsLocked(TEST_USER_0_ID); + mRecentTasks.loadRecentTasksIfNeeded(TEST_USER_0_ID); assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID); assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID)); assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID)); // Load user 1 tasks - mRecentTasks.loadUserRecentsLocked(TEST_USER_1_ID); + mRecentTasks.loadRecentTasksIfNeeded(TEST_USER_1_ID); assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID); assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_1_ID); assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID)); @@ -575,15 +575,15 @@ public class RecentTasksTest extends WindowTestsBase { mTaskPersister.mUserTaskIdsOverride.put(2, true); mTaskPersister.mUserTaskIdsOverride.put(3, true); mTaskPersister.mUserTasksOverride = new ArrayList<>(); - mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask1").build()); - mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask2").build()); - mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask3").build()); + mTaskPersister.mUserTasksOverride.add(mTasks.get(0)); + mTaskPersister.mUserTasksOverride.add(mTasks.get(1)); + mTaskPersister.mUserTasksOverride.add(mTasks.get(2)); // Assert no user tasks are initially loaded assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).hasLength(0); // Load tasks - mRecentTasks.loadUserRecentsLocked(TEST_USER_0_ID); + mRecentTasks.loadRecentTasksIfNeeded(TEST_USER_0_ID); assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID); // Sort the time descendingly so the order should be in-sync with task recency (most @@ -1419,8 +1419,6 @@ public class RecentTasksTest extends WindowTestsBase { } private List<RecentTaskInfo> getRecentTasks(int flags) { - doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt()); - doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt()); return mRecentTasks.getRecentTasks(MAX_VALUE, flags, true /* getTasksAllowed */, TEST_USER_0_ID, 0 /* callingUid */).getList(); } @@ -1590,19 +1588,20 @@ public class RecentTasksTest extends WindowTestsBase { } @Override - SparseBooleanArray loadPersistedTaskIdsForUser(int userId) { + SparseBooleanArray readPersistedTaskIdsFromFileForUser(int userId) { if (mUserTaskIdsOverride != null) { return mUserTaskIdsOverride; } - return super.loadPersistedTaskIdsForUser(userId); + return super.readPersistedTaskIdsFromFileForUser(userId); } @Override - List<Task> restoreTasksForUserLocked(int userId, SparseBooleanArray preaddedTasks) { + ArrayList<Task> restoreTasksForUserLocked(int userId, RecentTaskFiles recentTaskFiles, + IntArray existedTaskIds) { if (mUserTasksOverride != null) { return mUserTasksOverride; } - return super.restoreTasksForUserLocked(userId, preaddedTasks); + return super.restoreTasksForUserLocked(userId, recentTaskFiles, existedTaskIds); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java index 0fcae92fdbfc..280fe4c30739 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java @@ -16,12 +16,14 @@ package com.android.server.wm; +import static android.server.wm.CtsWindowInfoUtils.waitForStableWindowGeometry; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.statusBars; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -43,6 +45,7 @@ import android.os.Handler; import android.os.Looper; import android.os.ServiceManager; import android.platform.test.annotations.Presubmit; +import android.server.wm.BuildUtils; import android.view.IWindowManager; import android.view.PointerIcon; import android.view.SurfaceControl; @@ -50,7 +53,6 @@ import android.view.cts.surfacevalidator.BitmapPixelChecker; import android.view.cts.surfacevalidator.SaveBitmapHelper; import android.window.ScreenCapture; import android.window.ScreenCapture.ScreenshotHardwareBuffer; -import android.window.ScreenCapture.SynchronousScreenCaptureListener; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; @@ -74,6 +76,7 @@ import java.util.concurrent.TimeUnit; @SmallTest @Presubmit public class ScreenshotTests { + private static final long WAIT_TIME_S = 5L * BuildUtils.HW_TIMEOUT_MULTIPLIER; private static final int BUFFER_WIDTH = 100; private static final int BUFFER_HEIGHT = 100; @@ -119,32 +122,61 @@ public class ScreenshotTests { canvas.drawColor(Color.RED); buffer.unlockCanvasAndPost(canvas); + CountDownLatch countDownLatch = new CountDownLatch(1); t.show(secureSC) .setBuffer(secureSC, HardwareBuffer.createFromGraphicBuffer(buffer)) .setDataSpace(secureSC, DataSpace.DATASPACE_SRGB) - .apply(true); + .addTransactionCommittedListener(Runnable::run, countDownLatch::countDown) + .apply(); + assertTrue("Failed to wait for transaction to get committed", + countDownLatch.await(WAIT_TIME_S, TimeUnit.SECONDS)); + assertTrue("Failed to wait for stable geometry", + waitForStableWindowGeometry(WAIT_TIME_S, TimeUnit.SECONDS)); ScreenCapture.LayerCaptureArgs args = new ScreenCapture.LayerCaptureArgs.Builder(secureSC) .setCaptureSecureLayers(true) .setChildrenOnly(false) .build(); - ScreenCapture.ScreenshotHardwareBuffer hardwareBuffer = ScreenCapture.captureLayers(args); - assertNotNull(hardwareBuffer); - Bitmap screenshot = hardwareBuffer.asBitmap(); - assertNotNull(screenshot); - - Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false); - screenshot.recycle(); - - BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(Color.RED); - Rect bounds = new Rect(0, 0, swBitmap.getWidth(), swBitmap.getHeight()); - int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds); - int sizeOfBitmap = bounds.width() * bounds.height(); - boolean success = numMatchingPixels == sizeOfBitmap; - swBitmap.recycle(); - - assertTrue(success); + ScreenshotHardwareBuffer[] screenCapture = new ScreenshotHardwareBuffer[1]; + Bitmap screenshot = null; + Bitmap swBitmap = null; + try { + CountDownLatch screenshotComplete = new CountDownLatch(1); + ScreenCapture.captureLayers(args, new ScreenCapture.ScreenCaptureListener( + (screenshotHardwareBuffer, result) -> { + if (result == 0) { + screenCapture[0] = screenshotHardwareBuffer; + } + screenshotComplete.countDown(); + })); + assertTrue("Failed to wait for screen capture", + screenshotComplete.await(WAIT_TIME_S, TimeUnit.SECONDS)); + assertNotNull("Screen capture buffer is null", screenCapture[0]); + + screenshot = screenCapture[0].asBitmap(); + assertNotNull("Screenshot from bitmap is null", screenshot); + + swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false); + + BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(Color.RED); + Rect bounds = new Rect(0, 0, swBitmap.getWidth(), swBitmap.getHeight()); + int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds); + int sizeOfBitmap = bounds.width() * bounds.height(); + + assertEquals("numMatchingPixels=" + numMatchingPixels + " sizeOfBitmap=" + sizeOfBitmap, + sizeOfBitmap, numMatchingPixels); + } finally { + if (screenshot != null) { + screenshot.recycle(); + } + if (swBitmap != null) { + swBitmap.recycle(); + } + if (screenCapture[0].getHardwareBuffer() != null) { + screenCapture[0].getHardwareBuffer().close(); + } + } } @Test @@ -169,36 +201,65 @@ public class ScreenshotTests { buffer.unlockCanvasAndPost(canvas); Point point = mActivity.getPositionBelowStatusBar(); + CountDownLatch countDownLatch = new CountDownLatch(1); t.show(sc) .setBuffer(sc, HardwareBuffer.createFromGraphicBuffer(buffer)) .setDataSpace(sc, DataSpace.DATASPACE_SRGB) .setPosition(sc, point.x, point.y) - .apply(true); - - SynchronousScreenCaptureListener syncScreenCapture = - ScreenCapture.createSyncCaptureListener(); - windowManager.captureDisplay(DEFAULT_DISPLAY, null, syncScreenCapture); - ScreenshotHardwareBuffer hardwareBuffer = syncScreenCapture.getBuffer(); - assertNotNull(hardwareBuffer); - - Bitmap screenshot = hardwareBuffer.asBitmap(); - assertNotNull(screenshot); - - Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false); - screenshot.recycle(); - - BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(Color.RED); - Rect bounds = new Rect(point.x, point.y, BUFFER_WIDTH + point.x, BUFFER_HEIGHT + point.y); - int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds); - int pixelMatchSize = bounds.width() * bounds.height(); - boolean success = numMatchingPixels == pixelMatchSize; - - if (!success) { - SaveBitmapHelper.saveBitmap(swBitmap, getClass(), mTestName, "failedImage"); + .addTransactionCommittedListener(Runnable::run, countDownLatch::countDown) + .apply(); + + assertTrue("Failed to wait for transaction to get committed", + countDownLatch.await(WAIT_TIME_S, TimeUnit.SECONDS)); + assertTrue("Failed to wait for stable geometry", + waitForStableWindowGeometry(WAIT_TIME_S, TimeUnit.SECONDS)); + + ScreenshotHardwareBuffer[] screenCapture = new ScreenshotHardwareBuffer[1]; + Bitmap screenshot = null; + Bitmap swBitmap = null; + try { + CountDownLatch screenshotComplete = new CountDownLatch(1); + windowManager.captureDisplay(DEFAULT_DISPLAY, null, + new ScreenCapture.ScreenCaptureListener( + (screenshotHardwareBuffer, result) -> { + if (result == 0) { + screenCapture[0] = screenshotHardwareBuffer; + } + screenshotComplete.countDown(); + })); + assertTrue("Failed to wait for screen capture", + screenshotComplete.await(WAIT_TIME_S, TimeUnit.SECONDS)); + assertNotNull("Screen capture buffer is null", screenCapture[0]); + + screenshot = screenCapture[0].asBitmap(); + assertNotNull("Screenshot from bitmap is null", screenshot); + + swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false); + + BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(Color.RED); + Rect bounds = new Rect(point.x, point.y, BUFFER_WIDTH + point.x, + BUFFER_HEIGHT + point.y); + int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds); + int pixelMatchSize = bounds.width() * bounds.height(); + boolean success = numMatchingPixels == pixelMatchSize; + + if (!success) { + SaveBitmapHelper.saveBitmap(swBitmap, getClass(), mTestName, "failedImage"); + } + assertTrue( + "numMatchingPixels=" + numMatchingPixels + " pixelMatchSize=" + pixelMatchSize, + success); + } finally { + if (screenshot != null) { + screenshot.recycle(); + } + if (swBitmap != null) { + swBitmap.recycle(); + } + if (screenCapture[0].getHardwareBuffer() != null) { + screenCapture[0].getHardwareBuffer().close(); + } } - swBitmap.recycle(); - assertTrue("numMatchingPixels=" + numMatchingPixels + " pixelMatchSize=" + pixelMatchSize, - success); } public static class ScreenshotActivity extends Activity { diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java index d84620b4444a..ead36f1d353f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.platform.test.annotations.Presubmit; +import android.server.wm.BuildUtils; import android.view.SurfaceControl; import android.window.SurfaceSyncGroup; @@ -370,6 +371,7 @@ public class SurfaceSyncGroupTest { assertEquals(0, finishedLatch.getCount()); } + @Test public void testSurfaceSyncGroupTimeout() throws InterruptedException { final CountDownLatch finishedLatch = new CountDownLatch(1); SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG); @@ -386,7 +388,7 @@ public class SurfaceSyncGroupTest { // Never finish syncTarget2 so it forces the timeout. Timeout is 1 second so wait a little // over 1 second to make sure it completes. - finishedLatch.await(1100, TimeUnit.MILLISECONDS); + finishedLatch.await(1100L * BuildUtils.HW_TIMEOUT_MULTIPLIER, TimeUnit.MILLISECONDS); assertEquals(0, finishedLatch.getCount()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java index 12ed3c28161f..319be89b2901 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java @@ -29,8 +29,6 @@ import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.util.SparseBooleanArray; -import androidx.test.filters.FlakyTest; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -81,7 +79,7 @@ public class TaskPersisterTest { } mTaskPersister.writePersistedTaskIdsForUser(taskIdsOnFile, mTestUserId); SparseBooleanArray newTaskIdsOnFile = mTaskPersister - .loadPersistedTaskIdsForUser(mTestUserId); + .readPersistedTaskIdsFromFileForUser(mTestUserId); assertEquals("TaskIds written differ from TaskIds read back from file", taskIdsOnFile, newTaskIdsOnFile); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java index a0e64bf94393..12f46df451fe 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -82,7 +82,10 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.ArraySet; import android.util.MergedConfiguration; import android.view.ContentRecordingSession; @@ -109,6 +112,7 @@ import com.android.internal.os.IResultReceiver; import com.android.server.LocalServices; import com.android.server.wm.SensitiveContentPackages.PackageInfo; import com.android.server.wm.WindowManagerService.WindowContainerInfo; +import com.android.window.flags.Flags; import com.google.common.truth.Expect; @@ -140,6 +144,9 @@ public class WindowManagerServiceTests extends WindowTestsBase { @Rule public Expect mExpect = Expect.create(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @After public void tearDown() { mWm.mSensitiveContentPackages.clearBlockedApps(); @@ -1106,6 +1113,7 @@ public class WindowManagerServiceTests extends WindowTestsBase { argThat(h -> (h.inputConfig & InputConfig.SPY) == InputConfig.SPY)); } + @RequiresFlagsDisabled(Flags.FLAG_MAGNIFICATION_ALWAYS_DRAW_FULLSCREEN_BORDER) @Test public void testDrawMagnifiedViewport() { final int displayId = mDisplayContent.mDisplayId; diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java index 0a1f3c78e0e6..ad7b9e69282e 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java @@ -411,7 +411,8 @@ abstract class DetectorSession { audioFormat, options, callback, - /* shouldCloseAudioStreamWithDelayOnDetect= */ true); + /* shouldCloseAudioStreamWithDelayOnDetect= */ true, + /* shouldCheckPermissionsAndAppOpsOnDetected= */ true); } void startListeningFromWearableLocked( @@ -481,12 +482,29 @@ abstract class DetectorSession { return null; } }; + /* + * By setting shouldCheckPermissionsAndAppOpsOnDetected to false, when the audio + * stream is sent from the sandboxed HotwordDetectionService to the non-sandboxed + * VoiceInteractionService as a result of second-stage hotword detection, audio-related + * permissions will not be checked against the VoiceInteractionService and the AppOpsManager + * will not be notified of the data flow to the VoiceInteractionService. These checks are + * not performed because the audio stream here originates from a remotely connected wearable + * device. It does not originate from the microphone of the device where this code runs on, + * or a microphone directly controlled by this system. Permission checks are expected to + * happen on the remote wearable device. From the perspective of this system, the audio + * stream is data received from an external source. + * + * Not notifying AppOpsManager allows this device's microphone indicator to remain off when + * this data flow happens. It avoids confusion since the audio does not originate from + * this device. The wearable is expected to turn on its own microphone indicator. + */ handleExternalSourceHotwordDetectionLocked( audioStream, audioFormat, options, voiceInteractionCallback, - /* shouldCloseAudioStreamWithDelayOnDetect= */ false); + /* shouldCloseAudioStreamWithDelayOnDetect= */ false, + /* shouldCheckPermissionsAndAppOpsOnDetected= */ false); } @SuppressWarnings("GuardedBy") @@ -495,7 +513,8 @@ abstract class DetectorSession { AudioFormat audioFormat, @Nullable PersistableBundle options, IMicrophoneHotwordDetectionVoiceInteractionCallback callback, - boolean shouldCloseAudioStreamWithDelayOnDetect) { + boolean shouldCloseAudioStreamWithDelayOnDetect, + boolean shouldCheckPermissionsAndAppOpsOnDetected) { if (DEBUG) { Slog.d(TAG, "#handleExternalSourceHotwordDetectionLocked"); } @@ -631,36 +650,39 @@ abstract class DetectorSession { EXTERNAL_HOTWORD_CLEANUP_MILLIS, TimeUnit.MILLISECONDS); } - try { - enforcePermissionsForDataDelivery(); - } catch (SecurityException e) { - Slog.w( - TAG, - "Ignoring #onDetected due to a " - + "SecurityException", - e); - HotwordMetricsLogger.writeDetectorEvent( - getDetectorType(), - EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION, - mVoiceInteractionServiceUid); + if (shouldCheckPermissionsAndAppOpsOnDetected) { try { - callback.onHotwordDetectionServiceFailure( + enforcePermissionsForDataDelivery(); + } catch (SecurityException e) { + Slog.w( + TAG, + "Ignoring #onDetected due to a " + + "SecurityException", + e); + HotwordMetricsLogger.writeDetectorEvent( + getDetectorType(), + EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION, + mVoiceInteractionServiceUid); + try { + callback.onHotwordDetectionServiceFailure( new HotwordDetectionServiceFailure( ONDETECTED_GOT_SECURITY_EXCEPTION, "Security exception occurs in " + "#onDetected method")); - } catch (RemoteException e1) { - notifyOnDetectorRemoteException(); - throw e1; + } catch (RemoteException e1) { + notifyOnDetectorRemoteException(); + throw e1; + } + return; } - return; } HotwordDetectedResult newResult; try { newResult = - mHotwordAudioStreamCopier - .startCopyingAudioStreams( - triggerResult); + mHotwordAudioStreamCopier + .startCopyingAudioStreams( + triggerResult, + shouldCheckPermissionsAndAppOpsOnDetected); } catch (IOException e) { Slog.w( TAG, diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java index 65c95d1261f3..6f00dc82f42b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java @@ -87,18 +87,31 @@ final class HotwordAudioStreamCopier { } /** + * Calls {@link #startCopyingAudioStreams(HotwordDetectedResult, boolean)} and notifies + * AppOpsManager of the {@link AppOpsManager#OPSTR_RECORD_AUDIO_HOTWORD} operation. + */ + @NonNull + public HotwordDetectedResult startCopyingAudioStreams(@NonNull HotwordDetectedResult result) + throws IOException { + return startCopyingAudioStreams(result, /* shouldNotifyAppOpsManager= */ true); + } + + /** * Starts copying the audio streams in the given {@link HotwordDetectedResult}. - * <p> - * The returned {@link HotwordDetectedResult} is identical the one that was passed in, except + * + * <p>The returned {@link HotwordDetectedResult} is identical the one that was passed in, except * that the {@link ParcelFileDescriptor}s within {@link HotwordDetectedResult#getAudioStreams()} * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamCopier}. The * returned value should be passed on to the client (i.e., the voice interactor). - * </p> * + * @param result The {@link HotwordDetectedResult} to copy from. + * @param shouldNotifyAppOpsManager Whether the {@link AppOpsManager} should be notified of the + * {@link AppOpsManager#OPSTR_RECORD_AUDIO_HOTWORD} operation during the copy. * @throws IOException If there was an error creating the managed pipe. */ @NonNull - public HotwordDetectedResult startCopyingAudioStreams(@NonNull HotwordDetectedResult result) + public HotwordDetectedResult startCopyingAudioStreams( + @NonNull HotwordDetectedResult result, boolean shouldNotifyAppOpsManager) throws IOException { List<HotwordAudioStream> audioStreams = result.getAudioStreams(); if (audioStreams.isEmpty()) { @@ -154,8 +167,12 @@ final class HotwordAudioStreamCopier { String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); mExecutorService.execute( - new HotwordDetectedResultCopyTask(resultTaskId, copyTaskInfos, - totalMetadataBundleSizeBytes, totalInitialAudioSizeBytes)); + new HotwordDetectedResultCopyTask( + resultTaskId, + copyTaskInfos, + totalMetadataBundleSizeBytes, + totalInitialAudioSizeBytes, + shouldNotifyAppOpsManager)); return result.buildUpon().setAudioStreams(newAudioStreams).build(); } @@ -178,13 +195,19 @@ final class HotwordAudioStreamCopier { private final int mTotalMetadataSizeBytes; private final int mTotalInitialAudioSizeBytes; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - - HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos, - int totalMetadataSizeBytes, int totalInitialAudioSizeBytes) { + private final boolean mShouldNotifyAppOpsManager; + + HotwordDetectedResultCopyTask( + String resultTaskId, + List<CopyTaskInfo> copyTaskInfos, + int totalMetadataSizeBytes, + int totalInitialAudioSizeBytes, + boolean shouldNotifyAppOpsManager) { mResultTaskId = resultTaskId; mCopyTaskInfos = copyTaskInfos; mTotalMetadataSizeBytes = totalMetadataSizeBytes; mTotalInitialAudioSizeBytes = totalInitialAudioSizeBytes; + mShouldNotifyAppOpsManager = shouldNotifyAppOpsManager; } @Override @@ -200,55 +223,14 @@ final class HotwordAudioStreamCopier { mVoiceInteractorUid)); } - if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorUid, mVoiceInteractorPackageName, - mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { - try { - HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, - HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED, - mVoiceInteractorUid, mTotalInitialAudioSizeBytes, - mTotalMetadataSizeBytes, size); - // TODO(b/244599891): Set timeout, close after inactivity - mExecutorService.invokeAll(tasks); - - // We are including the non-streamed initial audio - // (HotwordAudioStream.getInitialAudio()) bytes in the "stream" size metrics. - int totalStreamSizeBytes = mTotalInitialAudioSizeBytes; - for (SingleAudioStreamCopyTask task : tasks) { - totalStreamSizeBytes += task.mTotalCopiedBytes; - } - - Slog.i(TAG, mResultTaskId + ": Task was completed. Total bytes egressed: " - + totalStreamSizeBytes + " (including " + mTotalInitialAudioSizeBytes - + " bytes NOT streamed), total metadata bundle size bytes: " - + mTotalMetadataSizeBytes); - HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, - HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ENDED, - mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes, - size); - } catch (InterruptedException e) { - // We are including the non-streamed initial audio - // (HotwordAudioStream.getInitialAudio()) bytes in the "stream" size metrics. - int totalStreamSizeBytes = mTotalInitialAudioSizeBytes; - for (SingleAudioStreamCopyTask task : tasks) { - totalStreamSizeBytes += task.mTotalCopiedBytes; - } - - HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, - HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__INTERRUPTED_EXCEPTION, - mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes, - size); - Slog.i(TAG, mResultTaskId + ": Task was interrupted. Total bytes egressed: " - + totalStreamSizeBytes + " (including " + mTotalInitialAudioSizeBytes - + " bytes NOT streamed), total metadata bundle size bytes: " - + mTotalMetadataSizeBytes); - bestEffortPropagateError(e.getMessage()); - } finally { - mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorUid, mVoiceInteractorPackageName, - mVoiceInteractorAttributionTag); - } - } else { + if (mShouldNotifyAppOpsManager + && mAppOpsManager.startOpNoThrow( + AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, + mVoiceInteractorUid, + mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag, + OP_MESSAGE) + != MODE_ALLOWED) { HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__NO_PERMISSION, mVoiceInteractorUid, /* streamSizeBytes= */ 0, /* bundleSizeBytes= */ 0, @@ -258,6 +240,56 @@ final class HotwordAudioStreamCopier { + " uid=" + mVoiceInteractorUid + " packageName=" + mVoiceInteractorPackageName + " attributionTag=" + mVoiceInteractorAttributionTag); + return; + } + try { + HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, + HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__STARTED, + mVoiceInteractorUid, mTotalInitialAudioSizeBytes, + mTotalMetadataSizeBytes, size); + // TODO(b/244599891): Set timeout, close after inactivity + mExecutorService.invokeAll(tasks); + + // We are including the non-streamed initial audio + // (HotwordAudioStream.getInitialAudio()) bytes in the "stream" size metrics. + int totalStreamSizeBytes = mTotalInitialAudioSizeBytes; + for (SingleAudioStreamCopyTask task : tasks) { + totalStreamSizeBytes += task.mTotalCopiedBytes; + } + + Slog.i(TAG, mResultTaskId + ": Task was completed. Total bytes egressed: " + + totalStreamSizeBytes + " (including " + mTotalInitialAudioSizeBytes + + " bytes NOT streamed), total metadata bundle size bytes: " + + mTotalMetadataSizeBytes); + HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, + HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__ENDED, + mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes, + size); + } catch (InterruptedException e) { + // We are including the non-streamed initial audio + // (HotwordAudioStream.getInitialAudio()) bytes in the "stream" size metrics. + int totalStreamSizeBytes = mTotalInitialAudioSizeBytes; + for (SingleAudioStreamCopyTask task : tasks) { + totalStreamSizeBytes += task.mTotalCopiedBytes; + } + + HotwordMetricsLogger.writeAudioEgressEvent(mDetectorType, + HOTWORD_AUDIO_EGRESS_EVENT_REPORTED__EVENT__INTERRUPTED_EXCEPTION, + mVoiceInteractorUid, totalStreamSizeBytes, mTotalMetadataSizeBytes, + size); + Slog.i(TAG, mResultTaskId + ": Task was interrupted. Total bytes egressed: " + + totalStreamSizeBytes + " (including " + mTotalInitialAudioSizeBytes + + " bytes NOT streamed), total metadata bundle size bytes: " + + mTotalMetadataSizeBytes); + bestEffortPropagateError(e.getMessage()); + } finally { + if (mShouldNotifyAppOpsManager) { + mAppOpsManager.finishOp( + AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, + mVoiceInteractorUid, + mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag); + } } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 889f8429077c..c217780d90d6 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -2582,7 +2582,6 @@ public class VoiceInteractionManagerService extends SystemService { if (anyPackagesAppearing()) { initRecognizer(userHandle); } - return; } if (curInteractor != null) { @@ -2631,15 +2630,16 @@ public class VoiceInteractionManagerService extends SystemService { } } - // There is no interactor, so just deal with a simple recognizer. - int change = isPackageDisappearing(curRecognizer.getPackageName()); - if (change == PACKAGE_PERMANENT_CHANGE - || change == PACKAGE_TEMPORARY_CHANGE) { - setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); + if (curRecognizer != null) { + int change = isPackageDisappearing(curRecognizer.getPackageName()); + if (change == PACKAGE_PERMANENT_CHANGE + || change == PACKAGE_TEMPORARY_CHANGE) { + setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); - } else if (isPackageModified(curRecognizer.getPackageName())) { - setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(), - userHandle), userHandle); + } else if (isPackageModified(curRecognizer.getPackageName())) { + setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(), + userHandle), userHandle); + } } } } diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index 7ad26c901188..5ba5ee8836e1 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -169,8 +169,7 @@ public final class DisconnectCause implements Parcelable { int toneToPlay) { this(code, label, description, reason, toneToPlay, android.telephony.DisconnectCause.ERROR_UNSPECIFIED, - PreciseDisconnectCause.ERROR_UNSPECIFIED, - null /* imsReasonInfo */); + PreciseDisconnectCause.ERROR_UNSPECIFIED, null /* imsReasonInfo */); } /** @@ -187,8 +186,6 @@ public final class DisconnectCause implements Parcelable { * @param imsReasonInfo The relevant {@link ImsReasonInfo}, or {@code null} if not available. * @hide */ - @SystemApi - @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) public DisconnectCause(int code, @NonNull CharSequence label, @NonNull CharSequence description, @NonNull String reason, int toneToPlay, @Annotation.DisconnectCauses int telephonyDisconnectCause, @@ -298,6 +295,117 @@ public final class DisconnectCause implements Parcelable { return mToneToPlay; } + /** + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) + public static final class Builder { + private int mDisconnectCode; + private CharSequence mDisconnectLabel; + private CharSequence mDisconnectDescription; + private String mDisconnectReason; + private int mToneToPlay; + private int mTelephonyDisconnectCause; + private int mTelephonyPreciseDisconnectCause; + private ImsReasonInfo mImsReasonInfo; + + /** + * Sets the code for the reason for this disconnect. + * @param code The code denoting the type of disconnect. + */ + public @NonNull DisconnectCause.Builder setCode(int code) { + mDisconnectCode = code; + return this; + } + + /** + * Sets a label which explains the reason for the disconnect cause, used for display in the + * user interface. + * @param label The label to associate with the disconnect cause. + */ + public @NonNull DisconnectCause.Builder setLabel(@Nullable CharSequence label) { + mDisconnectLabel = label; + return this; + } + + /** + * Sets a description which provides the reason for the disconnect cause, used for display + * in the user interface. + * @param description The description to associate with the disconnect cause. + */ + public @NonNull DisconnectCause.Builder setDescription( + @Nullable CharSequence description) { + mDisconnectDescription = description; + return this; + } + + /** + * Sets a reason providing explanation for the disconnect (intended for logging and not for + * displaying in the user interface). + * @param reason The reason for the disconnect. + */ + public @NonNull DisconnectCause.Builder setReason(@NonNull String reason) { + mDisconnectReason = reason; + return this; + } + + /** + * Sets the tone to play when disconnected. + * @param toneToPlay The tone as defined in {@link ToneGenerator} to play when disconnected. + */ + public @NonNull DisconnectCause.Builder setTone(int toneToPlay) { + mToneToPlay = toneToPlay; + return this; + } + + /** + * Sets the telephony {@link android.telephony.DisconnectCause} for the call (used + * internally by Telecom for providing extra debug information from Telephony). + * @param telephonyDisconnectCause The disconnect cause as provided by Telephony. + */ + public @NonNull DisconnectCause.Builder setTelephonyDisconnectCause( + @Annotation.DisconnectCauses int telephonyDisconnectCause) { + mTelephonyDisconnectCause = telephonyDisconnectCause; + return this; + } + + /** + * Sets the telephony {@link android.telephony.PreciseDisconnectCause} for the call (used + * internally by Telecom for providing extra debug information from Telephony). + * @param telephonyPreciseDisconnectCause The precise disconnect cause as provided by + * Telephony. + */ + + public @NonNull DisconnectCause.Builder setTelephonyPreciseDisconnectCause( + @Annotation.PreciseDisconnectCauses int telephonyPreciseDisconnectCause) { + mTelephonyPreciseDisconnectCause = telephonyPreciseDisconnectCause; + return this; + } + + /** + * Returns the telephony {@link ImsReasonInfo} associated with the call disconnection. This + * is only used internally by Telecom for providing extra debug information from Telephony. + * + * @param imsReasonInfo The {@link ImsReasonInfo} or {@code null} if not known. + */ + public @NonNull DisconnectCause.Builder setImsReasonInfo( + @Nullable ImsReasonInfo imsReasonInfo) { + mImsReasonInfo = imsReasonInfo; + return this; + } + + /** + * Build the {@link DisconnectCause} from the provided Builder config. + * @return The {@link DisconnectCause} instance from provided builder. + */ + public @NonNull DisconnectCause build() { + return new DisconnectCause(mDisconnectCode, mDisconnectLabel, mDisconnectDescription, + mDisconnectReason, mToneToPlay, mTelephonyDisconnectCause, + mTelephonyPreciseDisconnectCause, mImsReasonInfo); + } + } + public static final @android.annotation.NonNull Creator<DisconnectCause> CREATOR = new Creator<DisconnectCause>() { @Override diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 08c76af70511..9792cdd80a00 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -2797,13 +2797,10 @@ public class TelecomManager { * calls for a given {@code packageName} and {@code userHandle}. * * @param packageName the package name of the app to check calls for. - * @param userHandle the user handle on which to check for calls. - * @param detectForAllUsers indicates if calls should be detected across all users. If it is - * set to {@code true}, and the caller has the ability to interact - * across users, the userHandle parameter is disregarded. + * @param userHandle the user handle to check calls for. * @return {@code true} if there are ongoing calls, {@code false} otherwise. - * @throws SecurityException if detectForAllUsers is true or userHandle is not the calling user - * and the caller does not grant the ability to interact across users. + * @throws SecurityException if the userHandle is not the calling user and the caller does not + * grant the ability to interact across users. * @hide */ @SystemApi @@ -2811,11 +2808,45 @@ public class TelecomManager { @RequiresPermission(allOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) public boolean isInSelfManagedCall(@NonNull String packageName, - @NonNull UserHandle userHandle, boolean detectForAllUsers) { + @NonNull UserHandle userHandle) { ITelecomService service = getTelecomService(); if (service != null) { try { return service.isInSelfManagedCall(packageName, userHandle, + mContext.getOpPackageName(), false); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException isInSelfManagedCall: " + e); + e.rethrowFromSystemServer(); + return false; + } + } else { + throw new IllegalStateException("Telecom service is not present"); + } + } + + /** + * Determines whether there are any ongoing {@link PhoneAccount#CAPABILITY_SELF_MANAGED} + * calls for a given {@code packageName} amongst all users, given that detectForAllUsers is true + * and the caller has the ability to interact across users. If detectForAllUsers isn't enabled, + * the calls will be checked against the caller. + * + * @param packageName the package name of the app to check calls for. + * @param detectForAllUsers indicates if calls should be detected across all users. + * @return {@code true} if there are ongoing calls, {@code false} otherwise. + * @throws SecurityException if detectForAllUsers is true and the caller does not grant the + * ability to interact across users. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) + @RequiresPermission(allOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) + public boolean isInSelfManagedCall(@NonNull String packageName, + boolean detectForAllUsers) { + ITelecomService service = getTelecomService(); + if (service != null) { + try { + return service.isInSelfManagedCall(packageName, null, mContext.getOpPackageName(), detectForAllUsers); } catch (RemoteException e) { Log.e(TAG, "RemoteException isInSelfManagedCall: " + e); diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java index 5af2c3458368..55245419c570 100644 --- a/telephony/java/android/service/euicc/EuiccService.java +++ b/telephony/java/android/service/euicc/EuiccService.java @@ -856,10 +856,22 @@ public abstract class EuiccService extends Service { int slotId, IGetAvailableMemoryInBytesCallback callback) { mExecutor.execute( () -> { - long availableMemoryInBytes = - EuiccService.this.onGetAvailableMemoryInBytes(slotId); + long availableMemoryInBytes = EuiccManager.EUICC_MEMORY_FIELD_UNAVAILABLE; + String unsupportedOperationMessage = ""; try { - callback.onSuccess(availableMemoryInBytes); + availableMemoryInBytes = + EuiccService.this.onGetAvailableMemoryInBytes(slotId); + } catch (UnsupportedOperationException e) { + unsupportedOperationMessage = e.getMessage(); + } + + try { + if (!unsupportedOperationMessage.isEmpty()) { + callback.onUnsupportedOperationException( + unsupportedOperationMessage); + } else { + callback.onSuccess(availableMemoryInBytes); + } } catch (RemoteException e) { // Can't communicate with the phone process; ignore. } diff --git a/telephony/java/android/service/euicc/IGetAvailableMemoryInBytesCallback.aidl b/telephony/java/android/service/euicc/IGetAvailableMemoryInBytesCallback.aidl index bd6d19b81d47..e550e77a3605 100644 --- a/telephony/java/android/service/euicc/IGetAvailableMemoryInBytesCallback.aidl +++ b/telephony/java/android/service/euicc/IGetAvailableMemoryInBytesCallback.aidl @@ -19,4 +19,5 @@ package android.service.euicc; /** @hide */ oneway interface IGetAvailableMemoryInBytesCallback { void onSuccess(long availableMemoryInBytes); + void onUnsupportedOperationException(String message); } diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl index bdd212afd4b0..e69b60b3a37c 100644 --- a/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl +++ b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl @@ -26,4 +26,5 @@ oneway interface IQualifiedNetworksServiceCallback { void onQualifiedNetworkTypesChanged(int apnTypes, in int[] qualifiedNetworkTypes); void onNetworkValidationRequested(int networkCapability, IIntegerConsumer callback); + void onReconnectQualifedNetworkType(int apnTypes, int qualifiedNetworkType); } diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java index c3ba09248298..7bfe04d025c8 100644 --- a/telephony/java/android/telephony/data/QualifiedNetworksService.java +++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java @@ -33,6 +33,7 @@ import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.NetCapability; import android.telephony.PreciseDataConnectionState; +import android.telephony.TelephonyManager; import android.util.Log; import android.util.SparseArray; @@ -82,6 +83,7 @@ public abstract class QualifiedNetworksService extends Service { private static final int QNS_APN_THROTTLE_STATUS_CHANGED = 5; private static final int QNS_EMERGENCY_DATA_NETWORK_PREFERRED_TRANSPORT_CHANGED = 6; private static final int QNS_REQUEST_NETWORK_VALIDATION = 7; + private static final int QNS_RECONNECT_QUALIFIED_NETWORK = 8; /** Feature flags */ private static final FeatureFlags sFeatureFlag = new FeatureFlagsImpl(); @@ -186,8 +188,42 @@ public abstract class QualifiedNetworksService extends Service { qualifiedNetworkTypesArray).sendToTarget(); } - private void onUpdateQualifiedNetworkTypes(@ApnType int apnTypes, - int[] qualifiedNetworkTypes) { + /** + * Request to make a clean initial connection instead of handover to a transport type mapped + * to the {@code qualifiedNetworkType} for the {@code apnTypes}. This will update the + * preferred network type like {@link #updateQualifiedNetworkTypes(int, List)}, however if + * the data network for the {@code apnTypes} is not in the state {@link TelephonyManager + * #DATA_CONNECTED} or it's already connected on the transport type mapped to the + * qualified network type, forced reconnection will be ignored. + * + * <p>This will tear down current data network even though target transport type mapped to + * the {@code qualifiedNetworkType} is not available, and the data network will be connected + * to the transport type when it becomes available. + * + * <p>This is one shot request and does not mean further handover is not allowed to the + * qualified network type for this APN type. + * + * @param apnTypes APN type(s) of the qualified networks. This must be a bitmask combination + * of {@link ApnType}. The same qualified networks will be applicable to all APN types + * specified here. + * @param qualifiedNetworkType Access network types which are qualified for data connection + * setup for {@link ApnType}. Empty list means QNS has no suggestion to the frameworks, and + * for that APN type frameworks will route the corresponding network requests to + * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}. + * + * <p> If one of the element is invalid, for example, {@link AccessNetworkType#UNKNOWN}, + * then this operation becomes a no-op. + * + * @hide + */ + public final void reconnectQualifiedNetworkType(@ApnType int apnTypes, + @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType) { + mHandler.obtainMessage(QNS_RECONNECT_QUALIFIED_NETWORK, mSlotIndex, apnTypes, + new Integer(qualifiedNetworkType)).sendToTarget(); + } + + private void onUpdateQualifiedNetworkTypes( + @ApnType int apnTypes, int[] qualifiedNetworkTypes) { mQualifiedNetworkTypesList.put(apnTypes, qualifiedNetworkTypes); if (mCallback != null) { try { @@ -198,6 +234,17 @@ public abstract class QualifiedNetworksService extends Service { } } + private void onReconnectQualifiedNetworkType(@ApnType int apnTypes, + @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType) { + if (mCallback != null) { + try { + mCallback.onReconnectQualifedNetworkType(apnTypes, qualifiedNetworkType); + } catch (RemoteException e) { + loge("Failed to call onReconnectQualifiedNetworkType. " + e); + } + } + } + /** * The framework calls this method when the throttle status of an APN changes. * @@ -366,6 +413,12 @@ public abstract class QualifiedNetworksService extends Service { case QNS_REQUEST_NETWORK_VALIDATION: if (provider == null) break; provider.onRequestNetworkValidation((NetworkValidationRequestData) message.obj); + break; + + case QNS_RECONNECT_QUALIFIED_NETWORK: + if (provider == null) break; + provider.onReconnectQualifiedNetworkType(message.arg2, (Integer) message.obj); + break; } } } diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt index 6209a0838d9b..ad39fa99c85b 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt @@ -17,8 +17,8 @@ package com.android.server.wm.flicker.activityembedding import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper import org.junit.Before diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt index 0c36c59a8a83..46ad77e1eff9 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.activityembedding.close import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt index 955e801e7e0a..af4f7a721464 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.activityembedding.layoutchange import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt index ce9c337ff9bd..e511b727d57f 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.activityembedding.open import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt index 59ff0c65c4fc..5009c7ce4e70 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.activityembedding.open import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt index 365782012c54..000b457026be 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.activityembedding.open import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt index 9f9fc23081c5..4352177a8984 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.activityembedding.open import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt index 30e833f433a8..62cf6cd528e9 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.activityembedding.open import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.region.RegionSubject import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt index c8cac8fa2c82..aa8b4cebe91d 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt @@ -17,14 +17,14 @@ package com.android.server.wm.flicker.activityembedding.pip import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Rect -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.ComponentNameMatcher.Companion.TRANSITION_SNAPSHOT -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher.Companion.TRANSITION_SNAPSHOT import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase @@ -176,9 +176,7 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) : val secondaryVisibleRegion = it.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) if (secondaryVisibleRegion.region.isNotEmpty) { - check { "left" } - .that(secondaryVisibleRegion.region.bounds.left) - .isGreater(0) + check { "left" }.that(secondaryVisibleRegion.region.bounds.left).isGreater(0) } } } @@ -217,7 +215,7 @@ class SecondaryActivityEnterPipTest(flicker: LegacyFlickerTest) : flicker.assertLayers { visibleLayersShownMoreThanOneConsecutiveEntry( LayersTraceSubject.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS + - listOf(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + listOf(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) ) } } diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt index 0dce870966d7..3d834c16163f 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.activityembedding.rotation import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt index f6d51f981915..511c94849681 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.activityembedding.rotation import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.setRotation import org.junit.Test diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt index 6be78f829b34..65a23e854e0b 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.activityembedding.rtl import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt index 576eec847066..7298e5f71b05 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt @@ -18,12 +18,12 @@ package com.android.server.wm.flicker.activityembedding.splitscreen import android.platform.test.annotations.Presubmit import android.platform.test.annotations.RequiresDevice -import android.tools.common.datatypes.Rect -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt index 64dd44d8b6e0..e19e1ce35cd9 100644 --- a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt +++ b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt @@ -16,11 +16,11 @@ package com.android.server.wm.flicker.close -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import org.junit.FixMethodOrder import org.junit.Test diff --git a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt index eb256b56193d..47ed642cd5f5 100644 --- a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt +++ b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt @@ -16,11 +16,11 @@ package com.android.server.wm.flicker.close -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import org.junit.FixMethodOrder import org.junit.Test diff --git a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppTransition.kt index ea025c74b8db..65bc35641128 100644 --- a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppTransition.kt +++ b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppTransition.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.close import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt index 89ab41e49270..ffa90a33e7b3 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt index 413767ce7618..8c285bda6616 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt @@ -16,9 +16,9 @@ package com.android.server.wm.flicker.launch -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.launch.common.OpenAppFromIconTransition import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt index 4168bdc705f1..d47329ea97b4 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.launch import android.tools.device.apphelpers.CameraAppHelper -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.launch.common.OpenAppFromLauncherTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt index 9c55c98a8f4f..267f282db41c 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt @@ -18,12 +18,12 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.launch.common.OpenAppFromLauncherTransition import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt index fc6cdb1ee01e..83065de8b592 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.launch.common.OpenAppFromLauncherTransition diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt index de666dd42877..44ae27c2ee4b 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.NonResizeableAppHelper diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt index f8a9961d1d28..6d3eaeb9c1b3 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.annotation.FlickerServiceCompatible -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.annotation.FlickerServiceCompatible +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.launch.common.OpenAppFromLauncherTransition diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt index 0aceb354dec6..bec02d0e59c6 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt @@ -18,15 +18,15 @@ package com.android.server.wm.flicker.launch import android.os.SystemClock import android.platform.test.annotations.Postsubmit -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.CameraAppHelper import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.traces.component.ComponentNameMatcher import android.view.KeyEvent import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.setRotation diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt index f41a2a297ad9..e0aef8d1addd 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.launch import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.TransferSplashscreenAppHelper diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt index 93ca41c4181c..f1144991c438 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt @@ -20,15 +20,15 @@ import android.app.Instrumentation import android.os.Bundle import android.os.Handler import android.platform.test.annotations.Presubmit -import android.tools.common.traces.ConditionsFactory -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerBuilderProvider -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.junit.FlickerBuilderProvider +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.ConditionsFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt index 3aee93296eee..b1d78cbc034e 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt @@ -20,20 +20,20 @@ import android.app.Instrumentation import android.app.WallpaperManager import android.content.res.Resources import android.platform.test.annotations.Presubmit -import android.tools.common.datatypes.Region -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.common.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.ComponentNameMatcher.Companion.SPLASH_SCREEN -import android.tools.common.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER -import android.tools.common.traces.component.ComponentSplashScreenMatcher -import android.tools.common.traces.component.IComponentMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.datatypes.Region +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS +import android.tools.helpers.WindowUtils +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher.Companion.SPLASH_SCREEN +import android.tools.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER +import android.tools.traces.component.ComponentSplashScreenMatcher +import android.tools.traces.component.IComponentMatcher +import android.tools.traces.parsers.toFlickerComponent import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.BaseTest @@ -215,9 +215,10 @@ class TaskTransitionTest(flicker: LegacyFlickerTest) : BaseTest(flicker) { component: IComponentMatcher, expectedArea: Region, isOptional: Boolean = true - ): LayersTraceSubject = invoke("$component coversExactly $expectedArea", isOptional) { - it.visibleRegion(component).coversExactly(expectedArea) - } + ): LayersTraceSubject = + invoke("$component coversExactly $expectedArea", isOptional) { + it.visibleRegion(component).coversExactly(expectedArea) + } @Parameterized.Parameters(name = "{0}") @JvmStatic diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt index 802c755116af..8a3304b0343d 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromIconTransition.kt @@ -16,10 +16,10 @@ package com.android.server.wm.flicker.launch.common -import android.tools.common.Rotation -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.Rotation +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.rules.RemoveAllTasksButHomeRule abstract class OpenAppFromIconTransition(flicker: LegacyFlickerTest) : OpenAppFromLauncherTransition(flicker) { diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLauncherTransition.kt index 9d7096ea0e73..b56e9a51187c 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLauncherTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLauncherTransition.kt @@ -17,8 +17,8 @@ package com.android.server.wm.flicker.launch.common import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.replacesLayer import org.junit.Test diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt index 7b088431b0bb..f8fd35860f6f 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppFromLockscreenTransition.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.launch.common import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.navBarLayerPositionAtEnd import com.android.server.wm.flicker.statusBarLayerPositionAtEnd diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppTransition.kt index 989619e08d98..7ca336daaa11 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/common/OpenAppTransition.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.launch.common import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.helpers.setRotation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt index 8242e9a31992..8a241de32a2b 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/Utils.kt @@ -20,12 +20,12 @@ import android.app.Instrumentation import android.platform.test.rule.NavigationModeRule import android.platform.test.rule.PressHomeRule import android.platform.test.rule.UnlockScreenRule -import android.tools.common.NavBar -import android.tools.common.Rotation +import android.tools.NavBar +import android.tools.Rotation import android.tools.device.apphelpers.MessagingAppHelper -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.flicker.rules.LaunchAppRule -import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.flicker.rules.LaunchAppRule +import android.tools.flicker.rules.RemoveAllTasksButHomeRule import androidx.test.platform.app.InstrumentationRegistry import org.junit.rules.RuleChain diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonLandscape.kt index b3c9c96c614c..8040610c485b 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppBackButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonPortrait.kt index 29c11a4257f6..aacccf4e680c 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButton3ButtonPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppBackButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavLandscape.kt index 1bb4a253ff41..74ee46093f6e 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppBackButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavPortrait.kt index 17cb6e194ec3..57463c33c1fa 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppBackButtonGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppBackButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonLandscape.kt index 47c25294f66e..3d5f0f2806d6 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonLandscape.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppHomeButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonPortrait.kt index b18148f97759..055cc727dc0b 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppHomeButton3ButtonPortrait.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppHomeButton import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavLandscape.kt index 85430154e202..38779811201d 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppSwipeToHome import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavPortrait.kt index f88963b7a341..ef7755e29ccf 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/flicker/CloseAppSwipeToHomeGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.close.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.close.scenarios.CloseAppSwipeToHome import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppBackButton.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppBackButton.kt index 2aaacde52547..17de26815079 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppBackButton.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppBackButton.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.service.close.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppHomeButton.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppHomeButton.kt index 08683a3ab43d..d8a88d4e6fb1 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppHomeButton.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppHomeButton.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.service.close.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppSwipeToHome.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppSwipeToHome.kt index 360e11408c92..f32f5ba57a7b 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppSwipeToHome.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/close/scenarios/CloseAppSwipeToHome.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.service.close.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavLandscape.kt index bb18770a8e7c..8b087509e486 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavPortrait.kt index 1c3cc2188c7c..cc7fe4d1111e 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationCold3ButtonNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavLandscape.kt index 46d36dbd6b09..f6414ca0ee29 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavPortrait.kt index f6a668feeed6..4244900302dc 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationColdGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavLandscape.kt index 93200ba1b6fe..548acbe08945 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavPortrait.kt index f5d41d250b1e..b231dd3319bb 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarm3ButtonNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavLandscape.kt index 28f322bee130..14f680a05b91 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavPortrait.kt index beb3fae8be48..6e07174d49cc 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWarmGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavLandscape.kt index 4adcc8bf5f0b..de71b9aab9c6 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWithOverlayApp import org.junit.Ignore import org.junit.Test diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavPortrait.kt index f7211e7287cf..714d5e8a7ee0 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayApp3ButtonNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWithOverlayApp import org.junit.Ignore import org.junit.Test diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavLandscape.kt index 1ade9560d90f..4c1bae78a8ad 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWithOverlayApp import org.junit.Ignore import org.junit.Test diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavPortrait.kt index ea26f0867c7f..0321f779f383 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromLockscreenNotificationWithOverlayAppGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromLockscreenNotificationWithOverlayApp import org.junit.Ignore import org.junit.Test diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavLandscape.kt index 866190f78827..e3b434d0ae7a 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavPortrait.kt index a8d628328ed9..64bce2e4b4df 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationCold3ButtonNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavLandscape.kt index ef84c3f1177e..83241bf19a33 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavPortrait.kt index 5bb6b3713e9f..06b89d38c2c6 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationColdGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationCold import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavLandscape.kt index 39f25e97f04c..8d3cf9084368 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavPortrait.kt index 28816bcba2a1..0d0adf26d57f 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarm3ButtonNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavLandscape.kt index 94ffe4e57994..1fbaddbfbb80 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavLandscape.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavPortrait.kt index e5f5ec4a6fe8..52df4bd809a1 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/flicker/OpenAppFromNotificationWarmGesturalNavPortrait.kt @@ -16,14 +16,14 @@ package com.android.server.wm.flicker.service.notification.flicker -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.notification.scenarios.OpenAppFromNotificationWarm import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/NotificationUtils.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/NotificationUtils.kt index ac4e16969bad..79d6bb71cbba 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/NotificationUtils.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/NotificationUtils.kt @@ -17,7 +17,7 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.WindowManagerStateHelper import android.view.WindowInsets import android.view.WindowManager import androidx.test.platform.app.InstrumentationRegistry diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationCold.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationCold.kt index 9c53ab30e8cd..e702f12c7538 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationCold.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationCold.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWarm.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWarm.kt index 31f55d9d2e99..0a509f860f76 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWarm.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWarm.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWithOverlayApp.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWithOverlayApp.kt index b971555f2747..ce6ee2f05526 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWithOverlayApp.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromLockscreenNotificationWithOverlayApp.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationCold.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationCold.kt index fed077ed0e50..e1cf32232734 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationCold.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationCold.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationWarm.kt index 403790e904d8..4dd84bd510c1 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationWarm.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/notification/scenarios/OpenAppFromNotificationWarm.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.notification.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.helpers.wakeUpAndGoToHomeScreen -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavLandscape.kt index d611a420edcb..da9f4bb88c1e 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchBetweenTwoAppsBack import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavPortrait.kt index e6bcbba661f3..f3ae920e1f87 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsBackGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchBetweenTwoAppsBack import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavLandscape.kt index 2a26d633adaf..a26906cc4a6f 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchBetweenTwoAppsForward import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavPortrait.kt index 5ce714371db0..01def0e1cd71 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchBetweenTwoAppsForwardGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchBetweenTwoAppsForward import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavLandscape.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavLandscape.kt index cff47bb8cc19..3f40e56ee0ff 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavLandscape.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavLandscape.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchFromLauncher import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavPortrait.kt index 33095a6ac078..70a95feef119 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavPortrait.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/flicker/QuickSwitchFromLauncherGesturalNavPortrait.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.service.quickswitch.flicker -import android.tools.common.Rotation -import android.tools.common.flicker.FlickerConfig -import android.tools.common.flicker.annotation.ExpectedScenarios -import android.tools.common.flicker.annotation.FlickerConfigProvider -import android.tools.common.flicker.config.FlickerConfig -import android.tools.common.flicker.config.FlickerServiceConfig -import android.tools.device.flicker.junit.FlickerServiceJUnit4ClassRunner +import android.tools.Rotation +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner import com.android.server.wm.flicker.service.quickswitch.scenarios.QuickSwitchFromLauncher import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsBack.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsBack.kt index a1708fe3a4b6..f0df37a9f37b 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsBack.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsBack.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.quickswitch.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.NonResizeableAppHelper diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsForward.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsForward.kt index fcf442a4e300..a22bdced6fcd 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsForward.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchBetweenTwoAppsForward.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.service.quickswitch.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.NonResizeableAppHelper diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchFromLauncher.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchFromLauncher.kt index 7afe5268ede4..e5aa181c95cd 100644 --- a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchFromLauncher.kt +++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/quickswitch/scenarios/QuickSwitchFromLauncher.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.service.quickswitch.scenarios import android.app.Instrumentation -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt index 99e8ef5e4c3d..7e486abbd30f 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.region.RegionSubject +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeEditorPopupDialogAppHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt index 48c54eabc5e2..2f3ec6301215 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt @@ -18,12 +18,12 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeAppHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt index 31d5d7f837d5..8821b69cdb3e 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt index 180ae5d6f097..d75eba68c7cc 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt index a0573b7b4b16..41d9e30a17ee 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt @@ -18,11 +18,11 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeAppHelper import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt index be47ec7098f9..0e7fb7975df8 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt @@ -18,13 +18,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.layers.LayersTraceSubject.Companion.VISIBLE_FOR_MORE_THAN_ONE_ENTRY_IGNORE_LAYERS +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeAppHelper import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt index 994edc592f5d..47a7e1b65b2d 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt @@ -16,15 +16,15 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.WindowUtils +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.region.RegionSubject +import android.tools.helpers.WindowUtils +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt index ea7c7c4276dc..e8249bca4c2d 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt @@ -18,13 +18,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.subject.layers.LayerTraceEntrySubject +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt index b7a183d7f7fe..617237d37368 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import com.android.server.wm.flicker.helpers.setRotation diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt index 6ee5a9a775b3..7b62c8967628 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt index 1ad5c0de282b..53bfb4ecf66f 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import com.android.server.wm.flicker.helpers.ImeStateInitializeHelper diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt index 918e1ea3bcd0..12290af8fd46 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt @@ -18,11 +18,11 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeAppHelper import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt index 181a2a229940..0948351ac65b 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import android.view.WindowInsets.Type.ime import android.view.WindowInsets.Type.navigationBars import android.view.WindowInsets.Type.statusBars @@ -55,10 +55,12 @@ class ShowImeWhileDismissingThemedPopupDialogTest(flicker: LegacyFlickerTest) : testApp.launchViaIntent(wmHelper) testApp.waitIMEShown(wmHelper) broadcastActionTrigger.doAction(ACTION_START_DIALOG_THEMED_ACTIVITY) - wmHelper.StateSyncBuilder() - .withFullScreenApp( - ActivityOptions.DialogThemedActivity.COMPONENT.toFlickerComponent()) - .waitForAndVerify() + wmHelper + .StateSyncBuilder() + .withFullScreenApp( + ActivityOptions.DialogThemedActivity.COMPONENT.toFlickerComponent() + ) + .waitForAndVerify() // Verify IME insets isn't visible on dialog since it's non-IME focusable window assertFalse(testApp.getInsetsVisibleFromDialog(ime())) assertTrue(testApp.getInsetsVisibleFromDialog(statusBars())) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt index f1bc125b99dc..a14dc62b0023 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.Presubmit -import android.tools.common.traces.ConditionsFactory -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.traces.parsers.WindowManagerStateHelper +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.ConditionsFactory +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/common/CommonAssertions.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/common/CommonAssertions.kt index 777231e001f7..bd3d1ce3de50 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/common/CommonAssertions.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/common/CommonAssertions.kt @@ -18,8 +18,8 @@ package com.android.server.wm.flicker.ime -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher fun LegacyFlickerTest.imeLayerBecomesVisible() { assertLayers { diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/Consts.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/Consts.kt index b81439e8a1d1..edcee46affe6 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/Consts.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/Consts.kt @@ -16,7 +16,7 @@ package com.android.server.wm.flicker.notification -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.traces.component.ComponentNameMatcher object Consts { val IMAGE_WALLPAPER = ComponentNameMatcher("", "com.android.systemui.wallpapers.ImageWallpaper") diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt index 620502e521c4..ffaeeadb1042 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt @@ -20,12 +20,12 @@ import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.platform.test.rule.SettingOverrideRule import android.provider.Settings -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.RequiresDevice import org.junit.ClassRule import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt index 2a458ef82448..6e67e193ed8c 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt @@ -19,11 +19,11 @@ package com.android.server.wm.flicker.notification import android.platform.test.annotations.Presubmit import android.platform.test.rule.SettingOverrideRule import android.provider.Settings -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.statusBarLayerPositionAtEnd diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt index 00aad2783d5d..8e210d455591 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt @@ -18,12 +18,12 @@ package com.android.server.wm.flicker.notification import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt index f8d78b5ddd1e..b6d09d0bf3bb 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt @@ -18,12 +18,12 @@ package com.android.server.wm.flicker.notification import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.statusBarLayerPositionAtEnd import org.junit.FixMethodOrder diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt index 5c7ec46d6f04..1e607bfb2f49 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt @@ -18,13 +18,13 @@ package com.android.server.wm.flicker.notification import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.FlickerTestData -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory -import android.tools.device.helpers.wakeUpAndGoToHomeScreen +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.FlickerTestData +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.helpers.wakeUpAndGoToHomeScreen +import android.tools.traces.component.ComponentNameMatcher import android.view.WindowInsets import android.view.WindowManager import androidx.test.uiautomator.By diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt index 4e0e3c04ae5a..4ba444b0815a 100644 --- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt +++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.notification import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.SimpleAppHelper import org.junit.Test diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt index 13fcc2ba0b54..8b09b590e790 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.quickswitch import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.datatypes.Rect -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.NonResizeableAppHelper diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt index badd7c8c712c..c54ddcf793f6 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt @@ -16,13 +16,13 @@ package com.android.server.wm.flicker.quickswitch -import android.tools.common.NavBar -import android.tools.common.datatypes.Rect -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.NonResizeableAppHelper diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt index f51be908750a..69a84a0cbcb0 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt @@ -17,14 +17,14 @@ package com.android.server.wm.flicker.quickswitch import android.platform.test.annotations.Presubmit -import android.tools.common.NavBar -import android.tools.common.Rotation -import android.tools.common.datatypes.Rect -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.NavBar +import android.tools.Rotation +import android.tools.datatypes.Rect +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import androidx.test.filters.FlakyTest import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.SimpleAppHelper diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index bdbf0d24e624..05ab364ed72c 100644 --- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -18,11 +18,11 @@ package com.android.server.wm.flicker.rotation import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.helpers.SimpleAppHelper import org.junit.FixMethodOrder import org.junit.Test diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt index 79d3a10a34cb..c7da778b752b 100644 --- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt +++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/RotationTransition.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.rotation import android.platform.test.annotations.Presubmit -import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.IComponentMatcher -import android.tools.common.traces.surfaceflinger.Display import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.subject.layers.LayerTraceEntrySubject +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.IComponentMatcher +import android.tools.traces.surfaceflinger.Display import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.setRotation import org.junit.Test @@ -76,9 +76,9 @@ abstract class RotationTransition(flicker: LegacyFlickerTest) : BaseTest(flicker } private fun LayerTraceEntrySubject.getDisplay(componentMatcher: IComponentMatcher): Display { - val stackId = this.layer { - componentMatcher.layerMatchesAnyOf(it) && it.isVisible - }?.layer?.stackId ?: -1 + val stackId = + this.layer { componentMatcher.layerMatchesAnyOf(it) && it.isVisible }?.layer?.stackId + ?: -1 return this.entry.displays.firstOrNull { it.layerStackId == stackId } ?: error("Unable to find visible layer for $componentMatcher") diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt index 6d3ae43c1472..a41362857420 100644 --- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt +++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt @@ -18,13 +18,13 @@ package com.android.server.wm.flicker.rotation import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit -import android.tools.common.ScenarioBuilder -import android.tools.common.ScenarioImpl -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import android.tools.ScenarioBuilder +import android.tools.ScenarioImpl +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.legacy.LegacyFlickerTestFactory +import android.tools.traces.component.ComponentNameMatcher import android.view.WindowManager import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt index ce92eac3fc59..17f91ebad771 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt @@ -19,10 +19,10 @@ package com.android.server.wm.flicker import android.app.Instrumentation import android.content.Intent import android.platform.test.annotations.Presubmit -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.flicker.junit.FlickerBuilderProvider -import android.tools.device.flicker.legacy.FlickerBuilder -import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.junit.FlickerBuilderProvider +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher import android.util.Log import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt index 1abb8c217603..8853c1db856f 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt @@ -18,15 +18,15 @@ package com.android.server.wm.flicker -import android.tools.common.PlatformConsts -import android.tools.common.Position -import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject -import android.tools.common.flicker.subject.region.RegionSubject -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.IComponentNameMatcher -import android.tools.common.traces.wm.WindowManagerTrace -import android.tools.device.flicker.legacy.LegacyFlickerTest -import android.tools.device.helpers.WindowUtils +import android.tools.PlatformConsts +import android.tools.Position +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.flicker.subject.layers.LayerTraceEntrySubject +import android.tools.flicker.subject.region.RegionSubject +import android.tools.helpers.WindowUtils +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.IComponentNameMatcher +import android.tools.traces.wm.WindowManagerTrace /** * Checks that [ComponentNameMatcher.STATUS_BAR] window is visible and above the app windows in all diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt index 11e6bbe4eb13..4a675be65549 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt @@ -17,12 +17,12 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.PlatformConsts -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.PlatformConsts import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import android.util.Log import androidx.test.uiautomator.By import androidx.test.uiautomator.Until diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt index 94ac1a6e1e02..ec661d75eb17 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt @@ -17,8 +17,8 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper +import android.tools.traces.component.ComponentNameMatcher class AppPairsHelper( instrumentation: Instrumentation, diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt index fde098199042..53337251640e 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt @@ -19,7 +19,7 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation import android.content.ComponentName import android.provider.Settings -import android.tools.device.helpers.FIND_TIMEOUT +import android.tools.helpers.FIND_TIMEOUT import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt index c6fa1bb89220..1915225f05b0 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class FixedOrientationAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt index 5c8cbe49d7cf..926209f93128 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt @@ -18,9 +18,9 @@ package com.android.server.wm.flicker.helpers -import android.tools.common.Rotation -import android.tools.device.flicker.legacy.FlickerTestData -import android.tools.device.flicker.rules.ChangeDisplayOrientationRule +import android.tools.Rotation +import android.tools.flicker.legacy.FlickerTestData +import android.tools.flicker.rules.ChangeDisplayOrientationRule /** * Changes the device [rotation] and wait for the rotation animation to complete diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt index 3146139757c1..0c60f284a35b 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction import androidx.test.uiautomator.Until diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt index cb1aab0bfeea..495fbce6558a 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt index 7a8d780c3d9f..6fe7c29b543d 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt index 0ee7aeeb30c6..f5c88e3fea5c 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt @@ -17,13 +17,13 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.Rotation -import android.tools.common.traces.component.ComponentNameMatcher -import android.tools.common.traces.component.IComponentMatcher -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.helpers.IME_PACKAGE -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.Rotation +import android.tools.helpers.FIND_TIMEOUT +import android.tools.helpers.IME_PACKAGE +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.component.IComponentMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import android.view.WindowInsets.Type.ime import android.view.WindowInsets.Type.navigationBars import android.view.WindowInsets.Type.statusBars diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt index b2aeb14aaf78..db93bf7966de 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class ImeStateInitializeHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt index b95d86b72f34..d6ead85e9666 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt @@ -18,7 +18,7 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class LaunchBubbleHelper(instrumentation: Instrumentation) : diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt index 9b539c8641d4..b09e53b6400d 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt @@ -17,14 +17,14 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.datatypes.Rect -import android.tools.common.datatypes.Region -import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.datatypes.Rect +import android.tools.datatypes.Region import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.helpers.SYSTEMUI_PACKAGE -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.helpers.SYSTEMUI_PACKAGE +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt index 9895bda7f590..d4075e92d4bc 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt @@ -17,10 +17,10 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction import androidx.test.uiautomator.UiObject2 diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt index 65175ef33afb..29c1cde74fac 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt @@ -19,8 +19,8 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation import android.content.Context import android.provider.Settings -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper +import android.tools.traces.component.ComponentNameMatcher import android.util.Log import com.android.compatibility.common.util.SystemUtil import java.io.IOException diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt index b2f8d4748c07..ea4ea0a417df 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt index ee65004e9e78..ebf348703f76 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class NonResizeableAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt index e60c20df9967..c559d0faf42d 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.testapp.ActivityOptions diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index 452c98c65a7f..db933b30a822 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -20,15 +20,15 @@ import android.app.Instrumentation import android.content.Intent import android.media.session.MediaController import android.media.session.MediaSessionManager -import android.tools.common.datatypes.Rect -import android.tools.common.datatypes.Region -import android.tools.common.traces.ConditionsFactory -import android.tools.common.traces.component.IComponentMatcher +import android.tools.datatypes.Rect +import android.tools.datatypes.Region import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.helpers.SYSTEMUI_PACKAGE -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.helpers.SYSTEMUI_PACKAGE +import android.tools.traces.ConditionsFactory +import android.tools.traces.component.IComponentMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import android.util.Log import androidx.test.uiautomator.By import androidx.test.uiautomator.Until diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt index cac3530399de..55d43e654e7e 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class SeamlessRotationAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt index 8366a7a1fe41..05856ccc93c3 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class ShowWhenLockedAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt index 89c6c35af47d..82ef39834e74 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class SimpleAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TransferSplashscreenAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TransferSplashscreenAppHelper.kt index 6311678f1a04..ffe077ecd486 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TransferSplashscreenAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TransferSplashscreenAppHelper.kt @@ -17,9 +17,9 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.toFlickerComponent import com.android.server.wm.flicker.testapp.ActivityOptions class TransferSplashscreenAppHelper diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt index 8be5769f47cf..867bcb6db988 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt @@ -17,11 +17,11 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation -import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.apphelpers.StandardAppHelper -import android.tools.device.helpers.FIND_TIMEOUT -import android.tools.device.traces.parsers.WindowManagerStateHelper -import android.tools.device.traces.parsers.toFlickerComponent +import android.tools.helpers.FIND_TIMEOUT +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp index a4877999ff6f..827ff4fbd989 100644 --- a/tests/Internal/Android.bp +++ b/tests/Internal/Android.bp @@ -21,6 +21,9 @@ android_test { "mockito-target-minus-junit4", "truth", "platform-test-annotations", + "flickerlib-parsers", + "perfetto_trace_java_protos", + "flickerlib-trace_processor_shell", ], java_resource_dirs: ["res"], certificate: "platform", diff --git a/tests/Internal/AndroidManifest.xml b/tests/Internal/AndroidManifest.xml index dbba24531769..9a3fe617e70a 100644 --- a/tests/Internal/AndroidManifest.xml +++ b/tests/Internal/AndroidManifest.xml @@ -19,7 +19,11 @@ package="com.android.internal.tests"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.BIND_WALLPAPER"/> - <application> + <!-- Allow the test to connect to perfetto trace processor --> + <uses-permission android:name="android.permission.INTERNET"/> + <application + android:requestLegacyExternalStorage="true" + android:networkSecurityConfig="@xml/network_security_config"> <uses-library android:name="android.test.runner"/> <service android:name="stub.DummyWallpaperService" diff --git a/tests/Internal/res/xml/network_security_config.xml b/tests/Internal/res/xml/network_security_config.xml new file mode 100644 index 000000000000..fdf1dbbe7672 --- /dev/null +++ b/tests/Internal/res/xml/network_security_config.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<network-security-config> + <domain-config cleartextTrafficPermitted="true"> + <domain includeSubdomains="true">localhost</domain> + </domain-config> +</network-security-config> diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java new file mode 100644 index 000000000000..a64996c6838e --- /dev/null +++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.android.internal.protolog.LegacyProtoLogImpl.PROTOLOG_VERSION; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.SystemClock; +import android.platform.test.annotations.Presubmit; +import android.util.proto.ProtoInputStream; + +import androidx.test.filters.SmallTest; + +import com.android.internal.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.LogLevel; + +import org.junit.After; +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.Mockito; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.LinkedList; + +/** + * Test class for {@link ProtoLogImpl}. + */ +@SuppressWarnings("ConstantConditions") +@SmallTest +@Presubmit +@RunWith(JUnit4.class) +public class LegacyProtoLogImplTest { + + private static final byte[] MAGIC_HEADER = new byte[]{ + 0x9, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47 + }; + + private LegacyProtoLogImpl mProtoLog; + private File mFile; + + @Mock + private LegacyProtoLogViewerConfigReader mReader; + + private final String mViewerConfigFilename = "unused/file/path"; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + final Context testContext = getInstrumentation().getContext(); + mFile = testContext.getFileStreamPath("tracing_test.dat"); + //noinspection ResultOfMethodCallIgnored + mFile.delete(); + mProtoLog = new LegacyProtoLogImpl(mFile, mViewerConfigFilename, + 1024 * 1024, mReader, 1024); + } + + @After + public void tearDown() { + if (mFile != null) { + //noinspection ResultOfMethodCallIgnored + mFile.delete(); + } + ProtoLogImpl.setSingleInstance(null); + } + + @Test + public void isEnabled_returnsFalseByDefault() { + assertFalse(mProtoLog.isProtoEnabled()); + } + + @Test + public void isEnabled_returnsTrueAfterStart() { + mProtoLog.startProtoLog(mock(PrintWriter.class)); + assertTrue(mProtoLog.isProtoEnabled()); + } + + @Test + public void isEnabled_returnsFalseAfterStop() { + mProtoLog.startProtoLog(mock(PrintWriter.class)); + mProtoLog.stopProtoLog(mock(PrintWriter.class), true); + assertFalse(mProtoLog.isProtoEnabled()); + } + + @Test + public void logFile_startsWithMagicHeader() throws Exception { + mProtoLog.startProtoLog(mock(PrintWriter.class)); + mProtoLog.stopProtoLog(mock(PrintWriter.class), true); + + assertTrue("Log file should exist", mFile.exists()); + + byte[] header = new byte[MAGIC_HEADER.length]; + try (InputStream is = new FileInputStream(mFile)) { + assertEquals(MAGIC_HEADER.length, is.read(header)); + assertArrayEquals(MAGIC_HEADER, header); + } + } + + @Test + public void log_logcatEnabledExternalMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f"); + LegacyProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{true, 10000, 30000, "test", 0.000003}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), + eq("test true 10000 % 0x7530 test 3.0E-6")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatEnabledInvalidMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f"); + LegacyProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{true, 10000, 0.0001, 0.00002, "test"}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), + eq("UNKNOWN MESSAGE (1234) true 10000 1.0E-4 2.0E-5 test")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatEnabledInlineMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %d"); + LegacyProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", + new Object[]{5}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), eq("test 5")); + verify(mReader, never()).getViewerString(anyLong()); + } + + @Test + public void log_logcatEnabledNoMessage() { + when(mReader.getViewerString(anyLong())).thenReturn(null); + LegacyProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{5}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), eq("UNKNOWN MESSAGE (1234) 5")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatDisabled() { + when(mReader.getViewerString(anyLong())).thenReturn("test %d"); + LegacyProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", + new Object[]{5}); + + verify(implSpy, never()).passToLogcat(any(), any(), any()); + verify(mReader, never()).getViewerString(anyLong()); + } + + private static class ProtoLogData { + Long mMessageHash = null; + Long mElapsedTime = null; + LinkedList<String> mStrParams = new LinkedList<>(); + LinkedList<Long> mSint64Params = new LinkedList<>(); + LinkedList<Double> mDoubleParams = new LinkedList<>(); + LinkedList<Boolean> mBooleanParams = new LinkedList<>(); + } + + private ProtoLogData readProtoLogSingle(ProtoInputStream ip) throws IOException { + while (ip.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + if (ip.getFieldNumber() == (int) ProtoLogFileProto.VERSION) { + assertEquals(PROTOLOG_VERSION, ip.readString(ProtoLogFileProto.VERSION)); + continue; + } + if (ip.getFieldNumber() != (int) ProtoLogFileProto.LOG) { + continue; + } + long token = ip.start(ProtoLogFileProto.LOG); + ProtoLogData data = new ProtoLogData(); + while (ip.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (ip.getFieldNumber()) { + case (int) ProtoLogMessage.MESSAGE_HASH: { + data.mMessageHash = ip.readLong(ProtoLogMessage.MESSAGE_HASH); + break; + } + case (int) ProtoLogMessage.ELAPSED_REALTIME_NANOS: { + data.mElapsedTime = ip.readLong(ProtoLogMessage.ELAPSED_REALTIME_NANOS); + break; + } + case (int) ProtoLogMessage.STR_PARAMS: { + data.mStrParams.add(ip.readString(ProtoLogMessage.STR_PARAMS)); + break; + } + case (int) ProtoLogMessage.SINT64_PARAMS: { + data.mSint64Params.add(ip.readLong(ProtoLogMessage.SINT64_PARAMS)); + break; + } + case (int) ProtoLogMessage.DOUBLE_PARAMS: { + data.mDoubleParams.add(ip.readDouble(ProtoLogMessage.DOUBLE_PARAMS)); + break; + } + case (int) ProtoLogMessage.BOOLEAN_PARAMS: { + data.mBooleanParams.add(ip.readBoolean(ProtoLogMessage.BOOLEAN_PARAMS)); + break; + } + } + } + ip.end(token); + return data; + } + return null; + } + + @Test + public void log_protoEnabled() throws Exception { + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); + TestProtoLogGroup.TEST_GROUP.setLogToProto(true); + mProtoLog.startProtoLog(mock(PrintWriter.class)); + long before = SystemClock.elapsedRealtimeNanos(); + mProtoLog.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, + 0b1110101001010100, null, + new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true}); + long after = SystemClock.elapsedRealtimeNanos(); + mProtoLog.stopProtoLog(mock(PrintWriter.class), true); + try (InputStream is = new FileInputStream(mFile)) { + ProtoInputStream ip = new ProtoInputStream(is); + ProtoLogData data = readProtoLogSingle(ip); + assertNotNull(data); + assertEquals(1234, data.mMessageHash.longValue()); + assertTrue(before <= data.mElapsedTime && data.mElapsedTime <= after); + assertArrayEquals(new String[]{"test"}, data.mStrParams.toArray()); + assertArrayEquals(new Long[]{1L, 2L, 3L}, data.mSint64Params.toArray()); + assertArrayEquals(new Double[]{0.4, 0.5, 0.6}, data.mDoubleParams.toArray()); + assertArrayEquals(new Boolean[]{true}, data.mBooleanParams.toArray()); + } + } + + @Test + public void log_invalidParamsMask() throws Exception { + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); + TestProtoLogGroup.TEST_GROUP.setLogToProto(true); + mProtoLog.startProtoLog(mock(PrintWriter.class)); + long before = SystemClock.elapsedRealtimeNanos(); + mProtoLog.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, + 0b01100100, null, + new Object[]{"test", 1, 0.1, true}); + long after = SystemClock.elapsedRealtimeNanos(); + mProtoLog.stopProtoLog(mock(PrintWriter.class), true); + try (InputStream is = new FileInputStream(mFile)) { + ProtoInputStream ip = new ProtoInputStream(is); + ProtoLogData data = readProtoLogSingle(ip); + assertNotNull(data); + assertEquals(1234, data.mMessageHash.longValue()); + assertTrue(before <= data.mElapsedTime && data.mElapsedTime <= after); + assertArrayEquals(new String[]{"test", "(INVALID PARAMS_MASK) true"}, + data.mStrParams.toArray()); + assertArrayEquals(new Long[]{1L}, data.mSint64Params.toArray()); + assertArrayEquals(new Double[]{0.1}, data.mDoubleParams.toArray()); + assertArrayEquals(new Boolean[]{}, data.mBooleanParams.toArray()); + } + } + + @Test + public void log_protoDisabled() throws Exception { + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + mProtoLog.startProtoLog(mock(PrintWriter.class)); + mProtoLog.log(LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, + 0b11, null, new Object[]{true}); + mProtoLog.stopProtoLog(mock(PrintWriter.class), true); + try (InputStream is = new FileInputStream(mFile)) { + ProtoInputStream ip = new ProtoInputStream(is); + ProtoLogData data = readProtoLogSingle(ip); + assertNull(data); + } + } + + private enum TestProtoLogGroup implements IProtoLogGroup { + TEST_GROUP(true, true, false, "WindowManagetProtoLogTest"); + + private final boolean mEnabled; + private volatile boolean mLogToProto; + private volatile boolean mLogToLogcat; + private final String mTag; + + /** + * @param enabled set to false to exclude all log statements for this group from + * compilation, + * they will not be available in runtime. + * @param logToProto enable binary logging for the group + * @param logToLogcat enable text logging for the group + * @param tag name of the source of the logged message + */ + TestProtoLogGroup(boolean enabled, boolean logToProto, boolean logToLogcat, String tag) { + this.mEnabled = enabled; + this.mLogToProto = logToProto; + this.mLogToLogcat = logToLogcat; + this.mTag = tag; + } + + @Override + public boolean isEnabled() { + return mEnabled; + } + + @Override + public boolean isLogToProto() { + return mLogToProto; + } + + @Override + public boolean isLogToLogcat() { + return mLogToLogcat; + } + + @Override + public boolean isLogToAny() { + return mLogToLogcat || mLogToProto; + } + + @Override + public String getTag() { + return mTag; + } + + @Override + public void setLogToProto(boolean logToProto) { + this.mLogToProto = logToProto; + } + + @Override + public void setLogToLogcat(boolean logToLogcat) { + this.mLogToLogcat = logToLogcat; + } + + } +} diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java new file mode 100644 index 000000000000..b9f1738f9bb7 --- /dev/null +++ b/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeTrue; + +import android.tracing.perfetto.CreateTlsStateArgs; +import android.util.proto.ProtoInputStream; + +import com.android.internal.protolog.common.LogLevel; + +import com.google.common.truth.Truth; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import perfetto.protos.DataSourceConfigOuterClass; +import perfetto.protos.ProtologCommon; +import perfetto.protos.ProtologConfig; + +public class PerfettoDataSourceTest { + @Before + public void before() { + assumeTrue(android.tracing.Flags.perfettoProtolog()); + } + + @Test + public void noConfig() { + final ProtoLogDataSource.TlsState tlsState = createTlsState( + DataSourceConfigOuterClass.DataSourceConfig.newBuilder().build()); + + Truth.assertThat(tlsState.getLogFromLevel("SOME_TAG")).isEqualTo(LogLevel.WTF); + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_TAG")).isFalse(); + } + + @Test + public void defaultTraceMode() { + final ProtoLogDataSource.TlsState tlsState = createTlsState( + DataSourceConfigOuterClass.DataSourceConfig.newBuilder() + .setProtologConfig( + ProtologConfig.ProtoLogConfig.newBuilder() + .setTracingMode( + ProtologConfig.ProtoLogConfig.TracingMode + .ENABLE_ALL) + .build() + ).build()); + + Truth.assertThat(tlsState.getLogFromLevel("SOME_TAG")).isEqualTo(LogLevel.DEBUG); + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_TAG")).isFalse(); + } + + @Test + public void allEnabledTraceMode() { + final ProtoLogDataSource ds = new ProtoLogDataSource(() -> {}, () -> {}, () -> {}); + + final ProtoLogDataSource.TlsState tlsState = createTlsState( + DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig( + ProtologConfig.ProtoLogConfig.newBuilder() + .setTracingMode( + ProtologConfig.ProtoLogConfig.TracingMode.ENABLE_ALL) + .build() + ).build() + ); + + Truth.assertThat(tlsState.getLogFromLevel("SOME_TAG")).isEqualTo(LogLevel.DEBUG); + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_TAG")).isFalse(); + } + + @Test + public void requireGroupTagInOverrides() { + Exception exception = assertThrows(RuntimeException.class, () -> { + createTlsState(DataSourceConfigOuterClass.DataSourceConfig.newBuilder() + .setProtologConfig( + ProtologConfig.ProtoLogConfig.newBuilder() + .addGroupOverrides( + ProtologConfig.ProtoLogGroup.newBuilder() + .setLogFrom( + ProtologCommon.ProtoLogLevel + .PROTOLOG_LEVEL_WARN) + .setCollectStacktrace(true) + ) + .build() + ).build()); + }); + + Truth.assertThat(exception).hasMessageThat().contains("group override without a group tag"); + } + + @Test + public void stackTraceCollection() { + final ProtoLogDataSource.TlsState tlsState = createTlsState( + DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig( + ProtologConfig.ProtoLogConfig.newBuilder() + .addGroupOverrides( + ProtologConfig.ProtoLogGroup.newBuilder() + .setGroupName("SOME_TAG") + .setCollectStacktrace(true) + ) + .build() + ).build()); + + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_TAG")).isTrue(); + } + + @Test + public void groupLogFromOverrides() { + final ProtoLogDataSource.TlsState tlsState = createTlsState( + DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig( + ProtologConfig.ProtoLogConfig.newBuilder() + .addGroupOverrides( + ProtologConfig.ProtoLogGroup.newBuilder() + .setGroupName("SOME_TAG") + .setLogFrom( + ProtologCommon.ProtoLogLevel + .PROTOLOG_LEVEL_DEBUG) + .setCollectStacktrace(true) + ) + .addGroupOverrides( + ProtologConfig.ProtoLogGroup.newBuilder() + .setGroupName("SOME_OTHER_TAG") + .setLogFrom( + ProtologCommon.ProtoLogLevel + .PROTOLOG_LEVEL_WARN) + ) + .build() + ).build()); + + Truth.assertThat(tlsState.getLogFromLevel("SOME_TAG")).isEqualTo(LogLevel.DEBUG); + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_TAG")).isTrue(); + + Truth.assertThat(tlsState.getLogFromLevel("SOME_OTHER_TAG")).isEqualTo(LogLevel.WARN); + Truth.assertThat(tlsState.getShouldCollectStacktrace("SOME_OTHER_TAG")).isFalse(); + + Truth.assertThat(tlsState.getLogFromLevel("UNKNOWN_TAG")).isEqualTo(LogLevel.WTF); + Truth.assertThat(tlsState.getShouldCollectStacktrace("UNKNOWN_TAG")).isFalse(); + } + + private ProtoLogDataSource.TlsState createTlsState( + DataSourceConfigOuterClass.DataSourceConfig config) { + final ProtoLogDataSource ds = + Mockito.spy(new ProtoLogDataSource(() -> {}, () -> {}, () -> {})); + + ProtoInputStream configStream = new ProtoInputStream(config.toByteArray()); + final ProtoLogDataSource.Instance dsInstance = Mockito.spy( + ds.createInstance(configStream, 8)); + Mockito.doNothing().when(dsInstance).release(); + final CreateTlsStateArgs mockCreateTlsStateArgs = Mockito.mock(CreateTlsStateArgs.class); + Mockito.when(mockCreateTlsStateArgs.getDataSourceInstanceLocked()).thenReturn(dsInstance); + return ds.createTlsState(mockCreateTlsStateArgs); + } +} diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java new file mode 100644 index 000000000000..270f5957a9b9 --- /dev/null +++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java @@ -0,0 +1,586 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.protolog; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import static java.io.File.createTempFile; +import static java.nio.file.Files.createTempDirectory; + +import android.content.Context; +import android.os.SystemClock; +import android.platform.test.annotations.Presubmit; +import android.tools.ScenarioBuilder; +import android.tools.traces.TraceConfig; +import android.tools.traces.TraceConfigs; +import android.tools.traces.io.ResultReader; +import android.tools.traces.io.ResultWriter; +import android.tools.traces.monitors.PerfettoTraceMonitor; +import android.tools.traces.protolog.ProtoLogTrace; +import android.tracing.perfetto.DataSource; +import android.util.proto.ProtoInputStream; + +import androidx.test.filters.SmallTest; + +import com.android.internal.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.LogDataType; +import com.android.internal.protolog.common.LogLevel; + +import com.google.common.truth.Truth; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Random; + +import perfetto.protos.Protolog; +import perfetto.protos.ProtologCommon; + +/** + * Test class for {@link ProtoLogImpl}. + */ +@SuppressWarnings("ConstantConditions") +@SmallTest +@Presubmit +@RunWith(JUnit4.class) +public class PerfettoProtoLogImplTest { + private final File mTracingDirectory = createTempDirectory("temp").toFile(); + + private final ResultWriter mWriter = new ResultWriter() + .forScenario(new ScenarioBuilder() + .forClass(createTempFile("temp", "").getName()).build()) + .withOutputDir(mTracingDirectory) + .setRunComplete(); + + private final TraceConfigs mTraceConfig = new TraceConfigs( + new TraceConfig(false, true, false), + new TraceConfig(false, true, false), + new TraceConfig(false, true, false), + new TraceConfig(false, true, false) + ); + + private PerfettoProtoLogImpl mProtoLog; + private Protolog.ProtoLogViewerConfig.Builder mViewerConfigBuilder; + private File mFile; + + private ProtoLogViewerConfigReader mReader; + + public PerfettoProtoLogImplTest() throws IOException { + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + final Context testContext = getInstrumentation().getContext(); + mFile = testContext.getFileStreamPath("tracing_test.dat"); + //noinspection ResultOfMethodCallIgnored + mFile.delete(); + + mViewerConfigBuilder = Protolog.ProtoLogViewerConfig.newBuilder() + .addGroups( + Protolog.ProtoLogViewerConfig.Group.newBuilder() + .setId(1) + .setName(TestProtoLogGroup.TEST_GROUP.toString()) + .setTag(TestProtoLogGroup.TEST_GROUP.getTag()) + ).addMessages( + Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(1) + .setMessage("My Test Debug Log Message %b") + .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_DEBUG) + .setGroupId(1) + ).addMessages( + Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(2) + .setMessage("My Test Verbose Log Message %b") + .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_VERBOSE) + .setGroupId(1) + ).addMessages( + Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(3) + .setMessage("My Test Warn Log Message %b") + .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_WARN) + .setGroupId(1) + ).addMessages( + Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(4) + .setMessage("My Test Error Log Message %b") + .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_ERROR) + .setGroupId(1) + ).addMessages( + Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(5) + .setMessage("My Test WTF Log Message %b") + .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_WTF) + .setGroupId(1) + ); + + ViewerConfigInputStreamProvider viewerConfigInputStreamProvider = Mockito.mock( + ViewerConfigInputStreamProvider.class); + Mockito.when(viewerConfigInputStreamProvider.getInputStream()) + .thenAnswer(it -> new ProtoInputStream(mViewerConfigBuilder.build().toByteArray())); + + mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider)); + mProtoLog = new PerfettoProtoLogImpl(viewerConfigInputStreamProvider, mReader); + } + + @After + public void tearDown() { + if (mFile != null) { + //noinspection ResultOfMethodCallIgnored + mFile.delete(); + } + ProtoLogImpl.setSingleInstance(null); + } + + @Test + public void isEnabled_returnsFalseByDefault() { + assertFalse(mProtoLog.isProtoEnabled()); + } + + @Test + public void isEnabled_returnsTrueAfterStart() { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog().build(); + try { + traceMonitor.start(); + assertTrue(mProtoLog.isProtoEnabled()); + } finally { + traceMonitor.stop(mWriter); + } + } + + @Test + public void isEnabled_returnsFalseAfterStop() { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog().build(); + try { + traceMonitor.start(); + assertTrue(mProtoLog.isProtoEnabled()); + } finally { + traceMonitor.stop(mWriter); + } + + assertFalse(mProtoLog.isProtoEnabled()); + } + + @Test + public void defaultMode() throws IOException { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(false).build(); + try { + traceMonitor.start(); + // Shouldn't be logging anything except WTF unless explicitly requested in the group + // override. + mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5, + LogDataType.BOOLEAN, null, new Object[]{true}); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(1); + Truth.assertThat(protolog.messages.getFirst().getLevel()).isEqualTo(LogLevel.WTF); + } + + @Test + public void respectsOverrideConfigs_defaultMode() throws IOException { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(true, + List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride( + TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true))) + .build(); + try { + traceMonitor.start(); + mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5, + LogDataType.BOOLEAN, null, new Object[]{true}); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(5); + Truth.assertThat(protolog.messages.get(0).getLevel()).isEqualTo(LogLevel.DEBUG); + Truth.assertThat(protolog.messages.get(1).getLevel()).isEqualTo(LogLevel.VERBOSE); + Truth.assertThat(protolog.messages.get(2).getLevel()).isEqualTo(LogLevel.WARN); + Truth.assertThat(protolog.messages.get(3).getLevel()).isEqualTo(LogLevel.ERROR); + Truth.assertThat(protolog.messages.get(4).getLevel()).isEqualTo(LogLevel.WTF); + } + + @Test + public void respectsOverrideConfigs_allEnabledMode() throws IOException { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(true, + List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride( + TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN, false))) + .build(); + try { + traceMonitor.start(); + mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5, + LogDataType.BOOLEAN, null, new Object[]{true}); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(3); + Truth.assertThat(protolog.messages.get(0).getLevel()).isEqualTo(LogLevel.WARN); + Truth.assertThat(protolog.messages.get(1).getLevel()).isEqualTo(LogLevel.ERROR); + Truth.assertThat(protolog.messages.get(2).getLevel()).isEqualTo(LogLevel.WTF); + } + + @Test + public void respectsAllEnabledMode() throws IOException { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(true, List.of()) + .build(); + try { + traceMonitor.start(); + mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4, + LogDataType.BOOLEAN, null, new Object[]{true}); + mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5, + LogDataType.BOOLEAN, null, new Object[]{true}); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(5); + Truth.assertThat(protolog.messages.get(0).getLevel()).isEqualTo(LogLevel.DEBUG); + Truth.assertThat(protolog.messages.get(1).getLevel()).isEqualTo(LogLevel.VERBOSE); + Truth.assertThat(protolog.messages.get(2).getLevel()).isEqualTo(LogLevel.WARN); + Truth.assertThat(protolog.messages.get(3).getLevel()).isEqualTo(LogLevel.ERROR); + Truth.assertThat(protolog.messages.get(4).getLevel()).isEqualTo(LogLevel.WTF); + } + + @Test + public void log_logcatEnabledExternalMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f"); + PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{true, 10000, 30000, "test", 0.000003}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), + eq("test true 10000 % 0x7530 test 3.0E-6")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatEnabledInvalidMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f"); + PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{true, 10000, 0.0001, 0.00002, "test"}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), + eq("UNKNOWN MESSAGE (1234) true 10000 1.0E-4 2.0E-5 test")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatEnabledInlineMessage() { + when(mReader.getViewerString(anyLong())).thenReturn("test %d"); + PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", + new Object[]{5}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), eq("test 5")); + verify(mReader, never()).getViewerString(anyLong()); + } + + @Test + public void log_logcatEnabledNoMessage() { + when(mReader.getViewerString(anyLong())).thenReturn(null); + PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + TestProtoLogGroup.TEST_GROUP.setLogToProto(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, + new Object[]{5}); + + verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( + LogLevel.INFO), eq("UNKNOWN MESSAGE (1234) 5")); + verify(mReader).getViewerString(eq(1234L)); + } + + @Test + public void log_logcatDisabled() { + when(mReader.getViewerString(anyLong())).thenReturn("test %d"); + PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog); + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); + + implSpy.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", + new Object[]{5}); + + verify(implSpy, never()).passToLogcat(any(), any(), any()); + verify(mReader, never()).getViewerString(anyLong()); + } + + @Test + public void log_protoEnabled() throws Exception { + final long messageHash = addMessageToConfig( + ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_INFO, + "My test message :: %s, %d, %o, %x, %f, %e, %g, %b"); + + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog().build(); + long before; + long after; + try { + traceMonitor.start(); + assertTrue(mProtoLog.isProtoEnabled()); + + before = SystemClock.elapsedRealtimeNanos(); + mProtoLog.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash, + 0b1110101001010100, null, + new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true}); + after = SystemClock.elapsedRealtimeNanos(); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(1); + Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos()) + .isAtLeast(before); + Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos()) + .isAtMost(after); + Truth.assertThat(protolog.messages.getFirst().getMessage()) + .isEqualTo("My test message :: test, 2, 4, 6, 0.400000, 5.000000e-01, 0.6, true"); + } + + private long addMessageToConfig(ProtologCommon.ProtoLogLevel logLevel, String message) { + final long messageId = new Random().nextLong(); + mViewerConfigBuilder.addMessages(Protolog.ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(messageId) + .setMessage(message) + .setLevel(logLevel) + .setGroupId(1) + ); + + return messageId; + } + + @Test + public void log_invalidParamsMask() { + final long messageHash = addMessageToConfig( + ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_INFO, + "My test message :: %s, %d, %f, %b"); + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog().build(); + long before; + long after; + try { + traceMonitor.start(); + before = SystemClock.elapsedRealtimeNanos(); + mProtoLog.log( + LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash, + 0b01100100, null, + new Object[]{"test", 1, 0.1, true}); + after = SystemClock.elapsedRealtimeNanos(); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + assertThrows(IllegalStateException.class, reader::readProtoLogTrace); + } + + @Test + public void log_protoDisabled() throws Exception { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(false).build(); + try { + traceMonitor.start(); + mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1, + 0b11, null, new Object[]{true}); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).isEmpty(); + } + + @Test + public void stackTraceTrimmed() throws IOException { + PerfettoTraceMonitor traceMonitor = + PerfettoTraceMonitor.newBuilder().enableProtoLog(true, + List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride( + TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true))) + .build(); + try { + traceMonitor.start(); + + ProtoLogImpl.setSingleInstance(mProtoLog); + ProtoLogImpl.d(TestProtoLogGroup.TEST_GROUP, 1, + 0b11, null, true); + } finally { + traceMonitor.stop(mWriter); + } + + final ResultReader reader = new ResultReader(mWriter.write(), mTraceConfig); + final ProtoLogTrace protolog = reader.readProtoLogTrace(); + + Truth.assertThat(protolog.messages).hasSize(1); + String stacktrace = protolog.messages.getFirst().getStacktrace(); + Truth.assertThat(stacktrace) + .doesNotContain(PerfettoProtoLogImpl.class.getSimpleName() + ".java"); + Truth.assertThat(stacktrace).doesNotContain(DataSource.class.getSimpleName() + ".java"); + Truth.assertThat(stacktrace) + .doesNotContain(ProtoLogImpl.class.getSimpleName() + ".java"); + Truth.assertThat(stacktrace).contains(PerfettoProtoLogImplTest.class.getSimpleName()); + Truth.assertThat(stacktrace).contains("stackTraceTrimmed"); + } + + private enum TestProtoLogGroup implements IProtoLogGroup { + TEST_GROUP(true, true, false, "TEST_TAG"); + + private final boolean mEnabled; + private volatile boolean mLogToProto; + private volatile boolean mLogToLogcat; + private final String mTag; + + /** + * @param enabled set to false to exclude all log statements for this group from + * compilation, + * they will not be available in runtime. + * @param logToProto enable binary logging for the group + * @param logToLogcat enable text logging for the group + * @param tag name of the source of the logged message + */ + TestProtoLogGroup(boolean enabled, boolean logToProto, boolean logToLogcat, String tag) { + this.mEnabled = enabled; + this.mLogToProto = logToProto; + this.mLogToLogcat = logToLogcat; + this.mTag = tag; + } + + @Override + public boolean isEnabled() { + return mEnabled; + } + + @Override + public boolean isLogToProto() { + return mLogToProto; + } + + @Override + public boolean isLogToLogcat() { + return mLogToLogcat; + } + + @Override + public boolean isLogToAny() { + return mLogToLogcat || mLogToProto; + } + + @Override + public String getTag() { + return mTag; + } + + @Override + public void setLogToProto(boolean logToProto) { + this.mLogToProto = logToProto; + } + + @Override + public void setLogToLogcat(boolean logToLogcat) { + this.mLogToLogcat = logToLogcat; + } + + } +} diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java index 7deb8c73d1fc..4267c2c127ae 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java +++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java @@ -16,49 +16,23 @@ package com.android.internal.protolog; -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import static com.android.internal.protolog.ProtoLogImpl.PROTOLOG_VERSION; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import android.content.Context; -import android.os.SystemClock; import android.platform.test.annotations.Presubmit; -import android.util.proto.ProtoInputStream; import androidx.test.filters.SmallTest; +import com.android.internal.protolog.common.IProtoLog; import com.android.internal.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.LogLevel; import org.junit.After; -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.Mockito; -import org.mockito.MockitoAnnotations; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.util.LinkedList; /** * Test class for {@link ProtoLogImpl}. @@ -68,336 +42,78 @@ import java.util.LinkedList; @Presubmit @RunWith(JUnit4.class) public class ProtoLogImplTest { - - private static final byte[] MAGIC_HEADER = new byte[]{ - 0x9, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47 - }; - - private ProtoLogImpl mProtoLog; - private File mFile; - - @Mock - private ProtoLogViewerConfigReader mReader; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - final Context testContext = getInstrumentation().getContext(); - mFile = testContext.getFileStreamPath("tracing_test.dat"); - //noinspection ResultOfMethodCallIgnored - mFile.delete(); - mProtoLog = new ProtoLogImpl(mFile, 1024 * 1024, mReader, 1024); - } - @After public void tearDown() { - if (mFile != null) { - //noinspection ResultOfMethodCallIgnored - mFile.delete(); - } ProtoLogImpl.setSingleInstance(null); } @Test - public void isEnabled_returnsFalseByDefault() { - assertFalse(mProtoLog.isProtoEnabled()); - } - - @Test - public void isEnabled_returnsTrueAfterStart() { - mProtoLog.startProtoLog(mock(PrintWriter.class)); - assertTrue(mProtoLog.isProtoEnabled()); - } - - @Test - public void isEnabled_returnsFalseAfterStop() { - mProtoLog.startProtoLog(mock(PrintWriter.class)); - mProtoLog.stopProtoLog(mock(PrintWriter.class), true); - assertFalse(mProtoLog.isProtoEnabled()); - } - - @Test - public void logFile_startsWithMagicHeader() throws Exception { - mProtoLog.startProtoLog(mock(PrintWriter.class)); - mProtoLog.stopProtoLog(mock(PrintWriter.class), true); - - assertTrue("Log file should exist", mFile.exists()); - - byte[] header = new byte[MAGIC_HEADER.length]; - try (InputStream is = new FileInputStream(mFile)) { - assertEquals(MAGIC_HEADER.length, is.read(header)); - assertArrayEquals(MAGIC_HEADER, header); - } - } - - @Test public void getSingleInstance() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); assertSame(mockedProtoLog, ProtoLogImpl.getSingleInstance()); } @Test public void d_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.d(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.DEBUG), eq( + verify(mockedProtoLog).log(eq(LogLevel.DEBUG), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } @Test public void v_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.v(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.VERBOSE), eq( + verify(mockedProtoLog).log(eq(LogLevel.VERBOSE), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } @Test public void i_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.i(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.INFO), eq( + verify(mockedProtoLog).log(eq(LogLevel.INFO), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } @Test public void w_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.w(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.WARN), eq( + verify(mockedProtoLog).log(eq(LogLevel.WARN), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } @Test public void e_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.e(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq( + verify(mockedProtoLog).log(eq(LogLevel.ERROR), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } @Test public void wtf_logCalled() { - ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); + IProtoLog mockedProtoLog = mock(IProtoLog.class); ProtoLogImpl.setSingleInstance(mockedProtoLog); ProtoLogImpl.wtf(TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d"); - verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.WTF), eq( + verify(mockedProtoLog).log(eq(LogLevel.WTF), eq( TestProtoLogGroup.TEST_GROUP), - eq(1234), eq(4321), eq("test %d"), eq(new Object[]{})); - } - - @Test - public void log_logcatEnabledExternalMessage() { - when(mReader.getViewerString(anyInt())).thenReturn("test %b %d %% 0x%x %s %f"); - ProtoLogImpl implSpy = Mockito.spy(mProtoLog); - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - - implSpy.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, - new Object[]{true, 10000, 30000, "test", 0.000003}); - - verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( - ProtoLogImpl.LogLevel.INFO), - eq("test true 10000 % 0x7530 test 3.0E-6")); - verify(mReader).getViewerString(eq(1234)); - } - - @Test - public void log_logcatEnabledInvalidMessage() { - when(mReader.getViewerString(anyInt())).thenReturn("test %b %d %% %x %s %f"); - ProtoLogImpl implSpy = Mockito.spy(mProtoLog); - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - - implSpy.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, - new Object[]{true, 10000, 0.0001, 0.00002, "test"}); - - verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( - ProtoLogImpl.LogLevel.INFO), - eq("UNKNOWN MESSAGE (1234) true 10000 1.0E-4 2.0E-5 test")); - verify(mReader).getViewerString(eq(1234)); - } - - @Test - public void log_logcatEnabledInlineMessage() { - when(mReader.getViewerString(anyInt())).thenReturn("test %d"); - ProtoLogImpl implSpy = Mockito.spy(mProtoLog); - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - - implSpy.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", - new Object[]{5}); - - verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( - ProtoLogImpl.LogLevel.INFO), eq("test 5")); - verify(mReader, never()).getViewerString(anyInt()); - } - - @Test - public void log_logcatEnabledNoMessage() { - when(mReader.getViewerString(anyInt())).thenReturn(null); - ProtoLogImpl implSpy = Mockito.spy(mProtoLog); - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - - implSpy.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, null, - new Object[]{5}); - - verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( - ProtoLogImpl.LogLevel.INFO), eq("UNKNOWN MESSAGE (1234) 5")); - verify(mReader).getViewerString(eq(1234)); - } - - @Test - public void log_logcatDisabled() { - when(mReader.getViewerString(anyInt())).thenReturn("test %d"); - ProtoLogImpl implSpy = Mockito.spy(mProtoLog); - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - - implSpy.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321, "test %d", - new Object[]{5}); - - verify(implSpy, never()).passToLogcat(any(), any(), any()); - verify(mReader, never()).getViewerString(anyInt()); - } - - private static class ProtoLogData { - Integer mMessageHash = null; - Long mElapsedTime = null; - LinkedList<String> mStrParams = new LinkedList<>(); - LinkedList<Long> mSint64Params = new LinkedList<>(); - LinkedList<Double> mDoubleParams = new LinkedList<>(); - LinkedList<Boolean> mBooleanParams = new LinkedList<>(); - } - - private ProtoLogData readProtoLogSingle(ProtoInputStream ip) throws IOException { - while (ip.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - if (ip.getFieldNumber() == (int) ProtoLogFileProto.VERSION) { - assertEquals(PROTOLOG_VERSION, ip.readString(ProtoLogFileProto.VERSION)); - continue; - } - if (ip.getFieldNumber() != (int) ProtoLogFileProto.LOG) { - continue; - } - long token = ip.start(ProtoLogFileProto.LOG); - ProtoLogData data = new ProtoLogData(); - while (ip.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (ip.getFieldNumber()) { - case (int) ProtoLogMessage.MESSAGE_HASH: { - data.mMessageHash = ip.readInt(ProtoLogMessage.MESSAGE_HASH); - break; - } - case (int) ProtoLogMessage.ELAPSED_REALTIME_NANOS: { - data.mElapsedTime = ip.readLong(ProtoLogMessage.ELAPSED_REALTIME_NANOS); - break; - } - case (int) ProtoLogMessage.STR_PARAMS: { - data.mStrParams.add(ip.readString(ProtoLogMessage.STR_PARAMS)); - break; - } - case (int) ProtoLogMessage.SINT64_PARAMS: { - data.mSint64Params.add(ip.readLong(ProtoLogMessage.SINT64_PARAMS)); - break; - } - case (int) ProtoLogMessage.DOUBLE_PARAMS: { - data.mDoubleParams.add(ip.readDouble(ProtoLogMessage.DOUBLE_PARAMS)); - break; - } - case (int) ProtoLogMessage.BOOLEAN_PARAMS: { - data.mBooleanParams.add(ip.readBoolean(ProtoLogMessage.BOOLEAN_PARAMS)); - break; - } - } - } - ip.end(token); - return data; - } - return null; - } - - @Test - public void log_protoEnabled() throws Exception { - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); - TestProtoLogGroup.TEST_GROUP.setLogToProto(true); - mProtoLog.startProtoLog(mock(PrintWriter.class)); - long before = SystemClock.elapsedRealtimeNanos(); - mProtoLog.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, - 0b1110101001010100, null, - new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true}); - long after = SystemClock.elapsedRealtimeNanos(); - mProtoLog.stopProtoLog(mock(PrintWriter.class), true); - try (InputStream is = new FileInputStream(mFile)) { - ProtoInputStream ip = new ProtoInputStream(is); - ProtoLogData data = readProtoLogSingle(ip); - assertNotNull(data); - assertEquals(1234, data.mMessageHash.longValue()); - assertTrue(before <= data.mElapsedTime && data.mElapsedTime <= after); - assertArrayEquals(new String[]{"test"}, data.mStrParams.toArray()); - assertArrayEquals(new Long[]{1L, 2L, 3L}, data.mSint64Params.toArray()); - assertArrayEquals(new Double[]{0.4, 0.5, 0.6}, data.mDoubleParams.toArray()); - assertArrayEquals(new Boolean[]{true}, data.mBooleanParams.toArray()); - } - } - - @Test - public void log_invalidParamsMask() throws Exception { - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); - TestProtoLogGroup.TEST_GROUP.setLogToProto(true); - mProtoLog.startProtoLog(mock(PrintWriter.class)); - long before = SystemClock.elapsedRealtimeNanos(); - mProtoLog.log( - ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, - 0b01100100, null, - new Object[]{"test", 1, 0.1, true}); - long after = SystemClock.elapsedRealtimeNanos(); - mProtoLog.stopProtoLog(mock(PrintWriter.class), true); - try (InputStream is = new FileInputStream(mFile)) { - ProtoInputStream ip = new ProtoInputStream(is); - ProtoLogData data = readProtoLogSingle(ip); - assertNotNull(data); - assertEquals(1234, data.mMessageHash.longValue()); - assertTrue(before <= data.mElapsedTime && data.mElapsedTime <= after); - assertArrayEquals(new String[]{"test", "(INVALID PARAMS_MASK) true"}, - data.mStrParams.toArray()); - assertArrayEquals(new Long[]{1L}, data.mSint64Params.toArray()); - assertArrayEquals(new Double[]{0.1}, data.mDoubleParams.toArray()); - assertArrayEquals(new Boolean[]{}, data.mBooleanParams.toArray()); - } - } - - @Test - public void log_protoDisabled() throws Exception { - TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false); - TestProtoLogGroup.TEST_GROUP.setLogToProto(false); - mProtoLog.startProtoLog(mock(PrintWriter.class)); - mProtoLog.log(ProtoLogImpl.LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, - 0b11, null, new Object[]{true}); - mProtoLog.stopProtoLog(mock(PrintWriter.class), true); - try (InputStream is = new FileInputStream(mFile)) { - ProtoInputStream ip = new ProtoInputStream(is); - ProtoLogData data = readProtoLogSingle(ip); - assertNull(data); - } + eq(1234L), eq(4321), eq("test %d"), eq(new Object[]{})); } private enum TestProtoLogGroup implements IProtoLogGroup { diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java index ae5021638745..dbd85d38b7f2 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java +++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java @@ -72,8 +72,8 @@ public class ProtoLogViewerConfigReaderTest { + "}\n"; - private ProtoLogViewerConfigReader - mConfig = new ProtoLogViewerConfigReader(); + private LegacyProtoLogViewerConfigReader + mConfig = new LegacyProtoLogViewerConfigReader(); private File mTestViewerConfig; @Before @@ -98,7 +98,7 @@ public class ProtoLogViewerConfigReaderTest { @Test public void loadViewerConfig() { - mConfig.loadViewerConfig(null, mTestViewerConfig.getAbsolutePath()); + mConfig.loadViewerConfig(msg -> {}, mTestViewerConfig.getAbsolutePath()); assertEquals("Test completed successfully: %b", mConfig.getViewerString(70933285)); assertEquals("Test 2", mConfig.getViewerString(1352021864)); assertEquals("Window %s is already added", mConfig.getViewerString(409412266)); @@ -107,7 +107,7 @@ public class ProtoLogViewerConfigReaderTest { @Test public void loadViewerConfig_invalidFile() { - mConfig.loadViewerConfig(null, "/tmp/unknown/file/does/not/exist"); + mConfig.loadViewerConfig(msg -> {}, "/tmp/unknown/file/does/not/exist"); // No exception is thrown. assertNull(mConfig.getViewerString(1)); } diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt index 97398dc4e334..c2583475e484 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt @@ -15,7 +15,7 @@ */ package com.android.test -import android.tools.common.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject import junit.framework.Assert.assertEquals import junit.framework.Assert.assertTrue import org.junit.Test diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt index 0cc18d657cf5..0e70df4cb113 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt @@ -16,7 +16,7 @@ package com.android.test import android.graphics.Point -import android.tools.common.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode import com.android.test.SurfaceViewBufferTestBase.Companion.Transform import junit.framework.Assert.assertEquals diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt index 6f4d11c3aa1b..85024749746a 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt @@ -19,7 +19,7 @@ import android.graphics.Color import android.graphics.Point import android.graphics.Rect import android.os.SystemClock -import android.tools.common.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode import com.android.test.SurfaceViewBufferTestBase.Companion.Transform import junit.framework.Assert.assertEquals diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt index 1de965ebcb36..ad8b35ea8aa3 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt @@ -16,7 +16,7 @@ package com.android.test import android.graphics.Point -import android.tools.common.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject import com.android.test.SurfaceViewBufferTestBase.Companion.Transform import junit.framework.Assert.assertEquals import org.junit.Assert diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt index 4c5224a8b151..b2ceb40b5e2f 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt @@ -17,7 +17,7 @@ package com.android.test import android.graphics.Color import android.graphics.Rect -import android.tools.common.flicker.subject.layers.LayersTraceSubject +import android.tools.flicker.subject.layers.LayersTraceSubject import junit.framework.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt index b03b7335b08b..6e777960a475 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt @@ -21,9 +21,9 @@ import android.graphics.Color import android.graphics.Rect import android.util.Log import androidx.test.ext.junit.rules.ActivityScenarioRule -import android.tools.common.traces.surfaceflinger.LayersTrace -import android.tools.device.traces.monitors.withSFTracing -import android.tools.device.traces.monitors.PerfettoTraceMonitor +import android.tools.traces.surfaceflinger.LayersTrace +import android.tools.traces.monitors.withSFTracing +import android.tools.traces.monitors.PerfettoTraceMonitor import junit.framework.Assert import org.junit.After import org.junit.Before diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt index 1770e32a5145..e0b180955419 100644 --- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt +++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt @@ -18,8 +18,8 @@ package com.android.test import android.app.Instrumentation import android.graphics.Point import android.provider.Settings -import android.tools.common.datatypes.Size -import android.tools.common.flicker.subject.layers.LayerSubject +import android.tools.datatypes.Size +import android.tools.flicker.subject.layers.LayerSubject import androidx.test.InstrumentationRegistry import org.junit.After import org.junit.Before diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt index 2c7905d552f1..e76a399cc159 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt @@ -20,9 +20,9 @@ import android.graphics.Rect import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.platform.app.InstrumentationRegistry import androidx.test.runner.AndroidJUnit4 -import android.tools.common.datatypes.Size -import android.tools.common.flicker.subject.layers.LayersTraceSubject -import android.tools.device.traces.monitors.withSFTracing +import android.tools.datatypes.Size +import android.tools.flicker.subject.layers.LayersTraceSubject +import android.tools.traces.monitors.withSFTracing import org.junit.After import org.junit.Before import org.junit.FixMethodOrder diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING index eca258c5a74d..b5d5b5fb6d92 100644 --- a/tools/hoststubgen/TEST_MAPPING +++ b/tools/hoststubgen/TEST_MAPPING @@ -1,6 +1,7 @@ { "presubmit": [ - { "name": "tiny-framework-dump-test" }, + // TODO(b/326897452): Reenable after JDK 21 switch. + // { "name": "tiny-framework-dump-test" }, { "name": "hoststubgentest" }, { "name": "hoststubgen-invoke-test" } ], diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp index 46745e995f64..8fbc3e8a78db 100644 --- a/tools/protologtool/Android.bp +++ b/tools/protologtool/Android.bp @@ -11,12 +11,13 @@ java_library_host { name: "protologtool-lib", srcs: [ "src/com/android/protolog/tool/**/*.kt", - ":protolog-common-no-android-src", + ":protolog-common-src", ], static_libs: [ "javaparser", "platformprotos", "jsonlib", + "perfetto_trace-full", ], } @@ -42,5 +43,6 @@ java_test_host { "junit", "mockito", "objenesis", + "truth", ], } diff --git a/tools/protologtool/README.md b/tools/protologtool/README.md index ba639570f88c..24a4861c63a2 100644 --- a/tools/protologtool/README.md +++ b/tools/protologtool/README.md @@ -8,11 +8,13 @@ ProtoLogTool incorporates three different modes of operation: ### Code transformation -Command: `protologtool transform-protolog-calls - --protolog-class <protolog class name> - --protolog-impl-class <protolog implementation class name> +Command: `protologtool transform-protolog-calls + --protolog-class <protolog class name> --loggroups-class <protolog groups class name> --loggroups-jar <config jar path> + --viewer-config-file-path <protobuf viewer config file path> + --legacy-viewer-config-file-path <legacy json.gz viewer config file path> + --legacy-output-file-path <.winscope file path to write the legacy trace to> --output-srcjar <output.srcjar> [<input.java>]` @@ -44,10 +46,11 @@ jar file (config.jar). ### Viewer config generation Command: `generate-viewer-config - --protolog-class <protolog class name> + --protolog-class <protolog class name> --loggroups-class <protolog groups class name> --loggroups-jar <config jar path> - --viewer-conf <viewer.json> + --viewer-config-type <proto|json> + --viewer-config <viewer.json> [<input.java>]` This command is similar in it's syntax to the previous one, only instead of creating a processed source jar @@ -74,7 +77,7 @@ it writes a viewer configuration file with following schema: ### Binary log viewing -Command: `read-log --viewer-conf <viewer.json> <wm_log.pb>` +Command: `read-log --viewer-config <viewer.json> <wm_log.pb>` Reads the binary ProtoLog log file and outputs a human-readable LogCat-like text log. diff --git a/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt b/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt index 451e514b8b33..3d1dec2e0724 100644 --- a/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt +++ b/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt @@ -16,20 +16,27 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.ImportDeclaration import com.github.javaparser.ast.expr.BinaryExpr import com.github.javaparser.ast.expr.Expression import com.github.javaparser.ast.expr.StringLiteralExpr +import java.util.UUID object CodeUtils { /** * Returns a stable hash of a string. * We reimplement String::hashCode() for readability reasons. */ - fun hash(position: String, messageString: String, logLevel: LogLevel, logGroup: LogGroup): Int { - return (position + messageString + logLevel.name + logGroup.name) - .map { c -> c.code }.reduce { h, c -> h * 31 + c } + fun hash( + position: String, + messageString: String, + logLevel: LogLevel, + logGroup: LogGroup + ): Long { + val fullStringIdentifier = position + messageString + logLevel.name + logGroup.name + return UUID.nameUUIDFromBytes(fullStringIdentifier.toByteArray()).mostSignificantBits } fun checkWildcardStaticImported(code: CompilationUnit, className: String, fileName: String) { diff --git a/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt b/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt index bfbbf7a32c22..a3591558bd67 100644 --- a/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt +++ b/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt @@ -26,32 +26,35 @@ class CommandOptions(args: Array<String>) { private val commands = setOf(TRANSFORM_CALLS_CMD, GENERATE_CONFIG_CMD, READ_LOG_CMD) private const val PROTOLOG_CLASS_PARAM = "--protolog-class" - private const val PROTOLOGIMPL_CLASS_PARAM = "--protolog-impl-class" - private const val PROTOLOGCACHE_CLASS_PARAM = "--protolog-cache-class" private const val PROTOLOGGROUP_CLASS_PARAM = "--loggroups-class" private const val PROTOLOGGROUP_JAR_PARAM = "--loggroups-jar" - private const val VIEWER_CONFIG_JSON_PARAM = "--viewer-conf" + private const val VIEWER_CONFIG_PARAM = "--viewer-config" + private const val VIEWER_CONFIG_TYPE_PARAM = "--viewer-config-type" private const val OUTPUT_SOURCE_JAR_PARAM = "--output-srcjar" - private val parameters = setOf(PROTOLOG_CLASS_PARAM, PROTOLOGIMPL_CLASS_PARAM, - PROTOLOGCACHE_CLASS_PARAM, PROTOLOGGROUP_CLASS_PARAM, PROTOLOGGROUP_JAR_PARAM, - VIEWER_CONFIG_JSON_PARAM, OUTPUT_SOURCE_JAR_PARAM) + private const val VIEWER_CONFIG_FILE_PATH_PARAM = "--viewer-config-file-path" + // TODO(b/324128613): Remove these legacy options once we fully flip the Perfetto protolog flag + private const val LEGACY_VIEWER_CONFIG_FILE_PATH_PARAM = "--legacy-viewer-config-file-path" + private const val LEGACY_OUTPUT_FILE_PATH = "--legacy-output-file-path" + private val parameters = setOf(PROTOLOG_CLASS_PARAM, PROTOLOGGROUP_CLASS_PARAM, + PROTOLOGGROUP_JAR_PARAM, VIEWER_CONFIG_PARAM, VIEWER_CONFIG_TYPE_PARAM, + OUTPUT_SOURCE_JAR_PARAM, VIEWER_CONFIG_FILE_PATH_PARAM, + LEGACY_VIEWER_CONFIG_FILE_PATH_PARAM, LEGACY_OUTPUT_FILE_PATH) val USAGE = """ Usage: ${Constants.NAME} <command> [<args>] Available commands: - $TRANSFORM_CALLS_CMD $PROTOLOG_CLASS_PARAM <class name> $PROTOLOGIMPL_CLASS_PARAM - <class name> $PROTOLOGCACHE_CLASS_PARAM - <class name> $PROTOLOGGROUP_CLASS_PARAM <class name> $PROTOLOGGROUP_JAR_PARAM - <config.jar> $OUTPUT_SOURCE_JAR_PARAM <output.srcjar> [<input.java>] + $TRANSFORM_CALLS_CMD $PROTOLOG_CLASS_PARAM <class name> + $PROTOLOGGROUP_CLASS_PARAM <class name> $PROTOLOGGROUP_JAR_PARAM <config.jar> + $OUTPUT_SOURCE_JAR_PARAM <output.srcjar> [<input.java>] - processes java files replacing stub calls with logging code. - $GENERATE_CONFIG_CMD $PROTOLOG_CLASS_PARAM <class name> $PROTOLOGGROUP_CLASS_PARAM - <class name> $PROTOLOGGROUP_JAR_PARAM <config.jar> $VIEWER_CONFIG_JSON_PARAM - <viewer.json> [<input.java>] + $GENERATE_CONFIG_CMD $PROTOLOG_CLASS_PARAM <class name> + $PROTOLOGGROUP_CLASS_PARAM <class name> $PROTOLOGGROUP_JAR_PARAM <config.jar> + $VIEWER_CONFIG_PARAM <viewer.json|viewer.pb> [<input.java>] - creates viewer config file from given java files. - $READ_LOG_CMD $VIEWER_CONFIG_JSON_PARAM <viewer.json> <wm_log.pb> + $READ_LOG_CMD $VIEWER_CONFIG_PARAM <viewer.json|viewer.pb> <wm_log.pb> - translates a binary log to a readable format. """.trimIndent() @@ -69,6 +72,13 @@ class CommandOptions(args: Array<String>) { return params.getValue(paramName) } + private fun getOptionalParam(paramName: String, params: Map<String, String>): String? { + if (!params.containsKey(paramName)) { + return null + } + return params.getValue(paramName) + } + private fun validateNotSpecified(paramName: String, params: Map<String, String>): String { if (params.containsKey(paramName)) { throw InvalidCommandException("Unsupported param $paramName") @@ -90,9 +100,43 @@ class CommandOptions(args: Array<String>) { return name } - private fun validateJSONName(name: String): String { - if (!name.endsWith(".json")) { - throw InvalidCommandException("Json file required, got $name instead") + private fun validateViewerConfigFilePath(name: String): String { + if (!name.endsWith(".pb")) { + throw InvalidCommandException("Proto file (ending with .pb) required, " + + "got $name instead") + } + return name + } + + private fun validateLegacyViewerConfigFilePath(name: String): String { + if (!name.endsWith(".json.gz")) { + throw InvalidCommandException("GZiped Json file (ending with .json.gz) required, " + + "got $name instead") + } + return name + } + + private fun validateOutputFilePath(name: String): String { + if (!name.endsWith(".winscope")) { + throw InvalidCommandException("Winscope file (ending with .winscope) required, " + + "got $name instead") + } + return name + } + + private fun validateConfigFileName(name: String): String { + if (!name.endsWith(".json") && !name.endsWith(".pb")) { + throw InvalidCommandException("Json file (ending with .json) or proto file " + + "(ending with .pb) required, got $name instead") + } + return name + } + + private fun validateConfigType(name: String): String { + val validType = listOf("json", "proto") + if (!validType.contains(name)) { + throw InvalidCommandException("Unexpected config file type. " + + "Expected on of [${validType.joinToString()}], but got $name") } return name } @@ -102,8 +146,8 @@ class CommandOptions(args: Array<String>) { throw InvalidCommandException("No java source input files") } list.forEach { name -> - if (!name.endsWith(".java")) { - throw InvalidCommandException("Not a java source file $name") + if (!name.endsWith(".java") && !name.endsWith(".kt")) { + throw InvalidCommandException("Not a java or kotlin source file $name") } } return list @@ -122,12 +166,14 @@ class CommandOptions(args: Array<String>) { val protoLogClassNameArg: String val protoLogGroupsClassNameArg: String - val protoLogImplClassNameArg: String - val protoLogCacheClassNameArg: String val protoLogGroupsJarArg: String - val viewerConfigJsonArg: String + val viewerConfigFileNameArg: String + val viewerConfigTypeArg: String val outputSourceJarArg: String val logProtofileArg: String + val viewerConfigFilePathArg: String + val legacyViewerConfigFilePathArg: String? + val legacyOutputFilePath: String? val javaSourceArgs: List<String> val command: String @@ -169,38 +215,55 @@ class CommandOptions(args: Array<String>) { when (command) { TRANSFORM_CALLS_CMD -> { protoLogClassNameArg = validateClassName(getParam(PROTOLOG_CLASS_PARAM, params)) - protoLogGroupsClassNameArg = validateClassName(getParam(PROTOLOGGROUP_CLASS_PARAM, - params)) - protoLogImplClassNameArg = validateClassName(getParam(PROTOLOGIMPL_CLASS_PARAM, - params)) - protoLogCacheClassNameArg = validateClassName(getParam(PROTOLOGCACHE_CLASS_PARAM, - params)) + protoLogGroupsClassNameArg = + validateClassName(getParam(PROTOLOGGROUP_CLASS_PARAM, params)) protoLogGroupsJarArg = validateJarName(getParam(PROTOLOGGROUP_JAR_PARAM, params)) - viewerConfigJsonArg = validateNotSpecified(VIEWER_CONFIG_JSON_PARAM, params) + viewerConfigFileNameArg = validateNotSpecified(VIEWER_CONFIG_PARAM, params) + viewerConfigTypeArg = validateNotSpecified(VIEWER_CONFIG_TYPE_PARAM, params) outputSourceJarArg = validateSrcJarName(getParam(OUTPUT_SOURCE_JAR_PARAM, params)) + viewerConfigFilePathArg = validateViewerConfigFilePath( + getParam(VIEWER_CONFIG_FILE_PATH_PARAM, params)) + legacyViewerConfigFilePathArg = + getOptionalParam(LEGACY_VIEWER_CONFIG_FILE_PATH_PARAM, params)?.let { + validateLegacyViewerConfigFilePath(it) + } + legacyOutputFilePath = + getOptionalParam(LEGACY_OUTPUT_FILE_PATH, params)?.let { + validateOutputFilePath(it) + } javaSourceArgs = validateJavaInputList(inputFiles) logProtofileArg = "" } GENERATE_CONFIG_CMD -> { protoLogClassNameArg = validateClassName(getParam(PROTOLOG_CLASS_PARAM, params)) - protoLogGroupsClassNameArg = validateClassName(getParam(PROTOLOGGROUP_CLASS_PARAM, - params)) - protoLogImplClassNameArg = validateNotSpecified(PROTOLOGIMPL_CLASS_PARAM, params) - protoLogCacheClassNameArg = validateNotSpecified(PROTOLOGCACHE_CLASS_PARAM, params) + protoLogGroupsClassNameArg = + validateClassName(getParam(PROTOLOGGROUP_CLASS_PARAM, params)) protoLogGroupsJarArg = validateJarName(getParam(PROTOLOGGROUP_JAR_PARAM, params)) - viewerConfigJsonArg = validateJSONName(getParam(VIEWER_CONFIG_JSON_PARAM, params)) + viewerConfigFileNameArg = + validateConfigFileName(getParam(VIEWER_CONFIG_PARAM, params)) + viewerConfigTypeArg = validateConfigType(getParam(VIEWER_CONFIG_TYPE_PARAM, params)) outputSourceJarArg = validateNotSpecified(OUTPUT_SOURCE_JAR_PARAM, params) + viewerConfigFilePathArg = + validateNotSpecified(VIEWER_CONFIG_FILE_PATH_PARAM, params) + legacyViewerConfigFilePathArg = + validateNotSpecified(LEGACY_VIEWER_CONFIG_FILE_PATH_PARAM, params) + legacyOutputFilePath = validateNotSpecified(LEGACY_OUTPUT_FILE_PATH, params) javaSourceArgs = validateJavaInputList(inputFiles) logProtofileArg = "" } READ_LOG_CMD -> { protoLogClassNameArg = validateNotSpecified(PROTOLOG_CLASS_PARAM, params) protoLogGroupsClassNameArg = validateNotSpecified(PROTOLOGGROUP_CLASS_PARAM, params) - protoLogImplClassNameArg = validateNotSpecified(PROTOLOGIMPL_CLASS_PARAM, params) - protoLogCacheClassNameArg = validateNotSpecified(PROTOLOGCACHE_CLASS_PARAM, params) protoLogGroupsJarArg = validateNotSpecified(PROTOLOGGROUP_JAR_PARAM, params) - viewerConfigJsonArg = validateJSONName(getParam(VIEWER_CONFIG_JSON_PARAM, params)) + viewerConfigFileNameArg = + validateConfigFileName(getParam(VIEWER_CONFIG_PARAM, params)) + viewerConfigTypeArg = validateNotSpecified(VIEWER_CONFIG_TYPE_PARAM, params) outputSourceJarArg = validateNotSpecified(OUTPUT_SOURCE_JAR_PARAM, params) + viewerConfigFilePathArg = + validateNotSpecified(VIEWER_CONFIG_FILE_PATH_PARAM, params) + legacyViewerConfigFilePathArg = + validateNotSpecified(LEGACY_VIEWER_CONFIG_FILE_PATH_PARAM, params) + legacyOutputFilePath = validateNotSpecified(LEGACY_OUTPUT_FILE_PATH, params) javaSourceArgs = listOf() logProtofileArg = validateLogInputList(inputFiles) } diff --git a/tools/protologtool/src/com/android/protolog/tool/LogLevel.kt b/tools/protologtool/src/com/android/protolog/tool/LogLevel.kt deleted file mode 100644 index e88f0f8231bd..000000000000 --- a/tools/protologtool/src/com/android/protolog/tool/LogLevel.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.protolog.tool - -import com.github.javaparser.ast.Node - -enum class LogLevel { - DEBUG, VERBOSE, INFO, WARN, ERROR, WTF; - - companion object { - fun getLevelForMethodName(name: String, node: Node, context: ParsingContext): LogLevel { - return when (name) { - "d" -> DEBUG - "v" -> VERBOSE - "i" -> INFO - "w" -> WARN - "e" -> ERROR - "wtf" -> WTF - else -> - throw InvalidProtoLogCallException("Unknown log level $name in $node", context) - } - } - } -} diff --git a/tools/protologtool/src/com/android/protolog/tool/MethodCallVisitor.kt b/tools/protologtool/src/com/android/protolog/tool/MethodCallVisitor.kt new file mode 100644 index 000000000000..fda6351361bf --- /dev/null +++ b/tools/protologtool/src/com/android/protolog/tool/MethodCallVisitor.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.protolog.tool + +import com.github.javaparser.ast.expr.MethodCallExpr + +interface MethodCallVisitor { + fun processCall(call: MethodCallExpr) +} diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessor.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessor.kt index 2181cf680f6c..47724b7a9e1d 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessor.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessor.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,97 +17,12 @@ package com.android.protolog.tool import com.github.javaparser.ast.CompilationUnit -import com.github.javaparser.ast.expr.Expression -import com.github.javaparser.ast.expr.FieldAccessExpr -import com.github.javaparser.ast.expr.MethodCallExpr -import com.github.javaparser.ast.expr.NameExpr -/** - * Helper class for visiting all ProtoLog calls. - * For every valid call in the given {@code CompilationUnit} a {@code ProtoLogCallVisitor} callback - * is executed. - */ -open class ProtoLogCallProcessor( - private val protoLogClassName: String, - private val protoLogGroupClassName: String, - private val groupMap: Map<String, LogGroup> -) { - private val protoLogSimpleClassName = protoLogClassName.substringAfterLast('.') - private val protoLogGroupSimpleClassName = protoLogGroupClassName.substringAfterLast('.') - - private fun getLogGroupName( - expr: Expression, - isClassImported: Boolean, - staticImports: Set<String>, +interface ProtoLogCallProcessor { + fun process( + code: CompilationUnit, + logCallVisitor: ProtoLogCallVisitor?, + otherCallVisitor: MethodCallVisitor?, fileName: String - ): String { - val context = ParsingContext(fileName, expr) - return when (expr) { - is NameExpr -> when { - expr.nameAsString in staticImports -> expr.nameAsString - else -> - throw InvalidProtoLogCallException("Unknown/not imported ProtoLogGroup: $expr", - context) - } - is FieldAccessExpr -> when { - expr.scope.toString() == protoLogGroupClassName - || isClassImported && - expr.scope.toString() == protoLogGroupSimpleClassName -> expr.nameAsString - else -> - throw InvalidProtoLogCallException("Unknown/not imported ProtoLogGroup: $expr", - context) - } - else -> throw InvalidProtoLogCallException("Invalid group argument " + - "- must be ProtoLogGroup enum member reference: $expr", context) - } - } - - private fun isProtoCall( - call: MethodCallExpr, - isLogClassImported: Boolean, - staticLogImports: Collection<String> - ): Boolean { - return call.scope.isPresent && call.scope.get().toString() == protoLogClassName || - isLogClassImported && call.scope.isPresent && - call.scope.get().toString() == protoLogSimpleClassName || - !call.scope.isPresent && staticLogImports.contains(call.name.toString()) - } - - open fun process(code: CompilationUnit, callVisitor: ProtoLogCallVisitor?, fileName: String): - CompilationUnit { - CodeUtils.checkWildcardStaticImported(code, protoLogClassName, fileName) - CodeUtils.checkWildcardStaticImported(code, protoLogGroupClassName, fileName) - - val isLogClassImported = CodeUtils.isClassImportedOrSamePackage(code, protoLogClassName) - val staticLogImports = CodeUtils.staticallyImportedMethods(code, protoLogClassName) - val isGroupClassImported = CodeUtils.isClassImportedOrSamePackage(code, - protoLogGroupClassName) - val staticGroupImports = CodeUtils.staticallyImportedMethods(code, protoLogGroupClassName) - - code.findAll(MethodCallExpr::class.java) - .filter { call -> - isProtoCall(call, isLogClassImported, staticLogImports) - }.forEach { call -> - val context = ParsingContext(fileName, call) - if (call.arguments.size < 2) { - throw InvalidProtoLogCallException("Method signature does not match " + - "any ProtoLog method: $call", context) - } - - val messageString = CodeUtils.concatMultilineString(call.getArgument(1), - context) - val groupNameArg = call.getArgument(0) - val groupName = - getLogGroupName(groupNameArg, isGroupClassImported, - staticGroupImports, fileName) - if (groupName !in groupMap) { - throw InvalidProtoLogCallException("Unknown group argument " + - "- not a ProtoLogGroup enum member: $call", context) - } - - callVisitor?.processCall(call, messageString, LogLevel.getLevelForMethodName( - call.name.toString(), call, context), groupMap.getValue(groupName)) - } - return code - } + ): CompilationUnit } diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt new file mode 100644 index 000000000000..1087ae6ee41d --- /dev/null +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.protolog.tool + +import com.android.internal.protolog.common.LogLevel +import com.github.javaparser.ast.CompilationUnit +import com.github.javaparser.ast.expr.Expression +import com.github.javaparser.ast.expr.FieldAccessExpr +import com.github.javaparser.ast.expr.MethodCallExpr +import com.github.javaparser.ast.expr.NameExpr + +/** + * Helper class for visiting all ProtoLog calls. + * For every valid call in the given {@code CompilationUnit} a {@code ProtoLogCallVisitor} callback + * is executed. + */ +class ProtoLogCallProcessorImpl( + private val protoLogClassName: String, + private val protoLogGroupClassName: String, + private val groupMap: Map<String, LogGroup> +) : ProtoLogCallProcessor { + private val protoLogSimpleClassName = protoLogClassName.substringAfterLast('.') + private val protoLogGroupSimpleClassName = protoLogGroupClassName.substringAfterLast('.') + + private fun getLogGroupName( + expr: Expression, + isClassImported: Boolean, + staticImports: Set<String>, + fileName: String + ): String { + val context = ParsingContext(fileName, expr) + return when (expr) { + is NameExpr -> when { + expr.nameAsString in staticImports -> expr.nameAsString + else -> + throw InvalidProtoLogCallException("Unknown/not imported ProtoLogGroup: $expr", + context) + } + is FieldAccessExpr -> when { + expr.scope.toString() == protoLogGroupClassName || isClassImported && + expr.scope.toString() == protoLogGroupSimpleClassName -> expr.nameAsString + else -> + throw InvalidProtoLogCallException("Unknown/not imported ProtoLogGroup: $expr", + context) + } + else -> throw InvalidProtoLogCallException("Invalid group argument " + + "- must be ProtoLogGroup enum member reference: $expr", context) + } + } + + private fun isProtoCall( + call: MethodCallExpr, + isLogClassImported: Boolean, + staticLogImports: Collection<String> + ): Boolean { + return call.scope.isPresent && call.scope.get().toString() == protoLogClassName || + isLogClassImported && call.scope.isPresent && + call.scope.get().toString() == protoLogSimpleClassName || + !call.scope.isPresent && staticLogImports.contains(call.name.toString()) + } + + fun process(code: CompilationUnit, logCallVisitor: ProtoLogCallVisitor?, fileName: String): + CompilationUnit { + return process(code, logCallVisitor, null, fileName) + } + + override fun process( + code: CompilationUnit, + logCallVisitor: ProtoLogCallVisitor?, + otherCallVisitor: MethodCallVisitor?, + fileName: String + ): CompilationUnit { + CodeUtils.checkWildcardStaticImported(code, protoLogClassName, fileName) + CodeUtils.checkWildcardStaticImported(code, protoLogGroupClassName, fileName) + + val isLogClassImported = CodeUtils.isClassImportedOrSamePackage(code, protoLogClassName) + val staticLogImports = CodeUtils.staticallyImportedMethods(code, protoLogClassName) + val isGroupClassImported = CodeUtils.isClassImportedOrSamePackage(code, + protoLogGroupClassName) + val staticGroupImports = CodeUtils.staticallyImportedMethods(code, protoLogGroupClassName) + + code.findAll(MethodCallExpr::class.java) + .filter { call -> + isProtoCall(call, isLogClassImported, staticLogImports) + }.forEach { call -> + val context = ParsingContext(fileName, call) + + val logMethods = LogLevel.entries.map { it.shortCode } + if (logMethods.contains(call.name.id)) { + // Process a log call + if (call.arguments.size < 2) { + throw InvalidProtoLogCallException("Method signature does not match " + + "any ProtoLog method: $call", context) + } + + val messageString = CodeUtils.concatMultilineString(call.getArgument(1), + context) + val groupNameArg = call.getArgument(0) + val groupName = + getLogGroupName(groupNameArg, isGroupClassImported, + staticGroupImports, fileName) + if (groupName !in groupMap) { + throw InvalidProtoLogCallException("Unknown group argument " + + "- not a ProtoLogGroup enum member: $call", context) + } + + logCallVisitor?.processCall(call, messageString, getLevelForMethodName( + call.name.toString(), call, context), groupMap.getValue(groupName)) + } else { + // Process non-log message calls + otherCallVisitor?.processCall(call) + } + } + return code + } + + private fun getLevelForMethodName( + name: String, + node: MethodCallExpr, + context: ParsingContext + ): LogLevel = when (name) { + "d" -> LogLevel.DEBUG + "v" -> LogLevel.VERBOSE + "i" -> LogLevel.INFO + "w" -> LogLevel.WARN + "e" -> LogLevel.ERROR + "wtf" -> LogLevel.WTF + else -> + throw InvalidProtoLogCallException("Unknown log level $name in $node", context) + } +} diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt index aa58b69d61cb..8cd927a7cd0e 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt @@ -16,6 +16,7 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.ast.expr.MethodCallExpr interface ProtoLogCallVisitor { diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt index ce856cd49614..1381847c258f 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt @@ -16,13 +16,22 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel +import com.android.internal.protolog.common.ProtoLog +import com.android.internal.protolog.common.ProtoLogToolInjected import com.android.protolog.tool.CommandOptions.Companion.USAGE import com.github.javaparser.ParseProblemException import com.github.javaparser.ParserConfiguration import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.CompilationUnit +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration +import com.github.javaparser.ast.expr.MethodCallExpr +import com.github.javaparser.ast.expr.NullLiteralExpr +import com.github.javaparser.ast.expr.SimpleName +import com.github.javaparser.ast.expr.StringLiteralExpr import java.io.File import java.io.FileInputStream +import java.io.FileNotFoundException import java.io.FileOutputStream import java.io.OutputStream import java.time.LocalDateTime @@ -30,9 +39,21 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.jar.JarOutputStream import java.util.zip.ZipEntry +import kotlin.math.abs +import kotlin.random.Random import kotlin.system.exitProcess object ProtoLogTool { + const val PROTOLOG_IMPL_SRC_PATH = + "frameworks/base/core/java/com/android/internal/protolog/ProtoLogImpl.java" + + data class LogCall( + val messageString: String, + val logLevel: LogLevel, + val logGroup: LogGroup, + val position: String + ) + private fun showHelpAndExit() { println(USAGE) exitProcess(-1) @@ -51,26 +72,40 @@ object ProtoLogTool { } private fun processClasses(command: CommandOptions) { + val generationHash = abs(Random.nextInt()) + // Need to generate a new impl class to inject static constants into the class. + val generatedProtoLogImplClass = + "com.android.internal.protolog.ProtoLogImpl_$generationHash" + val groups = injector.readLogGroups( command.protoLogGroupsJarArg, command.protoLogGroupsClassNameArg) val out = injector.fileOutputStream(command.outputSourceJarArg) val outJar = JarOutputStream(out) - val processor = ProtoLogCallProcessor(command.protoLogClassNameArg, - command.protoLogGroupsClassNameArg, groups) + val processor = ProtoLogCallProcessorImpl( + command.protoLogClassNameArg, + command.protoLogGroupsClassNameArg, + groups) + + val protologImplName = generatedProtoLogImplClass.split(".").last() + val protologImplPath = "gen/${generatedProtoLogImplClass.split(".") + .joinToString("/")}.java" + outJar.putNextEntry(zipEntry(protologImplPath)) + + outJar.write(generateProtoLogImpl(protologImplName, command.viewerConfigFilePathArg, + command.legacyViewerConfigFilePathArg, command.legacyOutputFilePath).toByteArray()) val executor = newThreadPool() try { command.javaSourceArgs.map { path -> executor.submitCallable { - val transformer = SourceTransformer(command.protoLogImplClassNameArg, - command.protoLogCacheClassNameArg, processor) + val transformer = SourceTransformer(generatedProtoLogImplClass, processor) val file = File(path) val text = injector.readText(file) val outSrc = try { val code = tryParse(text, path) - if (containsProtoLogText(text, command.protoLogClassNameArg)) { + if (containsProtoLogText(text, ProtoLog::class.java.simpleName)) { transformer.processClass(text, path, packagePath(file, code), code) } else { text @@ -93,51 +128,77 @@ object ProtoLogTool { executor.shutdown() } - val cacheSplit = command.protoLogCacheClassNameArg.split(".") - val cacheName = cacheSplit.last() - val cachePackage = cacheSplit.dropLast(1).joinToString(".") - val cachePath = "gen/${cacheSplit.joinToString("/")}.java" - - outJar.putNextEntry(zipEntry(cachePath)) - outJar.write(generateLogGroupCache(cachePackage, cacheName, groups, - command.protoLogImplClassNameArg, command.protoLogGroupsClassNameArg).toByteArray()) - outJar.close() out.close() } - fun generateLogGroupCache( - cachePackage: String, - cacheName: String, - groups: Map<String, LogGroup>, - protoLogImplClassName: String, - protoLogGroupsClassName: String + private fun generateProtoLogImpl( + protoLogImplGenName: String, + viewerConfigFilePath: String, + legacyViewerConfigFilePath: String?, + legacyOutputFilePath: String?, ): String { - val fields = groups.values.map { - "public static boolean ${it.name}_enabled = false;" - }.joinToString("\n") + val file = File(PROTOLOG_IMPL_SRC_PATH) - val updates = groups.values.map { - "${it.name}_enabled = " + - "$protoLogImplClassName.isEnabled($protoLogGroupsClassName.${it.name});" - }.joinToString("\n") + val text = try { + injector.readText(file) + } catch (e: FileNotFoundException) { + throw RuntimeException("Expected to find '$PROTOLOG_IMPL_SRC_PATH' but file was not " + + "included in source for the ProtoLog Tool to process.") + } - return """ - package $cachePackage; + val code = tryParse(text, PROTOLOG_IMPL_SRC_PATH) - public class $cacheName { -${fields.replaceIndent(" ")} + val classDeclarations = code.findAll(ClassOrInterfaceDeclaration::class.java) + require(classDeclarations.size == 1) { "Expected exactly one class declaration" } + val classDeclaration = classDeclarations[0] - static { - $protoLogImplClassName.sCacheUpdater = $cacheName::update; - update(); - } + val classNameNode = classDeclaration.findFirst(SimpleName::class.java).get() + classNameNode.setId(protoLogImplGenName) - static void update() { -${updates.replaceIndent(" ")} - } - } - """.trimIndent() + injectConstants(classDeclaration, + viewerConfigFilePath, legacyViewerConfigFilePath, legacyOutputFilePath) + + return code.toString() + } + + private fun injectConstants( + classDeclaration: ClassOrInterfaceDeclaration, + viewerConfigFilePath: String, + legacyViewerConfigFilePath: String?, + legacyOutputFilePath: String? + ) { + classDeclaration.fields.forEach { field -> + field.getAnnotationByClass(ProtoLogToolInjected::class.java) + .ifPresent { annotationExpr -> + if (annotationExpr.isSingleMemberAnnotationExpr) { + val valueName = annotationExpr.asSingleMemberAnnotationExpr() + .memberValue.asNameExpr().name.asString() + when (valueName) { + ProtoLogToolInjected.Value.VIEWER_CONFIG_PATH.name -> { + field.setFinal(true) + field.variables.first() + .setInitializer(StringLiteralExpr(viewerConfigFilePath)) + } + ProtoLogToolInjected.Value.LEGACY_OUTPUT_FILE_PATH.name -> { + field.setFinal(true) + field.variables.first() + .setInitializer(legacyOutputFilePath?.let { + StringLiteralExpr(it) + } ?: NullLiteralExpr()) + } + ProtoLogToolInjected.Value.LEGACY_VIEWER_CONFIG_PATH.name -> { + field.setFinal(true) + field.variables.first() + .setInitializer(legacyViewerConfigFilePath?.let { + StringLiteralExpr(it) + } ?: NullLiteralExpr()) + } + else -> error("Unhandled ProtoLogToolInjected value: $valueName.") + } + } + } + } } private fun tryParse(code: String, fileName: String): CompilationUnit { @@ -145,24 +206,53 @@ ${updates.replaceIndent(" ")} return StaticJavaParser.parse(code) } catch (ex: ParseProblemException) { val problem = ex.problems.first() - throw ParsingException("Java parsing erro" + - "r: ${problem.verboseMessage}", + throw ParsingException("Java parsing error: ${problem.verboseMessage}", ParsingContext(fileName, problem.location.orElse(null) ?.begin?.range?.orElse(null)?.begin?.line ?: 0)) } } + class LogCallRegistry { + private val statements = mutableMapOf<LogCall, Long>() + + fun addLogCalls(calls: List<LogCall>) { + calls.forEach { logCall -> + if (logCall.logGroup.enabled) { + statements.putIfAbsent(logCall, + CodeUtils.hash(logCall.position, logCall.messageString, + logCall.logLevel, logCall.logGroup)) + } + } + } + + fun getStatements(): Map<LogCall, Long> { + return statements + } + } + + interface ProtologViewerConfigBuilder { + fun build(statements: Map<LogCall, Long>): ByteArray + } + private fun viewerConf(command: CommandOptions) { val groups = injector.readLogGroups( command.protoLogGroupsJarArg, command.protoLogGroupsClassNameArg) - val processor = ProtoLogCallProcessor(command.protoLogClassNameArg, + val processor = ProtoLogCallProcessorImpl(command.protoLogClassNameArg, command.protoLogGroupsClassNameArg, groups) - val builder = ViewerConfigBuilder(processor) + val outputType = command.viewerConfigTypeArg + + val configBuilder: ProtologViewerConfigBuilder = when (outputType.lowercase()) { + "json" -> ViewerConfigJsonBuilder() + "proto" -> ViewerConfigProtoBuilder() + else -> error("Invalid output type provide. Provided '$outputType'.") + } val executor = newThreadPool() + val logCallRegistry = LogCallRegistry() + try { command.javaSourceArgs.map { path -> executor.submitCallable { @@ -171,7 +261,7 @@ ${updates.replaceIndent(" ")} if (containsProtoLogText(text, command.protoLogClassNameArg)) { try { val code = tryParse(text, path) - builder.findLogCalls(code, path, packagePath(file, code)) + findLogCalls(code, path, packagePath(file, code), processor) } catch (ex: ParsingException) { // If we cannot parse this file, skip it (and log why). Compilation will // fail in a subsequent build step. @@ -183,15 +273,38 @@ ${updates.replaceIndent(" ")} } } }.forEach { future -> - builder.addLogCalls(future.get() ?: return@forEach) + logCallRegistry.addLogCalls(future.get() ?: return@forEach) } } finally { executor.shutdown() } - val out = injector.fileOutputStream(command.viewerConfigJsonArg) - out.write(builder.build().toByteArray()) - out.close() + val outFile = injector.fileOutputStream(command.viewerConfigFileNameArg) + outFile.write(configBuilder.build(logCallRegistry.getStatements())) + outFile.close() + } + + private fun findLogCalls( + unit: CompilationUnit, + path: String, + packagePath: String, + processor: ProtoLogCallProcessorImpl + ): List<LogCall> { + val calls = mutableListOf<LogCall>() + val logCallVisitor = object : ProtoLogCallVisitor { + override fun processCall( + call: MethodCallExpr, + messageString: String, + level: LogLevel, + group: LogGroup + ) { + val logCall = LogCall(messageString, level, group, packagePath) + calls.add(logCall) + } + } + processor.process(unit, logCallVisitor, path) + + return calls } private fun packagePath(file: File, code: CompilationUnit): String { @@ -204,7 +317,7 @@ ${updates.replaceIndent(" ")} private fun read(command: CommandOptions) { LogParser(ViewerConfigParser()) .parse(FileInputStream(command.logProtofileArg), - FileInputStream(command.viewerConfigJsonArg), System.out) + FileInputStream(command.viewerConfigFileNameArg), System.out) } @JvmStatic diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt index 27e61a139451..2b7164191dd0 100644 --- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt +++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt @@ -17,15 +17,16 @@ package com.android.protolog.tool import com.android.internal.protolog.common.LogDataType +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.NodeList import com.github.javaparser.ast.body.VariableDeclarator -import com.github.javaparser.ast.expr.BooleanLiteralExpr import com.github.javaparser.ast.expr.CastExpr import com.github.javaparser.ast.expr.Expression import com.github.javaparser.ast.expr.FieldAccessExpr import com.github.javaparser.ast.expr.IntegerLiteralExpr +import com.github.javaparser.ast.expr.LongLiteralExpr import com.github.javaparser.ast.expr.MethodCallExpr import com.github.javaparser.ast.expr.NameExpr import com.github.javaparser.ast.expr.NullLiteralExpr @@ -34,7 +35,6 @@ import com.github.javaparser.ast.expr.TypeExpr import com.github.javaparser.ast.expr.VariableDeclarationExpr import com.github.javaparser.ast.stmt.BlockStmt import com.github.javaparser.ast.stmt.ExpressionStmt -import com.github.javaparser.ast.stmt.IfStmt import com.github.javaparser.ast.type.ArrayType import com.github.javaparser.ast.type.ClassOrInterfaceType import com.github.javaparser.ast.type.PrimitiveType @@ -44,15 +44,59 @@ import com.github.javaparser.printer.PrettyPrinterConfiguration class SourceTransformer( protoLogImplClassName: String, - protoLogCacheClassName: String, private val protoLogCallProcessor: ProtoLogCallProcessor -) : ProtoLogCallVisitor { - override fun processCall( - call: MethodCallExpr, - messageString: String, - level: LogLevel, - group: LogGroup - ) { +) { + private val inlinePrinter: PrettyPrinter + private val objectType = StaticJavaParser.parseClassOrInterfaceType("Object") + + init { + val config = PrettyPrinterConfiguration() + config.endOfLineCharacter = " " + config.indentSize = 0 + config.tabWidth = 1 + inlinePrinter = PrettyPrinter(config) + } + + fun processClass( + code: String, + path: String, + packagePath: String, + compilationUnit: CompilationUnit = + StaticJavaParser.parse(code) + ): String { + this.path = path + this.packagePath = packagePath + processedCode = code.split('\n').toMutableList() + offsets = IntArray(processedCode.size) + protoLogCallProcessor.process(compilationUnit, protoLogCallVisitor, otherCallVisitor, path) + return processedCode.joinToString("\n") + } + + private val protoLogImplClassNode = + StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogImplClassName) + private var processedCode: MutableList<String> = mutableListOf() + private var offsets: IntArray = IntArray(0) + /** The path of the file being processed, relative to $ANDROID_BUILD_TOP */ + private var path: String = "" + /** The path of the file being processed, relative to the root package */ + private var packagePath: String = "" + + private val protoLogCallVisitor = object : ProtoLogCallVisitor { + override fun processCall( + call: MethodCallExpr, + messageString: String, + level: LogLevel, + group: LogGroup + ) { + validateCall(call) + val processedCallStatement = + createProcessedCallStatement(call, group, level, messageString) + val parentStmt = call.parentNode.get() as ExpressionStmt + injectProcessedCallStatementInCode(processedCallStatement, parentStmt) + } + } + + private fun validateCall(call: MethodCallExpr) { // Input format: ProtoLog.e(GROUP, "msg %d", arg) if (!call.parentNode.isPresent) { // Should never happen @@ -70,89 +114,79 @@ class SourceTransformer( throw RuntimeException("Unable to process log call $call " + "- no grandparent node in AST") } - val ifStmt: IfStmt - if (group.enabled) { - val hash = CodeUtils.hash(packagePath, messageString, level, group) - val newCall = call.clone() - if (!group.textEnabled) { - // Remove message string if text logging is not enabled by default. - // Out: ProtoLog.e(GROUP, null, arg) - newCall.arguments[1].replace(NameExpr("null")) - } - // Insert message string hash as a second argument. - // Out: ProtoLog.e(GROUP, 1234, null, arg) - newCall.arguments.add(1, IntegerLiteralExpr(hash)) - val argTypes = LogDataType.parseFormatString(messageString) - val typeMask = LogDataType.logDataTypesToBitMask(argTypes) - // Insert bitmap representing which Number parameters are to be considered as - // floating point numbers. - // Out: ProtoLog.e(GROUP, 1234, 0, null, arg) - newCall.arguments.add(2, IntegerLiteralExpr(typeMask)) - // Replace call to a stub method with an actual implementation. - // Out: ProtoLogImpl.e(GROUP, 1234, null, arg) - newCall.setScope(protoLogImplClassNode) - // Create a call to ProtoLog$Cache.GROUP_enabled - // Out: com.android.server.protolog.ProtoLog$Cache.GROUP_enabled - val isLogEnabled = FieldAccessExpr(protoLogCacheClassNode, "${group.name}_enabled") - if (argTypes.size != call.arguments.size - 2) { - throw InvalidProtoLogCallException( - "Number of arguments (${argTypes.size} does not mach format" + - " string in: $call", ParsingContext(path, call)) - } - val blockStmt = BlockStmt() - if (argTypes.isNotEmpty()) { - // Assign every argument to a variable to check its type in compile time - // (this is assignment is optimized-out by dex tool, there is no runtime impact)/ - // Out: long protoLogParam0 = arg - argTypes.forEachIndexed { idx, type -> - val varName = "protoLogParam$idx" - val declaration = VariableDeclarator(getASTTypeForDataType(type), varName, - getConversionForType(type)(newCall.arguments[idx + 4].clone())) - blockStmt.addStatement(ExpressionStmt(VariableDeclarationExpr(declaration))) - newCall.setArgument(idx + 4, NameExpr(SimpleName(varName))) - } - } else { - // Assign (Object[])null as the vararg parameter to prevent allocating an empty - // object array. - val nullArray = CastExpr(ArrayType(objectType), NullLiteralExpr()) - newCall.addArgument(nullArray) + } + + private fun createProcessedCallStatement( + call: MethodCallExpr, + group: LogGroup, + level: LogLevel, + messageString: String + ): BlockStmt { + val hash = CodeUtils.hash(packagePath, messageString, level, group) + val newCall = call.clone() + if (!group.textEnabled) { + // Remove message string if text logging is not enabled by default. + // Out: ProtoLog.e(GROUP, null, arg) + newCall.arguments[1].replace(NameExpr("null")) + } + // Insert message string hash as a second argument. + // Out: ProtoLog.e(GROUP, 1234, null, arg) + newCall.arguments.add(1, LongLiteralExpr("" + hash + "L")) + val argTypes = LogDataType.parseFormatString(messageString) + val typeMask = LogDataType.logDataTypesToBitMask(argTypes) + // Insert bitmap representing which Number parameters are to be considered as + // floating point numbers. + // Out: ProtoLog.e(GROUP, 1234, 0, null, arg) + newCall.arguments.add(2, IntegerLiteralExpr(typeMask)) + // Replace call to a stub method with an actual implementation. + // Out: ProtoLogImpl.e(GROUP, 1234, null, arg) + newCall.setScope(protoLogImplClassNode) + if (argTypes.size != call.arguments.size - 2) { + throw InvalidProtoLogCallException( + "Number of arguments (${argTypes.size} does not match format" + + " string in: $call", ParsingContext(path, call)) + } + val blockStmt = BlockStmt() + if (argTypes.isNotEmpty()) { + // Assign every argument to a variable to check its type in compile time + // (this is assignment is optimized-out by dex tool, there is no runtime impact)/ + // Out: long protoLogParam0 = arg + argTypes.forEachIndexed { idx, type -> + val varName = "protoLogParam$idx" + val declaration = VariableDeclarator(getASTTypeForDataType(type), varName, + getConversionForType(type)(newCall.arguments[idx + 4].clone())) + blockStmt.addStatement(ExpressionStmt(VariableDeclarationExpr(declaration))) + newCall.setArgument(idx + 4, NameExpr(SimpleName(varName))) } - blockStmt.addStatement(ExpressionStmt(newCall)) - // Create an IF-statement with the previously created condition. - // Out: if (ProtoLogImpl.isEnabled(GROUP)) { - // long protoLogParam0 = arg; - // ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0); - // } - ifStmt = IfStmt(isLogEnabled, blockStmt, null) } else { - // Surround with if (false). - val newCall = parentStmt.clone() - ifStmt = IfStmt(BooleanLiteralExpr(false), BlockStmt(NodeList(newCall)), null) - newCall.setBlockComment(" ${group.name} is disabled ") + // Assign (Object[])null as the vararg parameter to prevent allocating an empty + // object array. + val nullArray = CastExpr(ArrayType(objectType), NullLiteralExpr()) + newCall.addArgument(nullArray) } + blockStmt.addStatement(ExpressionStmt(newCall)) + + return blockStmt + } + + private fun injectProcessedCallStatementInCode( + processedCallStatement: BlockStmt, + parentStmt: ExpressionStmt + ) { // Inline the new statement. - val printedIfStmt = inlinePrinter.print(ifStmt) + val printedBlockStmt = inlinePrinter.print(processedCallStatement) // Append blank lines to preserve line numbering in file (to allow debugging) val parentRange = parentStmt.range.get() val newLines = parentRange.end.line - parentRange.begin.line - val newStmt = printedIfStmt.substringBeforeLast('}') + ("\n".repeat(newLines)) + '}' + val newStmt = printedBlockStmt.substringBeforeLast('}') + ("\n".repeat(newLines)) + '}' // pre-workaround code, see explanation below - /* - val inlinedIfStmt = StaticJavaParser.parseStatement(newStmt) - LexicalPreservingPrinter.setup(inlinedIfStmt) - // Replace the original call. - if (!parentStmt.replace(inlinedIfStmt)) { - // Should never happen - throw RuntimeException("Unable to process log call $call " + - "- unable to replace the call.") - } - */ + /** Workaround for a bug in JavaParser (AST tree invalid after replacing a node when using * LexicalPreservingPrinter (https://github.com/javaparser/javaparser/issues/2290). * Replace the code below with the one commended-out above one the issue is resolved. */ if (!parentStmt.range.isPresent) { // Should never happen - throw RuntimeException("Unable to process log call $call " + + throw RuntimeException("Unable to process log call in $parentStmt " + "- unable to replace the call.") } val range = parentStmt.range.get() @@ -160,29 +194,38 @@ class SourceTransformer( val oldLines = processedCode.subList(begin, range.end.line) val oldCode = oldLines.joinToString("\n") val newCode = oldCode.replaceRange( - offsets[begin] + range.begin.column - 1, - oldCode.length - oldLines.lastOrNull()!!.length + - range.end.column + offsets[range.end.line - 1], newStmt) + offsets[begin] + range.begin.column - 1, + oldCode.length - oldLines.lastOrNull()!!.length + + range.end.column + offsets[range.end.line - 1], newStmt) newCode.split("\n").forEachIndexed { idx, line -> offsets[begin + idx] += line.length - processedCode[begin + idx].length processedCode[begin + idx] = line } } - private val inlinePrinter: PrettyPrinter - private val objectType = StaticJavaParser.parseClassOrInterfaceType("Object") + private val otherCallVisitor = object : MethodCallVisitor { + override fun processCall(call: MethodCallExpr) { + val newCall = call.clone() + newCall.setScope(protoLogImplClassNode) - init { - val config = PrettyPrinterConfiguration() - config.endOfLineCharacter = " " - config.indentSize = 0 - config.tabWidth = 1 - inlinePrinter = PrettyPrinter(config) + val range = call.range.get() + val begin = range.begin.line - 1 + val oldLines = processedCode.subList(begin, range.end.line) + val oldCode = oldLines.joinToString("\n") + val newCode = oldCode.replaceRange( + offsets[begin] + range.begin.column - 1, + oldCode.length - oldLines.lastOrNull()!!.length + + range.end.column + offsets[range.end.line - 1], newCall.toString()) + newCode.split("\n").forEachIndexed { idx, line -> + offsets[begin + idx] += line.length - processedCode[begin + idx].length + processedCode[begin + idx] = line + } + } } companion object { private val stringType: ClassOrInterfaceType = - StaticJavaParser.parseClassOrInterfaceType("String") + StaticJavaParser.parseClassOrInterfaceType("String") fun getASTTypeForDataType(type: Int): Type { return when (type) { @@ -201,36 +244,10 @@ class SourceTransformer( return when (type) { LogDataType.STRING -> { expr -> MethodCallExpr(TypeExpr(StaticJavaParser.parseClassOrInterfaceType("String")), - SimpleName("valueOf"), NodeList(expr)) + SimpleName("valueOf"), NodeList(expr)) } else -> { expr -> expr } } } } - - private val protoLogImplClassNode = - StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogImplClassName) - private val protoLogCacheClassNode = - StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogCacheClassName) - private var processedCode: MutableList<String> = mutableListOf() - private var offsets: IntArray = IntArray(0) - /** The path of the file being processed, relative to $ANDROID_BUILD_TOP */ - private var path: String = "" - /** The path of the file being processed, relative to the root package */ - private var packagePath: String = "" - - fun processClass( - code: String, - path: String, - packagePath: String, - compilationUnit: CompilationUnit = - StaticJavaParser.parse(code) - ): String { - this.path = path - this.packagePath = packagePath - processedCode = code.split('\n').toMutableList() - offsets = IntArray(processedCode.size) - protoLogCallProcessor.process(compilationUnit, this, path) - return processedCode.joinToString("\n") - } } diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt deleted file mode 100644 index 175c71ff810b..000000000000 --- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.protolog.tool - -import com.android.json.stream.JsonWriter -import com.github.javaparser.ast.CompilationUnit -import com.android.protolog.tool.Constants.VERSION -import com.github.javaparser.ast.expr.MethodCallExpr -import java.io.StringWriter - -class ViewerConfigBuilder( - private val processor: ProtoLogCallProcessor -) { - private fun addLogCall(logCall: LogCall, context: ParsingContext) { - val group = logCall.logGroup - val messageString = logCall.messageString - if (group.enabled) { - val key = logCall.key() - if (statements.containsKey(key)) { - if (statements[key] != logCall) { - throw HashCollisionException( - "Please modify the log message \"$messageString\" " + - "or \"${statements[key]}\" - their hashes are equal.", context) - } - } else { - groups.add(group) - statements[key] = logCall - } - } - } - - private val statements: MutableMap<Int, LogCall> = mutableMapOf() - private val groups: MutableSet<LogGroup> = mutableSetOf() - - fun findLogCalls( - unit: CompilationUnit, - path: String, - packagePath: String - ): List<Pair<LogCall, ParsingContext>> { - val calls = mutableListOf<Pair<LogCall, ParsingContext>>() - val visitor = object : ProtoLogCallVisitor { - override fun processCall( - call: MethodCallExpr, - messageString: String, - level: LogLevel, - group: LogGroup - ) { - val logCall = LogCall(messageString, level, group, packagePath) - val context = ParsingContext(path, call) - calls.add(logCall to context) - } - } - processor.process(unit, visitor, path) - - return calls - } - - fun addLogCalls(calls: List<Pair<LogCall, ParsingContext>>) { - calls.forEach { (logCall, context) -> - addLogCall(logCall, context) - } - } - - fun build(): String { - val stringWriter = StringWriter() - val writer = JsonWriter(stringWriter) - writer.setIndent(" ") - writer.beginObject() - writer.name("version") - writer.value(VERSION) - writer.name("messages") - writer.beginObject() - statements.toSortedMap().forEach { (key, value) -> - writer.name(key.toString()) - writer.beginObject() - writer.name("message") - writer.value(value.messageString) - writer.name("level") - writer.value(value.logLevel.name) - writer.name("group") - writer.value(value.logGroup.name) - writer.name("at") - writer.value(value.position) - writer.endObject() - } - writer.endObject() - writer.name("groups") - writer.beginObject() - groups.toSortedSet(Comparator { o1, o2 -> o1.name.compareTo(o2.name) }).forEach { group -> - writer.name(group.name) - writer.beginObject() - writer.name("tag") - writer.value(group.tag) - writer.endObject() - } - writer.endObject() - writer.endObject() - stringWriter.buffer.append('\n') - return stringWriter.toString() - } - - data class LogCall( - val messageString: String, - val logLevel: LogLevel, - val logGroup: LogGroup, - val position: String - ) { - fun key() = CodeUtils.hash(position, messageString, logLevel, logGroup) - } -} diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigJsonBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigJsonBuilder.kt new file mode 100644 index 000000000000..7714db212c9f --- /dev/null +++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigJsonBuilder.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.protolog.tool + +import com.android.json.stream.JsonWriter +import com.android.protolog.tool.Constants.VERSION +import java.io.StringWriter + +class ViewerConfigJsonBuilder : ProtoLogTool.ProtologViewerConfigBuilder { + override fun build(statements: Map<ProtoLogTool.LogCall, Long>): ByteArray { + val groups = statements.map { it.key.logGroup }.toSet() + val stringWriter = StringWriter() + val writer = JsonWriter(stringWriter) + writer.setIndent(" ") + writer.beginObject() + writer.name("version") + writer.value(VERSION) + writer.name("messages") + writer.beginObject() + statements.forEach { (log, key) -> + writer.name(key.toString()) + writer.beginObject() + writer.name("message") + writer.value(log.messageString) + writer.name("level") + writer.value(log.logLevel.name) + writer.name("group") + writer.value(log.logGroup.name) + writer.name("at") + writer.value(log.position) + writer.endObject() + } + writer.endObject() + writer.name("groups") + writer.beginObject() + groups.toSortedSet { o1, o2 -> o1.name.compareTo(o2.name) }.forEach { group -> + writer.name(group.name) + writer.beginObject() + writer.name("tag") + writer.value(group.tag) + writer.endObject() + } + writer.endObject() + writer.endObject() + stringWriter.buffer.append('\n') + return stringWriter.toString().toByteArray() + } +} diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigParser.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigParser.kt index 7278db0094e6..58be3a3e04af 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigParser.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigParser.kt @@ -63,12 +63,12 @@ open class ViewerConfigParser { return GroupEntry(tag) } - fun parseMessages(jsonReader: JsonReader): Map<Int, MessageEntry> { - val config: MutableMap<Int, MessageEntry> = mutableMapOf() + fun parseMessages(jsonReader: JsonReader): Map<Long, MessageEntry> { + val config: MutableMap<Long, MessageEntry> = mutableMapOf() jsonReader.beginObject() while (jsonReader.hasNext()) { val key = jsonReader.nextName() - val hash = key.toIntOrNull() + val hash = key.toLongOrNull() ?: throw InvalidViewerConfigException("Invalid key in messages viewer config") config[hash] = parseMessage(jsonReader) } @@ -89,8 +89,8 @@ open class ViewerConfigParser { data class ConfigEntry(val messageString: String, val level: String, val tag: String) - open fun parseConfig(jsonReader: JsonReader): Map<Int, ConfigEntry> { - var messages: Map<Int, MessageEntry>? = null + open fun parseConfig(jsonReader: JsonReader): Map<Long, ConfigEntry> { + var messages: Map<Long, MessageEntry>? = null var groups: Map<String, GroupEntry>? = null var version: String? = null diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt new file mode 100644 index 000000000000..cf0876a1f072 --- /dev/null +++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.protolog.tool + +import perfetto.protos.PerfettoTrace.ProtoLogLevel +import perfetto.protos.PerfettoTrace.ProtoLogViewerConfig + +/** + * A builder class to construct the viewer configuration (i.e. mappings of protolog hashes to log + * message information used to decode the protolog messages) encoded as a proto message. + */ +class ViewerConfigProtoBuilder : ProtoLogTool.ProtologViewerConfigBuilder { + /** + * @return a byte array of a ProtoLogViewerConfig proto message encoding all the viewer + * configurations mapping protolog hashes to message information and log group information. + */ + override fun build(statements: Map<ProtoLogTool.LogCall, Long>): ByteArray { + val configBuilder = ProtoLogViewerConfig.newBuilder() + + val groups = statements.map { it.key.logGroup }.toSet() + val groupIds = mutableMapOf<LogGroup, Int>() + groups.forEach { + groupIds.putIfAbsent(it, groupIds.size + 1) + } + + groupIds.forEach { (group, id) -> + configBuilder.addGroups(ProtoLogViewerConfig.Group.newBuilder() + .setId(id) + .setName(group.name) + .setTag(group.tag) + .build()) + } + + statements.forEach { (log, key) -> + val groupId = groupIds[log.logGroup] ?: error("missing group id") + + configBuilder.addMessages( + ProtoLogViewerConfig.MessageData.newBuilder() + .setMessageId(key) + .setMessage(log.messageString) + .setLevel( + ProtoLogLevel.forNumber(log.logLevel.ordinal + 1)) + .setGroupId(groupId) + ) + } + + return configBuilder.build().toByteArray() + } +} diff --git a/tools/protologtool/tests/com/android/protolog/tool/CodeUtilsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CodeUtilsTest.kt index b916f8f00a68..0cd02a5c5ce8 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/CodeUtilsTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/CodeUtilsTest.kt @@ -16,6 +16,7 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.expr.BinaryExpr import com.github.javaparser.ast.expr.StringLiteralExpr @@ -27,31 +28,31 @@ import org.junit.Test class CodeUtilsTest { @Test fun hash() { - assertEquals(-1259556708, CodeUtils.hash("Test.java:50", "test", + assertEquals(3883826472308915399, CodeUtils.hash("Test.java:50", "test", LogLevel.DEBUG, LogGroup("test", true, true, "TAG"))) } @Test fun hash_changeLocation() { - assertEquals(15793504, CodeUtils.hash("Test.java:10", "test2", + assertEquals(4125273133972468649, CodeUtils.hash("Test.java:10", "test2", LogLevel.DEBUG, LogGroup("test", true, true, "TAG"))) } @Test fun hash_changeLevel() { - assertEquals(-731772463, CodeUtils.hash("Test.java:50", "test", + assertEquals(2618535069521361990, CodeUtils.hash("Test.java:50", "test", LogLevel.ERROR, LogGroup("test", true, true, "TAG"))) } @Test fun hash_changeMessage() { - assertEquals(-2026343204, CodeUtils.hash("Test.java:50", "test2", + assertEquals(8907822592109789043, CodeUtils.hash("Test.java:50", "test2", LogLevel.DEBUG, LogGroup("test", true, true, "TAG"))) } @Test fun hash_changeGroup() { - assertEquals(1607870166, CodeUtils.hash("Test.java:50", "test2", + assertEquals(-1299517016176640015, CodeUtils.hash("Test.java:50", "test2", LogLevel.DEBUG, LogGroup("test2", true, true, "TAG"))) } diff --git a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt index 3cfbb435a764..5ef2833080a2 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt @@ -16,7 +16,9 @@ package com.android.protolog.tool +import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertEquals +import org.junit.Assert.assertThrows import org.junit.Test class CommandOptionsTest { @@ -35,6 +37,10 @@ class CommandOptionsTest { private const val TEST_PROTOLOGGROUP_JAR = "out/soong/.intermediates/frameworks/base/" + "services/core/services.core.wm.protologgroups/android_common/javac/" + "services.core.wm.protologgroups.jar" + private const val TEST_VIEWER_CONFIG_FILE_PATH = "/some/viewer/config/file/path.pb" + private const val TEST_LEGACY_VIEWER_CONFIG_FILE_PATH = + "/some/viewer/config/file/path.json.gz" + private const val TEST_LEGACY_OUTPUT_FILE_PATH = "/some/output/file/path.winscope" private const val TEST_SRC_JAR = "out/soong/.temp/sbox175955373/" + "services.core.wm.protolog.srcjar" private const val TEST_VIEWER_JSON = "out/soong/.temp/sbox175955373/" + @@ -42,186 +48,263 @@ class CommandOptionsTest { private const val TEST_LOG = "./test_log.pb" } - @Test(expected = InvalidCommandException::class) + @Test fun noCommand() { - CommandOptions(arrayOf()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(arrayOf()) + } + assertThat(exception).hasMessageThat().contains("No command specified") } - @Test(expected = InvalidCommandException::class) + @Test fun invalidCommand() { val testLine = "invalid" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("Unknown command") } @Test fun transformClasses() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" val cmd = CommandOptions(testLine.split(' ').toTypedArray()) assertEquals(CommandOptions.TRANSFORM_CALLS_CMD, cmd.command) assertEquals(TEST_PROTOLOG_CLASS, cmd.protoLogClassNameArg) - assertEquals(TEST_PROTOLOGIMPL_CLASS, cmd.protoLogImplClassNameArg) assertEquals(TEST_PROTOLOGGROUP_CLASS, cmd.protoLogGroupsClassNameArg) assertEquals(TEST_PROTOLOGGROUP_JAR, cmd.protoLogGroupsJarArg) + assertEquals(TEST_VIEWER_CONFIG_FILE_PATH, cmd.viewerConfigFilePathArg) + assertEquals(TEST_LEGACY_VIEWER_CONFIG_FILE_PATH, cmd.legacyViewerConfigFilePathArg) + assertEquals(TEST_LEGACY_OUTPUT_FILE_PATH, cmd.legacyOutputFilePath) assertEquals(TEST_SRC_JAR, cmd.outputSourceJarArg) assertEquals(TEST_JAVA_SRC, cmd.javaSourceArgs) } - @Test(expected = InvalidCommandException::class) - fun transformClasses_noProtoLogClass() { + @Test + fun transformClasses_noViewerConfigFile() { val testLine = "transform-protolog-calls " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--viewer-config-file-path") } - @Test(expected = InvalidCommandException::class) - fun transformClasses_noProtoLogImplClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + @Test + fun transformClasses_noLegacyViewerConfigFile() { + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val cmd = CommandOptions(testLine.split(' ').toTypedArray()) + assertEquals(CommandOptions.TRANSFORM_CALLS_CMD, cmd.command) + assertEquals(TEST_PROTOLOG_CLASS, cmd.protoLogClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_CLASS, cmd.protoLogGroupsClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_JAR, cmd.protoLogGroupsJarArg) + assertEquals(TEST_VIEWER_CONFIG_FILE_PATH, cmd.viewerConfigFilePathArg) + assertEquals(null, cmd.legacyViewerConfigFilePathArg) + assertEquals(TEST_LEGACY_OUTPUT_FILE_PATH, cmd.legacyOutputFilePath) + assertEquals(TEST_SRC_JAR, cmd.outputSourceJarArg) + assertEquals(TEST_JAVA_SRC, cmd.javaSourceArgs) } - @Test(expected = InvalidCommandException::class) - fun transformClasses_noProtoLogCacheClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + + @Test + fun transformClasses_noLegacyOutputFile() { + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val cmd = CommandOptions(testLine.split(' ').toTypedArray()) + assertEquals(CommandOptions.TRANSFORM_CALLS_CMD, cmd.command) + assertEquals(TEST_PROTOLOG_CLASS, cmd.protoLogClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_CLASS, cmd.protoLogGroupsClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_JAR, cmd.protoLogGroupsJarArg) + assertEquals(TEST_VIEWER_CONFIG_FILE_PATH, cmd.viewerConfigFilePathArg) + assertEquals(TEST_LEGACY_VIEWER_CONFIG_FILE_PATH, cmd.legacyViewerConfigFilePathArg) + assertEquals(null, cmd.legacyOutputFilePath) + assertEquals(TEST_SRC_JAR, cmd.outputSourceJarArg) + assertEquals(TEST_JAVA_SRC, cmd.javaSourceArgs) } - @Test(expected = InvalidCommandException::class) + @Test + fun transformClasses_noProtoLogClass() { + val testLine = "transform-protolog-calls " + + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--protolog-class") + } + + @Test fun transformClasses_noProtoLogGroupClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--loggroups-class") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_noProtoLogGroupJar() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--loggroups-jar") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_noOutJar() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - TEST_JAVA_SRC.joinToString(" ") - CommandOptions(testLine.split(' ').toTypedArray()) + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + + "${TEST_JAVA_SRC.joinToString(" ")}" + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--output-srcjar") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_noJavaInput() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("No java source input files") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_invalidProtoLogClass() { - val testLine = "transform-protolog-calls --protolog-class invalid " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + - "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + - "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) - } - - @Test(expected = InvalidCommandException::class) - fun transformClasses_invalidProtoLogImplClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class invalid " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + - "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + - "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) - } - - @Test(expected = InvalidCommandException::class) - fun transformClasses_invalidProtoLogCacheClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class invalid " + + val testLine = "transform-protolog-calls " + + "--protolog-class invalid " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("class name invalid") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_invalidProtoLogGroupClass() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class invalid " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("class name invalid") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_invalidProtoLogGroupJar() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar invalid.txt " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat() + .contains("Jar file required, got invalid.txt instead") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_invalidOutJar() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--output-srcjar invalid.db ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + + "--output-srcjar invalid.pb ${TEST_JAVA_SRC.joinToString(" ")}" + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat() + .contains("Source jar file required, got invalid.pb instead") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_invalidJavaInput() { - val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + - "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + - "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--output-srcjar $TEST_SRC_JAR invalid.py" - CommandOptions(testLine.split(' ').toTypedArray()) + val testLine = "transform-protolog-calls " + + "--protolog-class $TEST_PROTOLOG_CLASS " + + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-file-path $TEST_VIEWER_CONFIG_FILE_PATH " + + "--legacy-viewer-config-file-path $TEST_LEGACY_VIEWER_CONFIG_FILE_PATH " + + "--legacy-output-file-path $TEST_LEGACY_OUTPUT_FILE_PATH " + + "--output-srcjar $TEST_SRC_JAR invalid.py" + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat() + .contains("Not a java or kotlin source file invalid.py") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_unknownParam() { val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + "--unknown test --protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " + @@ -229,59 +312,88 @@ class CommandOptionsTest { "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--unknown") } - @Test(expected = InvalidCommandException::class) + @Test fun transformClasses_noValue() { val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " + - "--protolog-impl-class " + - "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " + - "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + + "--loggroups-class " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("No value for --loggroups-class") } @Test - fun generateConfig() { - val testLine = "generate-viewer-config --protolog-class $TEST_PROTOLOG_CLASS " + + fun generateConfig_json() { + val testLine = "generate-viewer-config " + + "--protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--viewer-conf $TEST_VIEWER_JSON ${TEST_JAVA_SRC.joinToString(" ")}" + "--viewer-config-type json " + + "--viewer-config $TEST_VIEWER_JSON ${TEST_JAVA_SRC.joinToString(" ")}" val cmd = CommandOptions(testLine.split(' ').toTypedArray()) assertEquals(CommandOptions.GENERATE_CONFIG_CMD, cmd.command) assertEquals(TEST_PROTOLOG_CLASS, cmd.protoLogClassNameArg) assertEquals(TEST_PROTOLOGGROUP_CLASS, cmd.protoLogGroupsClassNameArg) assertEquals(TEST_PROTOLOGGROUP_JAR, cmd.protoLogGroupsJarArg) - assertEquals(TEST_VIEWER_JSON, cmd.viewerConfigJsonArg) + assertEquals(TEST_VIEWER_JSON, cmd.viewerConfigFileNameArg) assertEquals(TEST_JAVA_SRC, cmd.javaSourceArgs) } - @Test(expected = InvalidCommandException::class) + @Test + fun generateConfig_proto() { + val testLine = "generate-viewer-config " + + "--protolog-class $TEST_PROTOLOG_CLASS " + + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + + "--viewer-config-type proto " + + "--viewer-config $TEST_VIEWER_JSON ${TEST_JAVA_SRC.joinToString(" ")}" + val cmd = CommandOptions(testLine.split(' ').toTypedArray()) + assertEquals(CommandOptions.GENERATE_CONFIG_CMD, cmd.command) + assertEquals(TEST_PROTOLOG_CLASS, cmd.protoLogClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_CLASS, cmd.protoLogGroupsClassNameArg) + assertEquals(TEST_PROTOLOGGROUP_JAR, cmd.protoLogGroupsJarArg) + assertEquals(TEST_VIEWER_JSON, cmd.viewerConfigFileNameArg) + assertEquals(TEST_JAVA_SRC, cmd.javaSourceArgs) + } + + @Test fun generateConfig_noViewerConfig() { val testLine = "generate-viewer-config --protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + TEST_JAVA_SRC.joinToString(" ") - CommandOptions(testLine.split(' ').toTypedArray()) + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("--viewer-config required") } - @Test(expected = InvalidCommandException::class) + @Test fun generateConfig_invalidViewerConfig() { val testLine = "generate-viewer-config --protolog-class $TEST_PROTOLOG_CLASS " + "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " + "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " + - "--viewer-conf invalid.yaml ${TEST_JAVA_SRC.joinToString(" ")}" - CommandOptions(testLine.split(' ').toTypedArray()) + "--viewer-config invalid.yaml ${TEST_JAVA_SRC.joinToString(" ")}" + val exception = assertThrows<InvalidCommandException>(InvalidCommandException::class.java) { + CommandOptions(testLine.split(' ').toTypedArray()) + } + assertThat(exception).hasMessageThat().contains("required, got invalid.yaml instead") } @Test fun readLog() { - val testLine = "read-log --viewer-conf $TEST_VIEWER_JSON $TEST_LOG" + val testLine = "read-log --viewer-config $TEST_VIEWER_JSON $TEST_LOG" val cmd = CommandOptions(testLine.split(' ').toTypedArray()) assertEquals(CommandOptions.READ_LOG_CMD, cmd.command) - assertEquals(TEST_VIEWER_JSON, cmd.viewerConfigJsonArg) + assertEquals(TEST_VIEWER_JSON, cmd.viewerConfigFileNameArg) assertEquals(TEST_LOG, cmd.logProtofileArg) } } diff --git a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt index 0d2b91d6cfb8..822118cc5343 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt @@ -16,22 +16,24 @@ package com.android.protolog.tool -import org.junit.Assert -import org.junit.Assert.assertTrue -import org.junit.Test +import com.android.protolog.tool.ProtoLogTool.PROTOLOG_IMPL_SRC_PATH +import com.google.common.truth.Truth import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.FileNotFoundException import java.io.OutputStream import java.util.jar.JarInputStream +import java.util.regex.Pattern +import org.junit.Assert +import org.junit.Test class EndToEndTest { @Test fun e2e_transform() { val output = run( - src = "frameworks/base/org/example/Example.java" to """ + srcs = mapOf("frameworks/base/org/example/Example.java" to """ package org.example; import com.android.internal.protolog.common.ProtoLog; import static com.android.internal.protolog.ProtoLogGroup.GROUP; @@ -43,26 +45,29 @@ class EndToEndTest { ProtoLog.d(GROUP, "Example: %s %d", argString, argInt); } } - """.trimIndent(), + """.trimIndent()), logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), commandOptions = CommandOptions(arrayOf("transform-protolog-calls", "--protolog-class", "com.android.internal.protolog.common.ProtoLog", - "--protolog-impl-class", "com.android.internal.protolog.ProtoLogImpl", - "--protolog-cache-class", - "com.android.server.wm.ProtoLogCache", "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", "--loggroups-jar", "not_required.jar", + "--viewer-config-file-path", "not_required.pb", "--output-srcjar", "out.srcjar", "frameworks/base/org/example/Example.java")) ) val outSrcJar = assertLoadSrcJar(output, "out.srcjar") - assertTrue(" 2066303299," in outSrcJar["frameworks/base/org/example/Example.java"]!!) + Truth.assertThat(outSrcJar["frameworks/base/org/example/Example.java"]) + .containsMatch(Pattern.compile("\\{ String protoLogParam0 = " + + "String\\.valueOf\\(argString\\); long protoLogParam1 = argInt; " + + "com\\.android\\.internal\\.protolog.ProtoLogImpl_.*\\.d\\(" + + "GROUP, -6872339441335321086L, 4, null, protoLogParam0, protoLogParam1" + + "\\); \\}")) } @Test fun e2e_viewerConfig() { val output = run( - src = "frameworks/base/org/example/Example.java" to """ + srcs = mapOf("frameworks/base/org/example/Example.java" to """ package org.example; import com.android.internal.protolog.common.ProtoLog; import static com.android.internal.protolog.ProtoLogGroup.GROUP; @@ -74,17 +79,27 @@ class EndToEndTest { ProtoLog.d(GROUP, "Example: %s %d", argString, argInt); } } - """.trimIndent(), + """.trimIndent()), logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), commandOptions = CommandOptions(arrayOf("generate-viewer-config", "--protolog-class", "com.android.internal.protolog.common.ProtoLog", "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", "--loggroups-jar", "not_required.jar", - "--viewer-conf", "out.json", + "--viewer-config-type", "json", + "--viewer-config", "out.json", "frameworks/base/org/example/Example.java")) ) val viewerConfigJson = assertLoadText(output, "out.json") - assertTrue("\"2066303299\"" in viewerConfigJson) + Truth.assertThat(viewerConfigJson).contains(""" + "messages": { + "-6872339441335321086": { + "message": "Example: %s %d", + "level": "DEBUG", + "group": "GROUP", + "at": "org\/example\/Example.java" + } + } + """.trimIndent()) } private fun assertLoadSrcJar( @@ -112,21 +127,46 @@ class EndToEndTest { } fun run( - src: Pair<String, String>, + srcs: Map<String, String>, logGroup: LogGroup, commandOptions: CommandOptions ): Map<String, ByteArray> { val outputs = mutableMapOf<String, ByteArrayOutputStream>() + val srcs = srcs.toMutableMap() + srcs[PROTOLOG_IMPL_SRC_PATH] = """ + package com.android.internal.protolog; + + import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_OUTPUT_FILE_PATH; + import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_VIEWER_CONFIG_PATH; + import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.VIEWER_CONFIG_PATH; + + import com.android.internal.protolog.common.ProtoLogToolInjected; + + public class ProtoLogImpl { + @ProtoLogToolInjected(VIEWER_CONFIG_PATH) + private static String sViewerConfigPath; + + @ProtoLogToolInjected(LEGACY_VIEWER_CONFIG_PATH) + private static String sLegacyViewerConfigPath; + + @ProtoLogToolInjected(LEGACY_OUTPUT_FILE_PATH) + private static String sLegacyOutputFilePath; + } + """.trimIndent() + ProtoLogTool.injector = object : ProtoLogTool.Injector { override fun fileOutputStream(file: String): OutputStream = ByteArrayOutputStream().also { outputs[file] = it } override fun readText(file: File): String { - if (file.path == src.first) { - return src.second + for (src in srcs.entries) { + val filePath = src.key + if (file.path == filePath) { + return src.value + } } - throw FileNotFoundException("expected: ${src.first}, but was $file") + throw FileNotFoundException("$file not found in [${srcs.keys.joinToString()}].") } override fun readLogGroups(jarPath: String, className: String) = mapOf( diff --git a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt index 512d90c725fe..1d3270268843 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt @@ -35,7 +35,7 @@ import java.util.Locale class LogParserTest { private val configParser: ViewerConfigParser = mock(ViewerConfigParser::class.java) private val parser = LogParser(configParser) - private var config: MutableMap<Int, ViewerConfigParser.ConfigEntry> = mutableMapOf() + private var config: MutableMap<Long, ViewerConfigParser.ConfigEntry> = mutableMapOf() private var outStream: OutputStream = ByteArrayOutputStream() private var printStream: PrintStream = PrintStream(outStream) private val dateFormat = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US) diff --git a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt index 97f67a0a3fdb..5e50f71d75cc 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt @@ -16,12 +16,13 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.expr.MethodCallExpr import org.junit.Assert.assertEquals import org.junit.Test -class ProtoLogCallProcessorTest { +class ProtoLogCallProcessorImplTest { private data class LogCall( val call: MethodCallExpr, val messageString: String, @@ -31,8 +32,11 @@ class ProtoLogCallProcessorTest { private val groupMap: MutableMap<String, LogGroup> = mutableMapOf() private val calls: MutableList<LogCall> = mutableListOf() - private val visitor = ProtoLogCallProcessor("org.example.ProtoLog", "org.example.ProtoLogGroup", - groupMap) + private val visitor = ProtoLogCallProcessorImpl( + "org.example.ProtoLog", + "org.example.ProtoLogGroup", + groupMap + ) private val processor = object : ProtoLogCallVisitor { override fun processCall( call: MethodCallExpr, diff --git a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt deleted file mode 100644 index ea9a58d859af..000000000000 --- a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.protolog.tool - -import org.junit.Assert.assertEquals -import org.junit.Test - -class ProtoLogToolTest { - - @Test - fun generateLogGroupCache() { - val groups = mapOf( - "GROUP1" to LogGroup("GROUP1", true, true, "TAG1"), - "GROUP2" to LogGroup("GROUP2", true, true, "TAG2") - ) - val code = ProtoLogTool.generateLogGroupCache("org.example", "ProtoLog\$Cache", - groups, "org.example.ProtoLogImpl", "org.example.ProtoLogGroups") - - assertEquals(""" - package org.example; - - public class ProtoLog${'$'}Cache { - public static boolean GROUP1_enabled = false; - public static boolean GROUP2_enabled = false; - - static { - org.example.ProtoLogImpl.sCacheUpdater = ProtoLog${'$'}Cache::update; - update(); - } - - static void update() { - GROUP1_enabled = org.example.ProtoLogImpl.isEnabled(org.example.ProtoLogGroups.GROUP1); - GROUP2_enabled = org.example.ProtoLogImpl.isEnabled(org.example.ProtoLogGroups.GROUP2); - } - } - """.trimIndent(), code) - } -}
\ No newline at end of file diff --git a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt index 4f2be328fc8a..de0b5bae118e 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt @@ -16,20 +16,18 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.expr.MethodCallExpr -import com.github.javaparser.ast.stmt.IfStmt +import com.google.common.truth.Truth import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse import org.junit.Test import org.mockito.Mockito class SourceTransformerTest { companion object { - private const val PROTO_LOG_IMPL_PATH = "org.example.ProtoLogImpl" - /* ktlint-disable max-line-length */ private val TEST_CODE = """ package org.example; @@ -78,7 +76,7 @@ class SourceTransformerTest { class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } } } """.trimIndent() @@ -88,20 +86,20 @@ class SourceTransformerTest { class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); } } } """.trimIndent() - private val TRANSFORMED_CODE_MULTICALL_TEXT_ENABLED = """ + private val TRANSFORMED_CODE_MULTICALL_TEXT = """ package org.example; class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } } } """.trimIndent() @@ -111,7 +109,7 @@ class SourceTransformerTest { class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { org.example.ProtoLogImpl.w(TEST_GROUP, -1741986185, 0, "test", (Object[]) null); } + { org.example.ProtoLogImpl.w(TEST_GROUP, 3218600869538902408L, 0, "test", (Object[]) null); } } } """.trimIndent() @@ -121,7 +119,7 @@ class SourceTransformerTest { class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, null, protoLogParam0, protoLogParam1); } + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, null, protoLogParam0, protoLogParam1); } } } """.trimIndent() @@ -131,43 +129,19 @@ class SourceTransformerTest { class Test { void test() { - if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); + { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); } } } """.trimIndent() - private val TRANSFORMED_CODE_DISABLED = """ - package org.example; - - class Test { - void test() { - if (false) { /* TEST_GROUP is disabled */ ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); } - } - } - """.trimIndent() - - private val TRANSFORMED_CODE_MULTILINE_DISABLED = """ - package org.example; - - class Test { - void test() { - if (false) { /* TEST_GROUP is disabled */ ProtoLog.w(TEST_GROUP, "test %d %f " + "abc %s\n test", 100, 0.1, "test"); - - } - } - } - """.trimIndent() - /* ktlint-enable max-line-length */ - private const val PATH = "com.example.Test.java" } private val processor: ProtoLogCallProcessor = Mockito.mock(ProtoLogCallProcessor::class.java) private val implName = "org.example.ProtoLogImpl" - private val cacheName = "org.example.ProtoLogCache" - private val sourceJarWriter = SourceTransformer(implName, cacheName, processor) + private val sourceJarWriter = SourceTransformer(implName, processor) private fun <T> any(type: Class<T>): T = Mockito.any<T>(type) @@ -175,9 +149,12 @@ class SourceTransformerTest { fun processClass_textEnabled() { var code = StaticJavaParser.parse(TEST_CODE) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f", @@ -189,18 +166,15 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(3, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(1) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(6, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("1698911065", methodCall.arguments[1].toString()) + assertEquals("-1473209266730422156L", methodCall.arguments[1].toString()) assertEquals(0b1001.toString(), methodCall.arguments[2].toString()) assertEquals("\"test %d %f\"", methodCall.arguments[3].toString()) assertEquals("protoLogParam0", methodCall.arguments[4].toString()) @@ -212,9 +186,12 @@ class SourceTransformerTest { fun processClass_textEnabledMulticalls() { var code = StaticJavaParser.parse(TEST_CODE_MULTICALLS) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor val calls = code.findAll(MethodCallExpr::class.java) @@ -231,32 +208,32 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE_MULTICALLS, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(3, ifStmts.size) - val ifStmt = ifStmts[1] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(3, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(3) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(6, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("1698911065", methodCall.arguments[1].toString()) + assertEquals("-1473209266730422156L", methodCall.arguments[1].toString()) assertEquals(0b1001.toString(), methodCall.arguments[2].toString()) assertEquals("\"test %d %f\"", methodCall.arguments[3].toString()) assertEquals("protoLogParam0", methodCall.arguments[4].toString()) assertEquals("protoLogParam1", methodCall.arguments[5].toString()) - assertEquals(TRANSFORMED_CODE_MULTICALL_TEXT_ENABLED, out) + assertEquals(TRANSFORMED_CODE_MULTICALL_TEXT, out) } @Test fun processClass_textEnabledMultiline() { var code = StaticJavaParser.parse(TEST_CODE_MULTILINE) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], @@ -269,18 +246,15 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(4, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[1] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(1) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(7, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("1780316587", methodCall.arguments[1].toString()) + assertEquals("-4447034859795564700L", methodCall.arguments[1].toString()) assertEquals(0b001001.toString(), methodCall.arguments[2].toString()) assertEquals("protoLogParam0", methodCall.arguments[4].toString()) assertEquals("protoLogParam1", methodCall.arguments[5].toString()) @@ -292,9 +266,12 @@ class SourceTransformerTest { fun processClass_noParams() { var code = StaticJavaParser.parse(TEST_CODE_NO_PARAMS) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test", @@ -306,18 +283,15 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE_NO_PARAMS, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(1, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(1) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(5, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("-1741986185", methodCall.arguments[1].toString()) + assertEquals("3218600869538902408L", methodCall.arguments[1].toString()) assertEquals(0.toString(), methodCall.arguments[2].toString()) assertEquals(TRANSFORMED_CODE_NO_PARAMS, out) } @@ -326,9 +300,12 @@ class SourceTransformerTest { fun processClass_textDisabled() { var code = StaticJavaParser.parse(TEST_CODE) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f", @@ -340,18 +317,15 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(3, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(1) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(6, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("1698911065", methodCall.arguments[1].toString()) + assertEquals("-1473209266730422156L", methodCall.arguments[1].toString()) assertEquals(0b1001.toString(), methodCall.arguments[2].toString()) assertEquals("null", methodCall.arguments[3].toString()) assertEquals("protoLogParam0", methodCall.arguments[4].toString()) @@ -363,9 +337,12 @@ class SourceTransformerTest { fun processClass_textDisabledMultiline() { var code = StaticJavaParser.parse(TEST_CODE_MULTILINE) - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> + Mockito.`when`(processor.process( + any(CompilationUnit::class.java), + any(ProtoLogCallVisitor::class.java), + any(MethodCallVisitor::class.java), + any(String::class.java)) + ).thenAnswer { invocation -> val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], @@ -378,18 +355,15 @@ class SourceTransformerTest { val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code) code = StaticJavaParser.parse(out) - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString()) - assertFalse(ifStmt.elseStmt.isPresent) - assertEquals(4, ifStmt.thenStmt.childNodes.size) - val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[1] as MethodCallExpr - assertEquals(PROTO_LOG_IMPL_PATH, methodCall.scope.get().toString()) + val protoLogCalls = code.findAll(MethodCallExpr::class.java).filter { + it.scope.orElse(null)?.toString() == implName + } + Truth.assertThat(protoLogCalls).hasSize(1) + val methodCall = protoLogCalls[0] as MethodCallExpr assertEquals("w", methodCall.name.asString()) assertEquals(7, methodCall.arguments.size) assertEquals("TEST_GROUP", methodCall.arguments[0].toString()) - assertEquals("1780316587", methodCall.arguments[1].toString()) + assertEquals("-4447034859795564700L", methodCall.arguments[1].toString()) assertEquals(0b001001.toString(), methodCall.arguments[2].toString()) assertEquals("null", methodCall.arguments[3].toString()) assertEquals("protoLogParam0", methodCall.arguments[4].toString()) @@ -397,55 +371,4 @@ class SourceTransformerTest { assertEquals("protoLogParam2", methodCall.arguments[6].toString()) assertEquals(TRANSFORMED_CODE_MULTILINE_TEXT_DISABLED, out) } - - @Test - fun processClass_disabled() { - var code = StaticJavaParser.parse(TEST_CODE) - - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> - val visitor = invocation.arguments[1] as ProtoLogCallVisitor - - visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", false, true, "WM_TEST")) - - invocation.arguments[0] as CompilationUnit - } - - val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code) - code = StaticJavaParser.parse(out) - - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("false", ifStmt.condition.toString()) - assertEquals(TRANSFORMED_CODE_DISABLED, out) - } - - @Test - fun processClass_disabledMultiline() { - var code = StaticJavaParser.parse(TEST_CODE_MULTILINE) - - Mockito.`when`(processor.process(any(CompilationUnit::class.java), - any(ProtoLogCallVisitor::class.java), any(String::class.java))) - .thenAnswer { invocation -> - val visitor = invocation.arguments[1] as ProtoLogCallVisitor - - visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], - "test %d %f abc %s\n test", LogLevel.WARN, LogGroup("TEST_GROUP", - false, true, "WM_TEST")) - - invocation.arguments[0] as CompilationUnit - } - - val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code) - code = StaticJavaParser.parse(out) - - val ifStmts = code.findAll(IfStmt::class.java) - assertEquals(1, ifStmts.size) - val ifStmt = ifStmts[0] - assertEquals("false", ifStmt.condition.toString()) - assertEquals(TRANSFORMED_CODE_MULTILINE_DISABLED, out) - } } diff --git a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt index a24761aed9db..d27ae88fc488 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt @@ -16,14 +16,14 @@ package com.android.protolog.tool +import com.android.internal.protolog.common.LogLevel import com.android.json.stream.JsonReader -import com.android.protolog.tool.ViewerConfigBuilder.LogCall +import com.android.protolog.tool.ProtoLogTool.LogCall +import java.io.StringReader import org.junit.Assert.assertEquals import org.junit.Test -import org.mockito.Mockito -import java.io.StringReader -class ViewerConfigBuilderTest { +class ViewerConfigJsonBuilderTest { companion object { private val TAG1 = "WM_TEST" private val TAG2 = "WM_DEBUG" @@ -38,20 +38,22 @@ class ViewerConfigBuilderTest { private const val PATH = "/tmp/test.java" } - private val configBuilder = ViewerConfigBuilder(Mockito.mock(ProtoLogCallProcessor::class.java)) + private val configBuilder = ViewerConfigJsonBuilder() - private fun parseConfig(json: String): Map<Int, ViewerConfigParser.ConfigEntry> { + private fun parseConfig(json: String): Map<Long, ViewerConfigParser.ConfigEntry> { return ViewerConfigParser().parseConfig(JsonReader(StringReader(json))) } @Test fun processClass() { - configBuilder.addLogCalls(listOf( + val logCallRegistry = ProtoLogTool.LogCallRegistry() + logCallRegistry.addLogCalls(listOf( LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP2, PATH), - LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH)).withContext()) + LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH))) - val parsedConfig = parseConfig(configBuilder.build()) + val parsedConfig = parseConfig( + configBuilder.build(logCallRegistry.getStatements()).toString(Charsets.UTF_8)) assertEquals(3, parsedConfig.size) assertEquals(TEST1, parsedConfig[CodeUtils.hash(PATH, TEST1.messageString, LogLevel.INFO, GROUP1)]) @@ -63,32 +65,16 @@ class ViewerConfigBuilderTest { @Test fun processClass_nonUnique() { - configBuilder.addLogCalls(listOf( + val logCallRegistry = ProtoLogTool.LogCallRegistry() + logCallRegistry.addLogCalls(listOf( LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH)).withContext()) + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH))) - val parsedConfig = parseConfig(configBuilder.build()) + val parsedConfig = parseConfig( + configBuilder.build(logCallRegistry.getStatements()).toString(Charsets.UTF_8)) assertEquals(1, parsedConfig.size) assertEquals(TEST1, parsedConfig[CodeUtils.hash(PATH, TEST1.messageString, - LogLevel.INFO, GROUP1)]) - } - - @Test - fun processClass_disabled() { - configBuilder.addLogCalls(listOf( - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP_DISABLED, PATH), - LogCall(TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED, PATH)) - .withContext()) - - val parsedConfig = parseConfig(configBuilder.build()) - assertEquals(2, parsedConfig.size) - assertEquals(TEST1, parsedConfig[CodeUtils.hash( - PATH, TEST1.messageString, LogLevel.INFO, GROUP1)]) - assertEquals(TEST3, parsedConfig[CodeUtils.hash( - PATH, TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED)]) + LogLevel.INFO, GROUP1)]) } - - private fun List<LogCall>.withContext() = map { it to ParsingContext() } } |