diff options
333 files changed, 6582 insertions, 4490 deletions
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb index 3258514cb6d7..0ccd9511d945 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "7533747" + build_id: "7552332" target: "CtsShim" source_file: "aosp_arm64/CtsShimPriv.apk" } @@ -10,4 +10,6 @@ drops { git_project: "platform/frameworks/base" git_branch: "sc-dev" transform: TRANSFORM_NONE + transform_options { + } } diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb index 4fb50e22989c..7e85c8f6697d 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "7533747" + build_id: "7552332" target: "CtsShim" source_file: "aosp_arm64/CtsShim.apk" } @@ -10,4 +10,6 @@ drops { git_project: "platform/frameworks/base" git_branch: "sc-dev" transform: TRANSFORM_NONE + transform_options { + } } diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb index 1a0e3185665a..20c27858e9ab 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "7533747" + build_id: "7552332" target: "CtsShim" source_file: "aosp_x86_64/CtsShimPriv.apk" } @@ -10,4 +10,6 @@ drops { git_project: "platform/frameworks/base" git_branch: "sc-dev" transform: TRANSFORM_NONE + transform_options { + } } diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb index d72f62e52148..13e3ae5b121b 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "7533747" + build_id: "7552332" target: "CtsShim" source_file: "aosp_x86_64/CtsShim.apk" } @@ -10,4 +10,6 @@ drops { git_project: "platform/frameworks/base" git_branch: "sc-dev" transform: TRANSFORM_NONE + transform_options { + } } diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java index 21c4491fc371..ab3c50b209e6 100644 --- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java +++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java @@ -304,10 +304,9 @@ public class ImePerfTest extends ImePerfTestBase while (state.keepRunning(measuredTimeNs)) { setImeListener(activity, latchStart, latchEnd); - latchStart.set(new CountDownLatch(show ? 1 : 2)); - latchEnd.set(new CountDownLatch(2)); // For measuring hide, lets show IME first. if (!show) { + initLatch(latchStart, latchEnd); AtomicBoolean showCalled = new AtomicBoolean(); getInstrumentation().runOnMainSync(() -> { if (!isImeVisible(activity)) { @@ -316,9 +315,10 @@ public class ImePerfTest extends ImePerfTestBase } }); if (showCalled.get()) { - PollingCheck.check("IME show animation should finish ", TIMEOUT_1_S_IN_MS, - () -> latchStart.get().getCount() == 1 - && latchEnd.get().getCount() == 1); + PollingCheck.check("IME show animation should finish ", + TIMEOUT_1_S_IN_MS * 3, + () -> latchStart.get().getCount() == 0 + && latchEnd.get().getCount() == 0); } } if (!mIsTraceStarted && !state.isWarmingUp()) { @@ -328,6 +328,7 @@ public class ImePerfTest extends ImePerfTestBase AtomicLong startTime = new AtomicLong(); AtomicBoolean unexpectedVisibility = new AtomicBoolean(); + initLatch(latchStart, latchEnd); getInstrumentation().runOnMainSync(() -> { boolean isVisible = isImeVisible(activity); startTime.set(SystemClock.elapsedRealtimeNanos()); @@ -346,11 +347,15 @@ public class ImePerfTest extends ImePerfTestBase long timeElapsed = waitForAnimationStart(latchStart, startTime); if (timeElapsed != ANIMATION_NOT_STARTED) { measuredTimeNs = timeElapsed; + // wait for animation to end or we may start two animations and timing + // will not be measured accurately. + waitForAnimationEnd(latchEnd); } } // hide IME before next iteration. if (show) { + initLatch(latchStart, latchEnd); activity.runOnUiThread(() -> controller.hide(WindowInsets.Type.ime())); try { latchEnd.get().await(TIMEOUT_1_S_IN_MS * 5, TimeUnit.MILLISECONDS); @@ -372,6 +377,12 @@ public class ImePerfTest extends ImePerfTestBase addResultToState(state); } + private void initLatch(AtomicReference<CountDownLatch> latchStart, + AtomicReference<CountDownLatch> latchEnd) { + latchStart.set(new CountDownLatch(1)); + latchEnd.set(new CountDownLatch(1)); + } + @UiThread private boolean isImeVisible(@NonNull final Activity activity) { return activity.getWindow().getDecorView().getRootWindowInsets().isVisible( @@ -381,7 +392,7 @@ public class ImePerfTest extends ImePerfTestBase private long waitForAnimationStart( AtomicReference<CountDownLatch> latchStart, AtomicLong startTime) { try { - latchStart.get().await(TIMEOUT_1_S_IN_MS * 5, TimeUnit.MILLISECONDS); + latchStart.get().await(5, TimeUnit.SECONDS); if (latchStart.get().getCount() != 0) { return ANIMATION_NOT_STARTED; } @@ -390,6 +401,12 @@ public class ImePerfTest extends ImePerfTestBase return SystemClock.elapsedRealtimeNanos() - startTime.get(); } + private void waitForAnimationEnd(AtomicReference<CountDownLatch> latchEnd) { + try { + latchEnd.get().await(3, TimeUnit.SECONDS); + } catch (InterruptedException e) { } + } + private void addResultToState(ManualBenchmarkState state) { mTraceMethods.forAllSlices((key, slices) -> { for (TraceMarkSlice slice : slices) { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index b52a503a2166..666d49770a70 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -795,7 +795,7 @@ public class AppSearchManagerService extends SystemService { AppSearchUserInstance instance = mAppSearchUserInstanceManager.getUserInstance(callingUser); SearchResultPage searchResultPage = - instance.getAppSearchImpl().getNextPage(nextPageToken); + instance.getAppSearchImpl().getNextPage(packageName, nextPageToken); invokeCallbackOnResult( callback, AppSearchResult.newSuccessfulResult(searchResultPage.getBundle())); @@ -821,7 +821,7 @@ public class AppSearchManagerService extends SystemService { verifyNotInstantApp(userContext, packageName); AppSearchUserInstance instance = mAppSearchUserInstanceManager.getUserInstance(callingUser); - instance.getAppSearchImpl().invalidateNextPageToken(nextPageToken); + instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken); } catch (Throwable t) { Log.e(TAG, "Unable to invalidate the query page token", t); } @@ -871,7 +871,7 @@ public class AppSearchManagerService extends SystemService { .getGenericDocument().getBundle()); } searchResultPage = instance.getAppSearchImpl().getNextPage( - searchResultPage.getNextPageToken()); + packageName, searchResultPage.getNextPageToken()); } } invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null)); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java index a1b93ce12975..830e76c62279 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java @@ -173,6 +173,21 @@ public final class AppSearchImpl implements Closeable { @GuardedBy("mReadWriteLock") private final Map<String, Integer> mDocumentCountMapLocked = new ArrayMap<>(); + // Maps packages to the set of valid nextPageTokens that the package can manipulate. A token + // is unique and constant per query (i.e. the same token '123' is used to iterate through + // pages of search results). The tokens themselves are generated and tracked by + // IcingSearchEngine. IcingSearchEngine considers a token valid and won't be reused + // until we call invalidateNextPageToken on the token. + // + // Note that we synchronize on itself because the nextPageToken cache is checked at + // query-time, and queries are done in parallel with a read lock. Ideally, this would be + // guarded by the normal mReadWriteLock.writeLock, but ReentrantReadWriteLocks can't upgrade + // read to write locks. This lock should be acquired at the smallest scope possible. + // mReadWriteLock is a higher-level lock, so calls shouldn't be made out + // to any functions that grab the lock. + @GuardedBy("mNextPageTokensLocked") + private final Map<String, Set<Long>> mNextPageTokensLocked = new ArrayMap<>(); + /** * The counter to check when to call {@link #checkForOptimize}. The interval is {@link * #CHECK_OPTIMIZE_INTERVAL}. @@ -837,12 +852,15 @@ public final class AppSearchImpl implements Closeable { String prefix = createPrefix(packageName, databaseName); Set<String> allowedPrefixedSchemas = getAllowedPrefixSchemasLocked(prefix, searchSpec); - return doQueryLocked( - Collections.singleton(createPrefix(packageName, databaseName)), - allowedPrefixedSchemas, - queryExpression, - searchSpec, - sStatsBuilder); + SearchResultPage searchResultPage = + doQueryLocked( + Collections.singleton(createPrefix(packageName, databaseName)), + allowedPrefixedSchemas, + queryExpression, + searchSpec, + sStatsBuilder); + addNextPageToken(packageName, searchResultPage.getNextPageToken()); + return searchResultPage; } finally { mReadWriteLock.readLock().unlock(); if (logger != null) { @@ -956,12 +974,15 @@ public final class AppSearchImpl implements Closeable { } } - return doQueryLocked( - prefixFilters, - prefixedSchemaFilters, - queryExpression, - searchSpec, - sStatsBuilder); + SearchResultPage searchResultPage = + doQueryLocked( + prefixFilters, + prefixedSchemaFilters, + queryExpression, + searchSpec, + sStatsBuilder); + addNextPageToken(callerPackageName, searchResultPage.getNextPageToken()); + return searchResultPage; } finally { mReadWriteLock.readLock().unlock(); @@ -1093,17 +1114,20 @@ public final class AppSearchImpl implements Closeable { * * <p>This method belongs to query group. * + * @param packageName Package name of the caller. * @param nextPageToken The token of pre-loaded results of previously executed query. * @return The next page of results of previously executed query. - * @throws AppSearchException on IcingSearchEngine error. + * @throws AppSearchException on IcingSearchEngine error or if can't advance on nextPageToken. */ @NonNull - public SearchResultPage getNextPage(long nextPageToken) throws AppSearchException { + public SearchResultPage getNextPage(@NonNull String packageName, long nextPageToken) + throws AppSearchException { mReadWriteLock.readLock().lock(); try { throwIfClosedLocked(); mLogUtil.piiTrace("getNextPage, request", nextPageToken); + checkNextPageToken(packageName, nextPageToken); SearchResultProto searchResultProto = mIcingSearchEngineLocked.getNextPage(nextPageToken); mLogUtil.piiTrace( @@ -1122,16 +1146,26 @@ public final class AppSearchImpl implements Closeable { * * <p>This method belongs to query group. * + * @param packageName Package name of the caller. * @param nextPageToken The token of pre-loaded results of previously executed query to be * Invalidated. + * @throws AppSearchException if nextPageToken is unusable. */ - public void invalidateNextPageToken(long nextPageToken) { + public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken) + throws AppSearchException { mReadWriteLock.readLock().lock(); try { throwIfClosedLocked(); mLogUtil.piiTrace("invalidateNextPageToken, request", nextPageToken); + checkNextPageToken(packageName, nextPageToken); mIcingSearchEngineLocked.invalidateNextPageToken(nextPageToken); + + synchronized (mNextPageTokensLocked) { + // At this point, we're guaranteed that this nextPageToken exists for this package, + // otherwise checkNextPageToken would've thrown an exception. + mNextPageTokensLocked.get(packageName).remove(nextPageToken); + } } finally { mReadWriteLock.readLock().unlock(); } @@ -1568,6 +1602,9 @@ public final class AppSearchImpl implements Closeable { Set<String> databaseNames = entry.getValue(); if (!installedPackages.contains(packageName) && databaseNames != null) { mDocumentCountMapLocked.remove(packageName); + synchronized (mNextPageTokensLocked) { + mNextPageTokensLocked.remove(packageName); + } for (String databaseName : databaseNames) { String removedPrefix = createPrefix(packageName, databaseName); mSchemaMapLocked.remove(removedPrefix); @@ -1601,6 +1638,9 @@ public final class AppSearchImpl implements Closeable { mSchemaMapLocked.clear(); mNamespaceMapLocked.clear(); mDocumentCountMapLocked.clear(); + synchronized (mNextPageTokensLocked) { + mNextPageTokensLocked.clear(); + } if (initStatsBuilder != null) { initStatsBuilder .setHasReset(true) @@ -2015,6 +2055,32 @@ public final class AppSearchImpl implements Closeable { return schemaProto.getSchema(); } + private void addNextPageToken(String packageName, long nextPageToken) { + synchronized (mNextPageTokensLocked) { + Set<Long> tokens = mNextPageTokensLocked.get(packageName); + if (tokens == null) { + tokens = new ArraySet<>(); + mNextPageTokensLocked.put(packageName, tokens); + } + tokens.add(nextPageToken); + } + } + + private void checkNextPageToken(String packageName, long nextPageToken) + throws AppSearchException { + synchronized (mNextPageTokensLocked) { + Set<Long> nextPageTokens = mNextPageTokensLocked.get(packageName); + if (nextPageTokens == null || !nextPageTokens.contains(nextPageToken)) { + throw new AppSearchException( + AppSearchResult.RESULT_SECURITY_ERROR, + "Package \"" + + packageName + + "\" cannot use nextPageToken: " + + nextPageToken); + } + } + } + private static void addToMap( Map<String, Set<String>> map, String prefix, String prefixedValue) { Set<String> values = map.get(prefix); 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 ed80ddbd2cd7..9f529548833d 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -256,6 +256,7 @@ public class AlarmManagerService extends SystemService { AlarmHandler mHandler; AppWakeupHistory mAppWakeupHistory; AppWakeupHistory mAllowWhileIdleHistory; + AppWakeupHistory mAllowWhileIdleCompatHistory; private final SparseLongArray mLastPriorityAlarmDispatch = new SparseLongArray(); private final SparseArray<RingBuffer<RemovedAlarm>> mRemovalHistory = new SparseArray<>(); ClockReceiver mClockReceiver; @@ -1633,6 +1634,7 @@ public class AlarmManagerService extends SystemService { mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); mAllowWhileIdleHistory = new AppWakeupHistory(INTERVAL_HOUR); + mAllowWhileIdleCompatHistory = new AppWakeupHistory(INTERVAL_HOUR); mNextWakeup = mNextNonWakeup = 0; @@ -2142,20 +2144,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; + final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; + history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; + history = mAllowWhileIdleCompatHistory; } - final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( + final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); - if (dispatchesInWindow < quota) { + if (dispatchesInHistory < quota) { // fine to go out immediately. batterySaverPolicyElapsed = nowElapsed; } else { - batterySaverPolicyElapsed = mAllowWhileIdleHistory.getNthLastWakeupForPackage( + batterySaverPolicyElapsed = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; } } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) { @@ -2201,20 +2206,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; + final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; + history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; + history = mAllowWhileIdleCompatHistory; } - final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( + final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); - if (dispatchesInWindow < quota) { + if (dispatchesInHistory < quota) { // fine to go out immediately. deviceIdlePolicyTime = nowElapsed; } else { - final long whenInQuota = mAllowWhileIdleHistory.getNthLastWakeupForPackage( + final long whenInQuota = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed()); } @@ -2502,6 +2510,7 @@ public class AlarmManagerService extends SystemService { Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized"); // The API doesn't allow using both together. flags &= ~FLAG_ALLOW_WHILE_IDLE; + // Prioritized alarms don't need any extra permission to be exact. } else if (exact || allowWhileIdle) { final boolean needsPermission; boolean lowerQuota; @@ -2992,6 +3001,10 @@ public class AlarmManagerService extends SystemService { mAllowWhileIdleHistory.dump(pw, nowELAPSED); pw.println(); + pw.println("Allow while idle compat history:"); + mAllowWhileIdleCompatHistory.dump(pw, nowELAPSED); + pw.println(); + if (mLastPriorityAlarmDispatch.size() > 0) { pw.println("Last priority alarm dispatches:"); pw.increaseIndent(); @@ -4553,6 +4566,7 @@ public class AlarmManagerService extends SystemService { removeUserLocked(userHandle); mAppWakeupHistory.removeForUser(userHandle); mAllowWhileIdleHistory.removeForUser(userHandle); + mAllowWhileIdleCompatHistory.removeForUser(userHandle); } return; case Intent.ACTION_UID_REMOVED: @@ -4588,6 +4602,8 @@ public class AlarmManagerService extends SystemService { // package-removed and package-restarted case mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); + mAllowWhileIdleCompatHistory.removeForPackage(pkg, + UserHandle.getUserId(uid)); removeLocked(uid, REMOVE_REASON_UNDEFINED); } else { // external-applications-unavailable case @@ -4965,7 +4981,10 @@ public class AlarmManagerService extends SystemService { if (isAllowedWhileIdleRestricted(alarm)) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the // device was in doze or battery saver. - mAllowWhileIdleHistory.recordAlarmForPackage(alarm.sourcePackage, + final AppWakeupHistory history = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) + ? mAllowWhileIdleHistory + : mAllowWhileIdleCompatHistory; + history.recordAlarmForPackage(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid), nowELAPSED); mAlarmStore.updateAlarmDeliveries(a -> { if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java index 3069db32c548..6d67ee37d8e6 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java +++ b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java @@ -59,7 +59,7 @@ public class ThermalStatusRestriction extends JobRestriction { @Override public boolean isJobRestricted(JobStatus job) { - return mIsThermalRestricted && job.hasConnectivityConstraint(); + return mIsThermalRestricted; } @Override diff --git a/core/api/test-current.txt b/core/api/test-current.txt index dd7c6db5d8fb..a0799394177d 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1421,6 +1421,7 @@ package android.media { method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int abandonAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String); method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int); method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFadeOutDurationOnFocusLossMillis(@NonNull android.media.AudioAttributes); + method @NonNull public java.util.List<java.lang.Integer> getReportedSurroundFormats(); method @NonNull public java.util.Map<java.lang.Integer,java.lang.Boolean> getSurroundFormats(); method public boolean hasRegisteredDynamicPolicy(); method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.QUERY_AUDIO_STATE}) public boolean isFullVolumeDevice(); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 91e2d88ad7cb..4376d225e676 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -406,6 +406,12 @@ public class ActivityManager { public static final int BROADCAST_FAILED_USER_STOPPED = -2; /** + * Type for IActivityManaqer.getIntentSender: this PendingIntent type is unknown. + * @hide + */ + public static final int INTENT_SENDER_UNKNOWN = 0; + + /** * Type for IActivityManaqer.getIntentSender: this PendingIntent is * for a sendBroadcast operation. * @hide @@ -4860,12 +4866,12 @@ public class ActivityManager { */ public static final class PendingIntentInfo implements Parcelable { - private final String mCreatorPackage; + @Nullable private final String mCreatorPackage; private final int mCreatorUid; private final boolean mImmutable; private final int mIntentSenderType; - public PendingIntentInfo(String creatorPackage, int creatorUid, boolean immutable, + public PendingIntentInfo(@Nullable String creatorPackage, int creatorUid, boolean immutable, int intentSenderType) { mCreatorPackage = creatorPackage; mCreatorUid = creatorUid; @@ -4873,6 +4879,7 @@ public class ActivityManager { mIntentSenderType = intentSenderType; } + @Nullable public String getCreatorPackage() { return mCreatorPackage; } diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 444cc4eedcb1..85758a92fa98 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -28,11 +28,13 @@ import android.content.LocusId; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; +import android.graphics.Rect; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; +import android.view.DisplayCutout; import android.window.TaskSnapshot; import android.window.WindowContainerToken; @@ -174,6 +176,15 @@ public class TaskInfo { public PictureInPictureParams pictureInPictureParams; /** + * The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of + * (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS), + * {@code null} otherwise. + * @hide + */ + @Nullable + public Rect displayCutoutInsets; + + /** * The activity type of the top activity in this task. * @hide */ @@ -332,6 +343,7 @@ public class TaskInfo { && supportsMultiWindow == that.supportsMultiWindow && Objects.equals(positionInParent, that.positionInParent) && Objects.equals(pictureInPictureParams, that.pictureInPictureParams) + && Objects.equals(displayCutoutInsets, that.displayCutoutInsets) && getWindowingMode() == that.getWindowingMode() && Objects.equals(taskDescription, that.taskDescription) && isFocused == that.isFocused @@ -382,6 +394,7 @@ public class TaskInfo { token = WindowContainerToken.CREATOR.createFromParcel(source); topActivityType = source.readInt(); pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR); + displayCutoutInsets = source.readTypedObject(Rect.CREATOR); topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); isResizeable = source.readBoolean(); source.readBinderList(launchCookies); @@ -419,6 +432,7 @@ public class TaskInfo { token.writeToParcel(dest, flags); dest.writeInt(topActivityType); dest.writeTypedObject(pictureInPictureParams, flags); + dest.writeTypedObject(displayCutoutInsets, flags); dest.writeTypedObject(topActivityInfo, flags); dest.writeBoolean(isResizeable); dest.writeBinderList(launchCookies); @@ -447,6 +461,7 @@ public class TaskInfo { + " token=" + token + " topActivityType=" + topActivityType + " pictureInPictureParams=" + pictureInPictureParams + + " displayCutoutSafeInsets=" + displayCutoutInsets + " topActivityInfo=" + topActivityInfo + " launchCookies=" + launchCookies + " positionInParent=" + positionInParent diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java index d63ce0f4a943..bdb7900b5bb9 100644 --- a/core/java/android/content/AttributionSource.java +++ b/core/java/android/content/AttributionSource.java @@ -152,6 +152,10 @@ public final class AttributionSource implements Parcelable { AttributionSource(@NonNull Parcel in) { this(AttributionSourceState.CREATOR.createFromParcel(in)); + + // Since we just unpacked this object as part of it transiting a Binder + // call, this is the perfect time to enforce that its UID can be trusted + enforceCallingUid(); } /** @hide */ @@ -248,7 +252,8 @@ public final class AttributionSource implements Parcelable { */ public boolean checkCallingUid() { final int callingUid = Binder.getCallingUid(); - if (callingUid != Process.SYSTEM_UID + if (callingUid != Process.ROOT_UID + && callingUid != Process.SYSTEM_UID && callingUid != mAttributionSourceState.uid) { return false; } diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl index 6105c26dc651..debc074ea21a 100644 --- a/core/java/android/hardware/ISensorPrivacyManager.aidl +++ b/core/java/android/hardware/ISensorPrivacyManager.aidl @@ -46,6 +46,6 @@ interface ISensorPrivacyManager { void setIndividualSensorPrivacyForProfileGroup(int userId, int source, int sensor, boolean enable); // =============== End of transactions used on native side as well ============================ - void suppressIndividualSensorPrivacyReminders(int userId, String packageName, IBinder token, + void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress); }
\ No newline at end of file diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index c392fbb52de0..b7d95e7dea74 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -461,9 +461,9 @@ public final class SensorPrivacyManager { * @hide */ @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) - public void suppressSensorPrivacyReminders(@NonNull String packageName, + public void suppressSensorPrivacyReminders(int sensor, boolean suppress) { - suppressSensorPrivacyReminders(packageName, suppress, mContext.getUserId()); + suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId()); } /** @@ -476,10 +476,10 @@ public final class SensorPrivacyManager { * @hide */ @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) - public void suppressSensorPrivacyReminders(@NonNull String packageName, + public void suppressSensorPrivacyReminders(int sensor, boolean suppress, @UserIdInt int userId) { try { - mService.suppressIndividualSensorPrivacyReminders(userId, packageName, + mService.suppressIndividualSensorPrivacyReminders(userId, sensor, token, suppress); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java index 35d00f03de67..9309c5b0d8e3 100644 --- a/core/java/android/hardware/location/ContextHubClientCallback.java +++ b/core/java/android/hardware/location/ContextHubClientCallback.java @@ -68,8 +68,11 @@ public class ContextHubClientCallback { /** * Callback invoked when a nanoapp is dynamically loaded at the attached Context Hub through - * the {@link android.hardware.location.ContextHubManager}. This callback is not invoked for a - * nanoapp that is loaded internally by CHRE (e.g. nanoapps that are preloaded by the system). + * the {@link android.hardware.location.ContextHubManager}. + * + * NOTE: This callback is <b>not</b> invoked for a nanoapp that is loaded internally by CHRE + * (e.g. nanoapps that are preloaded by the system). To check the availability of these + * nanoapps, use the {@link ContextHubManager#queryNanoApps(ContextHubInfo)} API. * * @param client the client that is associated with this callback * @param nanoAppId the ID of the nanoapp that had been loaded diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index f69a7d7e5f16..9af0e09ee97a 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -128,7 +128,8 @@ public final class ContextHubManager { public static final int AUTHORIZATION_GRANTED = 2; /** - * Constants describing the type of events from a Context Hub. + * Constants describing the type of events from a Context Hub, as defined in + * {@link ContextHubClientCallback}. * {@hide} */ @Retention(RetentionPolicy.SOURCE) diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index a5b7e995293a..6bf394dc347b 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -441,23 +441,30 @@ public class Build { public static final int CUR_DEVELOPMENT = 10000; /** - * October 2008: The original, first, version of Android. Yay! + * The original, first, version of Android. Yay! + * + * <p>Released publicly as Android 1.0 in September 2008. */ public static final int BASE = 1; /** - * February 2009: First Android update, officially called 1.1. + * First Android update. + * + * <p>Released publicly as Android 1.1 in February 2009. */ public static final int BASE_1_1 = 2; /** - * May 2009: Android 1.5. + * C. + * + * <p>Released publicly as Android 1.5 in April 2009. */ public static final int CUPCAKE = 3; /** - * September 2009: Android 1.6. + * D. * + * <p>Released publicly as Android 1.6 in September 2009. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -481,8 +488,9 @@ public class Build { public static final int DONUT = 4; /** - * November 2009: Android 2.0 + * E. * + * <p>Released publicly as Android 2.0 in October 2009. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -501,23 +509,30 @@ public class Build { public static final int ECLAIR = 5; /** - * December 2009: Android 2.0.1 + * E incremental update. + * + * <p>Released publicly as Android 2.0.1 in December 2009. */ public static final int ECLAIR_0_1 = 6; /** - * January 2010: Android 2.1 + * E MR1. + * + * <p>Released publicly as Android 2.1 in January 2010. */ public static final int ECLAIR_MR1 = 7; /** - * June 2010: Android 2.2 + * F. + * + * <p>Released publicly as Android 2.2 in May 2010. */ public static final int FROYO = 8; /** - * November 2010: Android 2.3 + * G. * + * <p>Released publicly as Android 2.3 in December 2010. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -528,13 +543,16 @@ public class Build { public static final int GINGERBREAD = 9; /** - * February 2011: Android 2.3.3. + * G MR1. + * + * <p>Released publicly as Android 2.3.3 in February 2011. */ public static final int GINGERBREAD_MR1 = 10; /** - * February 2011: Android 3.0. + * H. * + * <p>Released publicly as Android 3.0 in February 2011. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -573,13 +591,16 @@ public class Build { public static final int HONEYCOMB = 11; /** - * May 2011: Android 3.1. + * H MR1. + * + * <p>Released publicly as Android 3.1 in May 2011. */ public static final int HONEYCOMB_MR1 = 12; /** - * June 2011: Android 3.2. + * H MR2. * + * <p>Released publicly as Android 3.2 in July 2011. * <p>Update to Honeycomb MR1 to support 7 inch tablets, improve * screen compatibility mode, etc.</p> * @@ -626,8 +647,9 @@ public class Build { public static final int HONEYCOMB_MR2 = 13; /** - * October 2011: Android 4.0. + * I. * + * <p>Released publicly as Android 4.0 in October 2011. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -672,13 +694,16 @@ public class Build { public static final int ICE_CREAM_SANDWICH = 14; /** - * December 2011: Android 4.0.3. + * I MR1. + * + * <p>Released publicly as Android 4.03 in December 2011. */ public static final int ICE_CREAM_SANDWICH_MR1 = 15; /** - * June 2012: Android 4.1. + * J. * + * <p>Released publicly as Android 4.1 in July 2012. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -720,8 +745,9 @@ public class Build { public static final int JELLY_BEAN = 16; /** - * November 2012: Android 4.2, Moar jelly beans! + * J MR1. * + * <p>Released publicly as Android 4.2 in November 2012. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -740,13 +766,16 @@ public class Build { public static final int JELLY_BEAN_MR1 = 17; /** - * July 2013: Android 4.3, the revenge of the beans. + * J MR2. + * + * <p>Released publicly as Android 4.3 in July 2013. */ public static final int JELLY_BEAN_MR2 = 18; /** - * October 2013: Android 4.4, KitKat, another tasty treat. + * K. * + * <p>Released publicly as Android 4.4 in October 2013. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see the * <a href="/about/versions/kitkat/">Android KitKat overview</a>.</p> @@ -778,8 +807,9 @@ public class Build { public static final int KITKAT = 19; /** - * June 2014: Android 4.4W. KitKat for watches, snacks on the run. + * K for watches. * + * <p>Released publicly as Android 4.4W in June 2014. * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> * <ul> @@ -796,8 +826,9 @@ public class Build { public static final int L = 21; /** - * November 2014: Lollipop. A flat one with beautiful shadows. But still tasty. + * L. * + * <p>Released publicly as Android 5.0 in November 2014. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see the * <a href="/about/versions/lollipop/">Android Lollipop overview</a>.</p> @@ -828,15 +859,18 @@ public class Build { public static final int LOLLIPOP = 21; /** - * March 2015: Lollipop with an extra sugar coating on the outside! - * For more information about this release, see the + * L MR1. + * + * <p>Released publicly as Android 5.1 in March 2015. + * <p>For more information about this release, see the * <a href="/about/versions/android-5.1">Android 5.1 APIs</a>. */ public static final int LOLLIPOP_MR1 = 22; /** - * M is for Marshmallow! + * M. * + * <p>Released publicly as Android 6.0 in October 2015. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see the * <a href="/about/versions/marshmallow/">Android 6.0 Marshmallow overview</a>.</p> @@ -867,8 +901,9 @@ public class Build { public static final int M = 23; /** - * N is for Nougat. + * N. * + * <p>Released publicly as Android 7.0 in August 2016. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see * the <a href="/about/versions/nougat/">Android Nougat overview</a>.</p> @@ -921,7 +956,10 @@ public class Build { public static final int N = 24; /** - * N MR1: Nougat++. For more information about this release, see + * N MR1. + * + * <p>Released publicly as Android 7.1 in October 2016. + * <p>For more information about this release, see * <a href="/about/versions/nougat/android-7.1">Android 7.1 for * Developers</a>. */ @@ -930,6 +968,7 @@ public class Build { /** * O. * + * <p>Released publicly as Android 8.0 in August 2017. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see * the <a href="/about/versions/oreo/">Android Oreo overview</a>.</p> @@ -1020,6 +1059,7 @@ public class Build { /** * O MR1. * + * <p>Released publicly as Android 8.1 in December 2017. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see * <a href="/about/versions/oreo/android-8.1">Android 8.1 features and @@ -1037,6 +1077,7 @@ public class Build { /** * P. * + * <p>Released publicly as Android 9 in August 2018. * <p>Applications targeting this or a later release will get these * new changes in behavior. For more information about this release, see the * <a href="/about/versions/pie/">Android 9 Pie overview</a>.</p> @@ -1054,6 +1095,7 @@ public class Build { /** * Q. * + * <p>Released publicly as Android 10 in September 2019. * <p>Applications targeting this or a later release will get these new changes in behavior. * For more information about this release, see the * <a href="/about/versions/10">Android 10 overview</a>.</p> @@ -1069,6 +1111,7 @@ public class Build { /** * R. * + * <p>Released publicly as Android 11 in September 2020. * <p>Applications targeting this or a later release will get these new changes in behavior. * For more information about this release, see the * <a href="/about/versions/11">Android 11 overview</a>.</p> diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index d90e129d36f7..b4930fa931eb 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -2599,11 +2599,11 @@ public final class Debug public static native long getIonPoolsSizeKb(); /** - * Return GPU DMA buffer usage in kB or -1 on error. + * Returns the global total GPU-private memory in kB or -1 on error. * * @hide */ - public static native long getGpuDmaBufUsageKb(); + public static native long getGpuPrivateMemoryKb(); /** * Return DMA-BUF memory mapped by processes in kB. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b191dfc561aa..ac520e8b3dec 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9660,13 +9660,6 @@ public final class Settings { public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles"; /** - * Whether the Lockdown button should be shown in the power menu. - * @hide - */ - @Readable - public static final String LOCKDOWN_IN_POWER_MENU = "lockdown_in_power_menu"; - - /** * Backup manager behavioral parameters. * This is encoded as a key=value list, separated by commas. Ex: * diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index ff692818863a..ee8353a9f203 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -1969,7 +1969,17 @@ public class ZenModeConfig implements Parcelable { } public boolean isAutomaticActive() { - return enabled && !snoozing && pkg != null && isTrueOrUnknown(); + return enabled && !snoozing && getPkg() != null && isTrueOrUnknown(); + } + + public String getPkg() { + return !TextUtils.isEmpty(pkg) + ? pkg + : (component != null) + ? component.getPackageName() + : (configurationActivity != null) + ? configurationActivity.getPackageName() + : null; } public boolean isTrueOrUnknown() { diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index ad09a48cf4c3..725e20f2a74d 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -2014,7 +2014,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall return mIndex; } - /**s + /** * @return the total number of activities for which the assist data is * being returned. */ diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java index a6ec399e7d30..362ea8c87f7f 100644 --- a/core/java/android/speech/RecognitionService.java +++ b/core/java/android/speech/RecognitionService.java @@ -115,18 +115,14 @@ public abstract class RecognitionService extends Service { @NonNull AttributionSource attributionSource) { try { if (mCurrentCallback == null) { - Context attributionContext = createContext(new ContextParams.Builder() - .setNextAttributionSource(attributionSource) - .build()); boolean preflightPermissionCheckPassed = checkPermissionForPreflight( - attributionContext.getAttributionSource()); + attributionSource); if (preflightPermissionCheckPassed) { if (DBG) { Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder()); } - mCurrentCallback = new Callback(listener, attributionSource, - attributionContext); + mCurrentCallback = new Callback(listener, attributionSource); RecognitionService.this.onStartListening(intent, mCurrentCallback); } @@ -293,15 +289,8 @@ public abstract class RecognitionService extends Service { private Callback(IRecognitionListener listener, @NonNull AttributionSource attributionSource) { - this(listener, attributionSource, null); - } - - private Callback(IRecognitionListener listener, - @NonNull AttributionSource attributionSource, - @Nullable Context attributionContext) { mListener = listener; mCallingAttributionSource = attributionSource; - mAttributionContext = attributionContext; } /** diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 696271c69717..73f7543ba819 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -198,6 +198,7 @@ public class ApkSignatureVerifier { ApkSignatureSchemeV4Verifier.extractCertificates(apkPath); Certificate[][] signerCerts = new Certificate[][]{vSigner.certs}; Signature[] signerSigs = convertToSignatures(signerCerts); + Signature[] pastSignerSigs = null; if (verifyFull) { Map<Integer, byte[]> nonstreamingDigests; @@ -210,6 +211,15 @@ public class ApkSignatureVerifier { ApkSignatureSchemeV3Verifier.unsafeGetCertsWithoutVerification(apkPath); nonstreamingDigests = v3Signer.contentDigests; nonstreamingCerts = new Certificate[][]{v3Signer.certs}; + if (v3Signer.por != null) { + // populate proof-of-rotation information + pastSignerSigs = new Signature[v3Signer.por.certs.size()]; + for (int i = 0; i < pastSignerSigs.length; i++) { + pastSignerSigs[i] = new Signature( + v3Signer.por.certs.get(i).getEncoded()); + pastSignerSigs[i].setFlags(v3Signer.por.flagsList.get(i)); + } + } } catch (SignatureNotFoundException e) { try { ApkSignatureSchemeV2Verifier.VerifiedSigner v2Signer = @@ -250,7 +260,8 @@ public class ApkSignatureVerifier { } return new SigningDetailsWithDigests(new PackageParser.SigningDetails(signerSigs, - SignatureSchemeVersion.SIGNING_BLOCK_V4), vSigner.contentDigests); + SignatureSchemeVersion.SIGNING_BLOCK_V4, pastSignerSigs), + vSigner.contentDigests); } catch (SignatureNotFoundException e) { throw e; } catch (Exception e) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9450801d8d83..f4223fb467f5 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10079,9 +10079,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); - ViewStructure child = structure.newChild(i); - populateVirtualStructure(child, provider, cinfo, forAutofill); - cinfo.recycle(); + if (cinfo != null) { + ViewStructure child = structure.newChild(i); + populateVirtualStructure(child, provider, cinfo, forAutofill); + cinfo.recycle(); + } } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 280685065aaf..3550a31f9038 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1955,22 +1955,23 @@ public final class ViewRootImpl implements ViewParent, return mBoundsLayer; } - Surface getOrCreateBLASTSurface(int width, int height, - @Nullable WindowManager.LayoutParams params) { + Surface getOrCreateBLASTSurface() { if (!mSurfaceControl.isValid()) { return null; } - int format = params == null ? PixelFormat.TRANSLUCENT : params.format; Surface ret = null; if (mBlastBufferQueue == null) { - mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl, width, height, - format); + mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl, + mSurfaceSize.x, mSurfaceSize.y, + mWindowAttributes.format); // We only return the Surface the first time, as otherwise // it hasn't changed and there is no need to update. ret = mBlastBufferQueue.createSurface(); } else { - mBlastBufferQueue.update(mSurfaceControl, width, height, format); + mBlastBufferQueue.update(mSurfaceControl, + mSurfaceSize.x, mSurfaceSize.y, + mWindowAttributes.format); } return ret; @@ -7784,8 +7785,7 @@ public final class ViewRootImpl implements ViewParent, if (!useBLAST()) { mSurface.copyFrom(mSurfaceControl); } else { - final Surface blastSurface = getOrCreateBLASTSurface(mSurfaceSize.x, mSurfaceSize.y, - params); + final Surface blastSurface = getOrCreateBLASTSurface(); // If blastSurface == null that means it hasn't changed since the last time we // called. In this situation, avoid calling transferFrom as we would then // inc the generation ID and cause EGL resources to be recreated. diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java index 9c1285064afb..3df09c24ca30 100644 --- a/core/java/android/widget/AnalogClock.java +++ b/core/java/android/widget/AnalogClock.java @@ -740,8 +740,22 @@ public class AnalogClock extends View { } } - private void onTimeChanged() { - Instant now = mClock.instant(); + /** + * Return the current Instant to be used for drawing the clockface. Protected to allow + * subclasses to override this to show a different time from the system clock. + * + * @return the Instant to be shown on the clockface + * @hide + */ + protected Instant now() { + return mClock.instant(); + } + + /** + * @hide + */ + protected void onTimeChanged() { + Instant now = now(); onTimeChanged(now.atZone(mClock.getZone()).toLocalTime(), now.toEpochMilli()); } @@ -789,7 +803,7 @@ public class AnalogClock extends View { return; } - Instant now = mClock.instant(); + Instant now = now(); ZonedDateTime zonedDateTime = now.atZone(mClock.getZone()); LocalTime localTime = zonedDateTime.toLocalTime(); diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java index 472e3e72ab2f..c110ab956030 100644 --- a/core/java/android/widget/EdgeEffect.java +++ b/core/java/android/widget/EdgeEffect.java @@ -365,6 +365,10 @@ public class EdgeEffect { mDuration = PULL_TIME; mPullDistance += deltaDistance; + if (edgeEffectBehavior == TYPE_STRETCH) { + // Don't allow stretch beyond 1 + mPullDistance = Math.min(1f, mPullDistance); + } mDistance = Math.max(0f, mPullDistance); mVelocity = 0; @@ -783,6 +787,10 @@ public class EdgeEffect { + mDampedFreq * sinCoeff * Math.cos(mDampedFreq * deltaT)); mDistance = (float) distance / mHeight; mVelocity = (float) velocity; + if (mDistance > 1f) { + mDistance = 1f; + mVelocity = 0f; + } if (isAtEquilibrium()) { mDistance = 0; mVelocity = 0; diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java index 986bbc8628ec..b7f6a615a452 100644 --- a/core/java/com/android/internal/app/PlatLogoActivity.java +++ b/core/java/com/android/internal/app/PlatLogoActivity.java @@ -16,9 +16,9 @@ package com.android.internal.app; +import static android.graphics.PixelFormat.TRANSLUCENT; + import android.animation.ObjectAnimator; -import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.ActionBar; import android.app.Activity; import android.content.ActivityNotFoundException; @@ -26,22 +26,21 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.ColorFilter; -import android.graphics.LinearGradient; import android.graphics.Paint; -import android.graphics.PixelFormat; import android.graphics.Rect; -import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.provider.Settings; -import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.util.Log; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; -import android.view.animation.PathInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.OvershootInterpolator; +import android.widget.AnalogClock; import android.widget.FrameLayout; import android.widget.ImageView; @@ -49,17 +48,22 @@ import com.android.internal.R; import org.json.JSONObject; +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + /** * @hide */ public class PlatLogoActivity extends Activity { - private static final boolean WRITE_SETTINGS = true; - - private static final String R_EGG_UNLOCK_SETTING = "egg_mode_r"; + private static final String TAG = "PlatLogoActivity"; - private static final int UNLOCK_TRIES = 3; + private static final String S_EGG_UNLOCK_SETTING = "egg_mode_s"; - BigDialView mDialView; + private SettableAnalogClock mClock; + private ImageView mLogo; + private BubblesDrawable mBg; @Override protected void onPause() { @@ -69,42 +73,81 @@ public class PlatLogoActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final float dp = getResources().getDisplayMetrics().density; - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); getWindow().setNavigationBarColor(0); getWindow().setStatusBarColor(0); final ActionBar ab = getActionBar(); if (ab != null) ab.hide(); - mDialView = new BigDialView(this, null); - if (Settings.System.getLong(getContentResolver(), - R_EGG_UNLOCK_SETTING, 0) == 0) { - mDialView.setUnlockTries(UNLOCK_TRIES); - } else { - mDialView.setUnlockTries(0); - } - final FrameLayout layout = new FrameLayout(this); - layout.setBackgroundColor(0xFFFF0000); - layout.addView(mDialView, FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.MATCH_PARENT); + + mClock = new SettableAnalogClock(this); + + final DisplayMetrics dm = getResources().getDisplayMetrics(); + final float dp = dm.density; + final int minSide = Math.min(dm.widthPixels, dm.heightPixels); + final int widgetSize = (int) (minSide * 0.75); + final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(widgetSize, widgetSize); + lp.gravity = Gravity.CENTER; + layout.addView(mClock, lp); + + mLogo = new ImageView(this); + mLogo.setVisibility(View.GONE); + mLogo.setImageResource(R.drawable.platlogo); + layout.addView(mLogo, lp); + + mBg = new BubblesDrawable(); + mBg.setLevel(0); + mBg.avoid = widgetSize / 2; + mBg.padding = 0.5f * dp; + mBg.minR = 1 * dp; + layout.setBackground(mBg); + setContentView(layout); } + private boolean shouldWriteSettings() { + return getPackageName().equals("android"); + } + private void launchNextStage(boolean locked) { + mClock.animate() + .alpha(0f).scaleX(0.5f).scaleY(0.5f) + .withEndAction(() -> mClock.setVisibility(View.GONE)) + .start(); + + mLogo.setAlpha(0f); + mLogo.setScaleX(0.5f); + mLogo.setScaleY(0.5f); + mLogo.setVisibility(View.VISIBLE); + mLogo.animate() + .alpha(1f) + .scaleX(1f) + .scaleY(1f) + .setInterpolator(new OvershootInterpolator()) + .start(); + + mLogo.postDelayed(() -> { + final ObjectAnimator anim = ObjectAnimator.ofInt(mBg, "level", 0, 10000); + anim.setInterpolator(new DecelerateInterpolator(1f)); + anim.start(); + }, + 500 + ); + final ContentResolver cr = getContentResolver(); try { - if (WRITE_SETTINGS) { + if (shouldWriteSettings()) { + Log.v(TAG, "Saving egg unlock=" + locked); + syncTouchPressure(); Settings.System.putLong(cr, - R_EGG_UNLOCK_SETTING, + S_EGG_UNLOCK_SETTING, locked ? 0 : System.currentTimeMillis()); } } catch (RuntimeException e) { - Log.e("com.android.internal.app.PlatLogoActivity", "Can't write settings", e); + Log.e(TAG, "Can't write settings", e); } try { @@ -151,7 +194,7 @@ public class PlatLogoActivity extends Activity { if (mPressureMax >= 0) { touchData.put("min", mPressureMin); touchData.put("max", mPressureMax); - if (WRITE_SETTINGS) { + if (shouldWriteSettings()) { Settings.System.putString(getContentResolver(), TOUCH_STATS, touchData.toString()); } @@ -173,44 +216,35 @@ public class PlatLogoActivity extends Activity { super.onStop(); } - class BigDialView extends ImageView { - private static final int COLOR_GREEN = 0xff3ddc84; - private static final int COLOR_BLUE = 0xff4285f4; - private static final int COLOR_NAVY = 0xff073042; - private static final int COLOR_ORANGE = 0xfff86734; - private static final int COLOR_CHARTREUSE = 0xffeff7cf; - private static final int COLOR_LIGHTBLUE = 0xffd7effe; - - private static final int STEPS = 11; - private static final float VALUE_CHANGE_MAX = 1f / STEPS; - - private BigDialDrawable mDialDrawable; - private boolean mWasLocked; - - BigDialView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - init(); - } - - BigDialView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - BigDialView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); - } + /** + * Subclass of AnalogClock that allows the user to flip up the glass and adjust the hands. + */ + public class SettableAnalogClock extends AnalogClock { + private int mOverrideHour = -1; + private int mOverrideMinute = -1; + private boolean mOverride = false; - private void init() { - mDialDrawable = new BigDialDrawable(); - setImageDrawable(mDialDrawable); + public SettableAnalogClock(Context context) { + super(context); } @Override - public void onDraw(Canvas c) { - super.onDraw(c); + protected Instant now() { + final Instant realNow = super.now(); + final ZoneId tz = Clock.systemDefaultZone().getZone(); + final ZonedDateTime zdTime = realNow.atZone(tz); + if (mOverride) { + if (mOverrideHour < 0) { + mOverrideHour = zdTime.getHour(); + } + return Clock.fixed(zdTime + .withHour(mOverrideHour) + .withMinute(mOverrideMinute) + .withSecond(0) + .toInstant(), tz).instant(); + } else { + return realNow; + } } double toPositiveDegrees(double rad) { @@ -221,226 +255,174 @@ public class PlatLogoActivity extends Activity { public boolean onTouchEvent(MotionEvent ev) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: - mWasLocked = mDialDrawable.isLocked(); + mOverride = true; // pass through case MotionEvent.ACTION_MOVE: + measureTouchPressure(ev); + float x = ev.getX(); float y = ev.getY(); - float cx = (getLeft() + getRight()) / 2f; - float cy = (getTop() + getBottom()) / 2f; + float cx = getWidth() / 2f; + float cy = getHeight() / 2f; float angle = (float) toPositiveDegrees(Math.atan2(x - cx, y - cy)); - final int oldLevel = mDialDrawable.getUserLevel(); - mDialDrawable.touchAngle(angle); - final int newLevel = mDialDrawable.getUserLevel(); - if (oldLevel != newLevel) { - performHapticFeedback(newLevel == STEPS - ? HapticFeedbackConstants.CONFIRM - : HapticFeedbackConstants.CLOCK_TICK); + + int minutes = (75 - (int) (angle / 6)) % 60; + int minuteDelta = minutes - mOverrideMinute; + if (minuteDelta != 0) { + if (Math.abs(minuteDelta) > 45 && mOverrideHour >= 0) { + int hourDelta = (minuteDelta < 0) ? 1 : -1; + mOverrideHour = (mOverrideHour + 24 + hourDelta) % 24; + } + mOverrideMinute = minutes; + if (mOverrideMinute == 0) { + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (getScaleX() == 1f) { + setScaleX(1.05f); + setScaleY(1.05f); + animate().scaleX(1f).scaleY(1f).setDuration(150).start(); + } + } else { + performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + } + + onTimeChanged(); + postInvalidate(); } + return true; case MotionEvent.ACTION_UP: - if (mWasLocked != mDialDrawable.isLocked()) { - launchNextStage(mDialDrawable.isLocked()); + if (mOverrideMinute == 0 && (mOverrideHour % 12) == 0) { + Log.v(TAG, "12:00 let's gooooo"); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + launchNextStage(false); } return true; } return false; } + } - @Override - public boolean performClick() { - if (mDialDrawable.getUserLevel() < STEPS - 1) { - mDialDrawable.setUserLevel(mDialDrawable.getUserLevel() + 1); - performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - } - return true; - } - - void setUnlockTries(int tries) { - mDialDrawable.setUnlockTries(tries); - } + static class Bubble { + public float x, y, r; + public int color; + } - private class BigDialDrawable extends Drawable { - public final int STEPS = 10; - private int mUnlockTries = 0; - final Paint mPaint = new Paint(); - final Drawable mEleven; - private boolean mNightMode; - private float mValue = 0f; - float mElevenAnim = 0f; - ObjectAnimator mElevenShowAnimator = ObjectAnimator.ofFloat(this, "elevenAnim", 0f, - 1f).setDuration(300); - ObjectAnimator mElevenHideAnimator = ObjectAnimator.ofFloat(this, "elevenAnim", 1f, - 0f).setDuration(500); - - BigDialDrawable() { - mNightMode = getContext().getResources().getConfiguration().isNightModeActive(); - mEleven = getContext().getDrawable(R.drawable.ic_number11); - mElevenShowAnimator.setInterpolator(new PathInterpolator(0.4f, 0f, 0.2f, 1f)); - mElevenHideAnimator.setInterpolator(new PathInterpolator(0.8f, 0.2f, 0.6f, 1f)); - } + class BubblesDrawable extends Drawable { + private static final int MAX_BUBBS = 2000; - public void setUnlockTries(int count) { - if (mUnlockTries != count) { - mUnlockTries = count; - setValue(getValue()); - invalidateSelf(); - } - } + private final int[] mColorIds = { + android.R.color.system_accent1_400, + android.R.color.system_accent1_500, + android.R.color.system_accent1_600, - boolean isLocked() { - return mUnlockTries > 0; - } + android.R.color.system_accent2_400, + android.R.color.system_accent2_500, + android.R.color.system_accent2_600, + }; - public void setValue(float v) { - // until the dial is "unlocked", you can't turn it all the way to 11 - final float max = isLocked() ? 1f - 1f / STEPS : 1f; - mValue = v < 0f ? 0f : v > max ? max : v; - invalidateSelf(); - } + private int[] mColors = new int[mColorIds.length]; - public float getValue() { - return mValue; - } + private final Bubble[] mBubbs = new Bubble[MAX_BUBBS]; + private int mNumBubbs; - public int getUserLevel() { - return Math.round(getValue() * STEPS - 0.25f); - } + private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - public void setUserLevel(int i) { - setValue(getValue() + ((float) i) / STEPS); - } + public float avoid = 0f; + public float padding = 0f; + public float minR = 0f; - public float getElevenAnim() { - return mElevenAnim; + BubblesDrawable() { + for (int i = 0; i < mColorIds.length; i++) { + mColors[i] = getColor(mColorIds[i]); } - - public void setElevenAnim(float f) { - if (mElevenAnim != f) { - mElevenAnim = f; - invalidateSelf(); - } + for (int j = 0; j < mBubbs.length; j++) { + mBubbs[j] = new Bubble(); } + } - @Override - public void draw(@NonNull Canvas canvas) { - final Rect bounds = getBounds(); - final int w = bounds.width(); - final int h = bounds.height(); - final float w2 = w / 2f; - final float h2 = h / 2f; - final float radius = w / 4f; - - canvas.drawColor(mNightMode ? COLOR_NAVY : COLOR_LIGHTBLUE); - - canvas.save(); - canvas.rotate(45, w2, h2); - canvas.clipRect(w2, h2 - radius, Math.min(w, h), h2 + radius); - final int gradientColor = mNightMode ? 0x60000020 : (0x10FFFFFF & COLOR_NAVY); - mPaint.setShader( - new LinearGradient(w2, h2, Math.min(w, h), h2, gradientColor, - 0x00FFFFFF & gradientColor, Shader.TileMode.CLAMP)); - mPaint.setColor(Color.BLACK); - canvas.drawPaint(mPaint); - mPaint.setShader(null); - canvas.restore(); - - mPaint.setStyle(Paint.Style.FILL); - mPaint.setColor(COLOR_GREEN); - - canvas.drawCircle(w2, h2, radius, mPaint); - - mPaint.setColor(mNightMode ? COLOR_LIGHTBLUE : COLOR_NAVY); - final float cx = w * 0.85f; - for (int i = 0; i < STEPS; i++) { - final float f = (float) i / STEPS; - canvas.save(); - final float angle = valueToAngle(f); - canvas.rotate(-angle, w2, h2); - canvas.drawCircle(cx, h2, (i <= getUserLevel()) ? 20 : 5, mPaint); - canvas.restore(); - } - - if (mElevenAnim > 0f) { - final int color = COLOR_ORANGE; - final int size2 = (int) ((0.5 + 0.5f * mElevenAnim) * w / 14); - final float cx11 = cx + size2 / 4f; - mEleven.setBounds((int) cx11 - size2, (int) h2 - size2, - (int) cx11 + size2, (int) h2 + size2); - final int alpha = 0xFFFFFF | ((int) clamp(0xFF * 2 * mElevenAnim, 0, 0xFF) - << 24); - mEleven.setTint(alpha & color); - mEleven.draw(canvas); - } - - // don't want to use the rounded value here since the quantization will be visible - final float angle = valueToAngle(mValue); - - // it's easier to draw at far-right and rotate backwards - canvas.rotate(-angle, w2, h2); - mPaint.setColor(Color.WHITE); - final float dimple = w2 / 12f; - canvas.drawCircle(w - radius - dimple * 2, h2, dimple, mPaint); + @Override + public void draw(Canvas canvas) { + final float f = getLevel() / 10000f; + mPaint.setStyle(Paint.Style.FILL); + int drawn = 0; + for (int j = 0; j < mNumBubbs; j++) { + if (mBubbs[j].color == 0 || mBubbs[j].r == 0) continue; + mPaint.setColor(mBubbs[j].color); + canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint); + drawn++; } + } - float clamp(float x, float a, float b) { - return x < a ? a : x > b ? b : x; - } + @Override + protected boolean onLevelChange(int level) { + invalidateSelf(); + return true; + } - float angleToValue(float a) { - return 1f - clamp(a / (360 - 45), 0f, 1f); - } + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + randomize(); + } - // rotation: min is at 4:30, max is at 3:00 - float valueToAngle(float v) { - return (1f - v) * (360 - 45); + private void randomize() { + final float w = getBounds().width(); + final float h = getBounds().height(); + final float maxR = Math.min(w, h) / 3f; + mNumBubbs = 0; + if (avoid > 0f) { + mBubbs[mNumBubbs].x = w / 2f; + mBubbs[mNumBubbs].y = h / 2f; + mBubbs[mNumBubbs].r = avoid; + mBubbs[mNumBubbs].color = 0; + mNumBubbs++; } - - public void touchAngle(float a) { - final int oldUserLevel = getUserLevel(); - final float newValue = angleToValue(a); - // this is how we prevent the knob from snapping from max back to min, or from - // jumping around wherever the user presses. The new value must be pretty close - // to the - // previous one. - if (Math.abs(newValue - getValue()) < VALUE_CHANGE_MAX) { - setValue(newValue); - - if (isLocked() && oldUserLevel != STEPS - 1 && getUserLevel() == STEPS - 1) { - mUnlockTries--; - } else if (!isLocked() && getUserLevel() == 0) { - mUnlockTries = UNLOCK_TRIES; + for (int j = 0; j < MAX_BUBBS; j++) { + // a simple but time-tested bubble-packing algorithm: + // 1. pick a spot + // 2. shrink the bubble until it is no longer overlapping any other bubble + // 3. if the bubble hasn't popped, keep it + int tries = 5; + while (tries-- > 0) { + float x = (float) Math.random() * w; + float y = (float) Math.random() * h; + float r = Math.min(Math.min(x, w - x), Math.min(y, h - y)); + + // shrink radius to fit other bubbs + for (int i = 0; i < mNumBubbs; i++) { + r = (float) Math.min(r, + Math.hypot(x - mBubbs[i].x, y - mBubbs[i].y) - mBubbs[i].r + - padding); + if (r < minR) break; } - if (!isLocked()) { - if (getUserLevel() == STEPS && mElevenAnim != 1f - && !mElevenShowAnimator.isRunning()) { - mElevenHideAnimator.cancel(); - mElevenShowAnimator.start(); - } else if (getUserLevel() != STEPS && mElevenAnim == 1f - && !mElevenHideAnimator.isRunning()) { - mElevenShowAnimator.cancel(); - mElevenHideAnimator.start(); - } + if (r >= minR) { + // we have found a spot for this bubble to live, let's save it and move on + r = Math.min(maxR, r); + + mBubbs[mNumBubbs].x = x; + mBubbs[mNumBubbs].y = y; + mBubbs[mNumBubbs].r = r; + mBubbs[mNumBubbs].color = mColors[(int) (Math.random() * mColors.length)]; + mNumBubbs++; + break; } } } + Log.v(TAG, String.format("successfully placed %d bubbles (%d%%)", + mNumBubbs, (int) (100f * mNumBubbs / MAX_BUBBS))); + } - @Override - public void setAlpha(int i) { - } + @Override + public void setAlpha(int alpha) { } - @Override - public void setColorFilter(@Nullable ColorFilter colorFilter) { - } + @Override + public void setColorFilter(ColorFilter colorFilter) { } - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } + @Override + public int getOpacity() { + return TRANSLUCENT; } } -} - - +} diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index a68a007dad56..8c63f38494ea 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1106,8 +1106,9 @@ public class BatteryStatsImpl extends BatteryStats { @VisibleForTesting protected PowerProfile mPowerProfile; + @VisibleForTesting @GuardedBy("this") - final Constants mConstants; + protected final Constants mConstants; /* * Holds a SamplingTimer associated with each Resource Power Manager state and voter, diff --git a/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java b/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java new file mode 100644 index 000000000000..481183e700a2 --- /dev/null +++ b/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import android.annotation.Nullable; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RemoteViews; + +import java.util.LinkedList; +import java.util.List; + +/** + * This is a subclass of LinearLayout meant to be used in the Conversation header, to fix a bug + * when multiple user-provided strings are shown in the same conversation header. b/189723284 + * + * This works around a deficiency in LinearLayout when shrinking views that it can't fully reduce + * all contents if any of the oversized views reaches zero. + */ +@RemoteViews.RemoteView +public class ConversationHeaderLinearLayout extends LinearLayout { + + public ConversationHeaderLinearLayout(Context context) { + super(context); + } + + public ConversationHeaderLinearLayout(Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ConversationHeaderLinearLayout(Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + private int calculateTotalChildLength() { + final int count = getChildCount(); + int totalLength = 0; + + for (int i = 0; i < count; ++i) { + final View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE) { + continue; + } + final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) + child.getLayoutParams(); + totalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; + } + return totalLength + getPaddingLeft() + getPaddingRight(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + final int containerWidth = getMeasuredWidth(); + final int contentsWidth = calculateTotalChildLength(); + + int excessContents = contentsWidth - containerWidth; + if (excessContents <= 0) { + return; + } + final int count = getChildCount(); + + float remainingWeight = 0; + List<ViewInfo> visibleChildrenToShorten = null; + + // Find children which need to be shortened in order to ensure the contents fit. + for (int i = 0; i < count; ++i) { + final View child = getChildAt(i); + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + final float weight = ((LayoutParams) child.getLayoutParams()).weight; + if (weight == 0) { + continue; + } + if (child.getMeasuredWidth() == 0) { + continue; + } + if (visibleChildrenToShorten == null) { + visibleChildrenToShorten = new LinkedList<>(); + } + visibleChildrenToShorten.add(new ViewInfo(child)); + remainingWeight += Math.max(0, weight); + } + if (visibleChildrenToShorten == null || visibleChildrenToShorten.isEmpty()) { + return; + } + balanceViewWidths(visibleChildrenToShorten, remainingWeight, excessContents); + remeasureChangedChildren(visibleChildrenToShorten); + } + + /** + * Measure any child with a width that has changed. + */ + private void remeasureChangedChildren(List<ViewInfo> childrenInfo) { + for (ViewInfo info : childrenInfo) { + if (info.mWidth != info.mStartWidth) { + final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + Math.max(0, info.mWidth), MeasureSpec.EXACTLY); + final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + info.mView.getMeasuredHeight(), MeasureSpec.EXACTLY); + info.mView.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + } + + /** + * Given a list of view, use the weights to remove width from each view proportionally to the + * weight (and ignoring the view's actual width), but do this iteratively whenever a view is + * reduced to zero width, because in that case other views need reduction. + */ + void balanceViewWidths(List<ViewInfo> viewInfos, float weightSum, int excessContents) { + boolean performAnotherPass = true; + // Loops only when all of the following are true: + // * `performAnotherPass` -- a view clamped to 0 width (or the first iteration) + // * `excessContents > 0` -- there is still horizontal space to allocate + // * `weightSum > 0` -- at least 1 view with nonzero width AND nonzero weight left + while (performAnotherPass && excessContents > 0 && weightSum > 0) { + int excessRemovedDuringThisPass = 0; + float weightSumForNextPass = 0; + performAnotherPass = false; + for (ViewInfo info : viewInfos) { + if (info.mWeight <= 0) { + continue; + } + if (info.mWidth <= 0) { + continue; + } + int newWidth = (int) (info.mWidth - (excessContents * (info.mWeight / weightSum))); + if (newWidth < 0) { + newWidth = 0; + performAnotherPass = true; + } + excessRemovedDuringThisPass += info.mWidth - newWidth; + info.mWidth = newWidth; + if (info.mWidth > 0) { + weightSumForNextPass += info.mWeight; + } + } + excessContents -= excessRemovedDuringThisPass; + weightSum = weightSumForNextPass; + } + } + + /** + * A helper class for measuring children. + */ + static class ViewInfo { + final View mView; + final float mWeight; + final int mStartWidth; + int mWidth; + + ViewInfo(View view) { + this.mView = view; + this.mWeight = ((LayoutParams) view.getLayoutParams()).weight; + this.mStartWidth = this.mWidth = view.getMeasuredWidth(); + } + } +} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 125182cab254..91a19e087bf1 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -237,7 +237,6 @@ cc_library_shared { ], shared_libs: [ - "android.hardware.memtrack-V1-ndk_platform", "audioclient-types-aidl-cpp", "audioflinger-aidl-cpp", "av-types-aidl-cpp", diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 41804480122c..4c2b114c724a 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -33,7 +33,6 @@ #include <string> #include <vector> -#include <aidl/android/hardware/memtrack/DeviceInfo.h> #include <android-base/logging.h> #include <bionic/malloc.h> #include <debuggerd/client.h> @@ -46,7 +45,6 @@ #include "jni.h" #include <dmabufinfo/dmabuf_sysfs_stats.h> #include <dmabufinfo/dmabufinfo.h> -#include <dmabufinfo/dmabuf_sysfs_stats.h> #include <meminfo/procmeminfo.h> #include <meminfo/sysmeminfo.h> #include <memtrack/memtrack.h> @@ -861,29 +859,24 @@ static jlong android_os_Debug_getDmabufHeapPoolsSizeKb(JNIEnv* env, jobject claz return poolsSizeKb; } -static jlong android_os_Debug_getGpuDmaBufUsageKb(JNIEnv* env, jobject clazz) { - std::vector<aidl::android::hardware::memtrack::DeviceInfo> gpu_device_info; - if (!memtrack_gpu_device_info(&gpu_device_info)) { +static jlong android_os_Debug_getGpuPrivateMemoryKb(JNIEnv* env, jobject clazz) { + struct memtrack_proc* p = memtrack_proc_new(); + if (p == nullptr) { + LOG(ERROR) << "getGpuPrivateMemoryKb: Failed to create memtrack_proc"; return -1; } - dmabufinfo::DmabufSysfsStats stats; - if (!GetDmabufSysfsStats(&stats)) { + // Memtrack hal defines PID 0 as global total for GPU-private (GL) memory. + if (memtrack_proc_get(p, 0) != 0) { + // The memtrack HAL may not be available, avoid flooding the log. + memtrack_proc_destroy(p); return -1; } - jlong sizeKb = 0; - const auto& importer_stats = stats.importer_info(); - for (const auto& dev_info : gpu_device_info) { - const auto& importer_info = importer_stats.find(dev_info.name); - if (importer_info == importer_stats.end()) { - continue; - } - - sizeKb += importer_info->second.size / 1024; - } + ssize_t gpuPrivateMem = memtrack_proc_gl_pss(p); - return sizeKb; + memtrack_proc_destroy(p); + return gpuPrivateMem / 1024; } static jlong android_os_Debug_getDmabufMappedSizeKb(JNIEnv* env, jobject clazz) { @@ -994,8 +987,8 @@ static const JNINativeMethod gMethods[] = { (void*)android_os_Debug_getIonHeapsSizeKb }, { "getDmabufTotalExportedKb", "()J", (void*)android_os_Debug_getDmabufTotalExportedKb }, - { "getGpuDmaBufUsageKb", "()J", - (void*)android_os_Debug_getGpuDmaBufUsageKb }, + { "getGpuPrivateMemoryKb", "()J", + (void*)android_os_Debug_getGpuPrivateMemoryKb }, { "getDmabufHeapTotalExportedKb", "()J", (void*)android_os_Debug_getDmabufHeapTotalExportedKb }, { "getIonPoolsSizeKb", "()J", diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7b97902da0b1..4dec0ffccb5e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5902,8 +5902,8 @@ android:process=":ui"> </activity> <activity android:name="com.android.internal.app.PlatLogoActivity" - android:theme="@style/Theme.DeviceDefault.DayNight" - android:configChanges="orientation|keyboardHidden" + android:theme="@style/Theme.DeviceDefault.Wallpaper.NoTitleBar" + android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" android:icon="@drawable/platlogo" android:process=":ui"> </activity> diff --git a/core/res/res/drawable-hdpi/clock_dial.png b/core/res/res/drawable-hdpi/clock_dial.png Binary files differdeleted file mode 100644 index 9de29bc0e53e..000000000000 --- a/core/res/res/drawable-hdpi/clock_dial.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/clock_hand_hour.png b/core/res/res/drawable-hdpi/clock_hand_hour.png Binary files differdeleted file mode 100644 index 9f7e5c02d49c..000000000000 --- a/core/res/res/drawable-hdpi/clock_hand_hour.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/clock_hand_minute.png b/core/res/res/drawable-hdpi/clock_hand_minute.png Binary files differdeleted file mode 100644 index 2eec38060c45..000000000000 --- a/core/res/res/drawable-hdpi/clock_hand_minute.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/clock_dial.png b/core/res/res/drawable-ldpi/clock_dial.png Binary files differdeleted file mode 100644 index cbc996185cc7..000000000000 --- a/core/res/res/drawable-ldpi/clock_dial.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/clock_hand_hour.png b/core/res/res/drawable-ldpi/clock_hand_hour.png Binary files differdeleted file mode 100644 index 3362fd0775d5..000000000000 --- a/core/res/res/drawable-ldpi/clock_hand_hour.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/clock_hand_minute.png b/core/res/res/drawable-ldpi/clock_hand_minute.png Binary files differdeleted file mode 100644 index 5c73d45ada5c..000000000000 --- a/core/res/res/drawable-ldpi/clock_hand_minute.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/clock_dial.png b/core/res/res/drawable-mdpi/clock_dial.png Binary files differdeleted file mode 100644 index 82f73fec0423..000000000000 --- a/core/res/res/drawable-mdpi/clock_dial.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/clock_hand_hour.png b/core/res/res/drawable-mdpi/clock_hand_hour.png Binary files differdeleted file mode 100644 index 1f0aec80ba14..000000000000 --- a/core/res/res/drawable-mdpi/clock_hand_hour.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/clock_hand_minute.png b/core/res/res/drawable-mdpi/clock_hand_minute.png Binary files differdeleted file mode 100644 index 6cd8a4bfa48d..000000000000 --- a/core/res/res/drawable-mdpi/clock_hand_minute.png +++ /dev/null diff --git a/core/res/res/drawable-nodpi/clock_dial.xml b/core/res/res/drawable-nodpi/clock_dial.xml new file mode 100644 index 000000000000..5263218ef880 --- /dev/null +++ b/core/res/res/drawable-nodpi/clock_dial.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="380dp" + android:height="380dp" + android:viewportWidth="380" + android:viewportHeight="380"> + <path + android:pathData="M177.389,2.803C185.381,-0.934 194.619,-0.934 202.611,2.803L231.193,16.169C234.358,17.649 237.76,18.56 241.242,18.861L272.677,21.577C281.467,22.336 289.468,26.956 294.52,34.188L312.59,60.054C314.591,62.919 317.081,65.409 319.946,67.41L345.812,85.48C353.044,90.533 357.664,98.533 358.423,107.323L361.139,138.758C361.44,142.24 362.351,145.642 363.832,148.807L377.197,177.389C380.934,185.381 380.934,194.619 377.197,202.611L363.832,231.193C362.351,234.359 361.44,237.76 361.139,241.242L358.423,272.677C357.664,281.467 353.044,289.468 345.812,294.52L319.946,312.59C317.081,314.591 314.591,317.081 312.59,319.946L294.52,345.812C289.468,353.044 281.467,357.664 272.677,358.423L241.242,361.139C237.76,361.44 234.359,362.351 231.193,363.832L202.611,377.197C194.619,380.934 185.381,380.934 177.389,377.197L148.807,363.832C145.642,362.351 142.24,361.44 138.758,361.139L107.323,358.423C98.533,357.664 90.533,353.044 85.48,345.812L67.41,319.946C65.409,317.081 62.919,314.591 60.054,312.59L34.188,294.52C26.956,289.468 22.336,281.467 21.577,272.677L18.861,241.242C18.56,237.76 17.649,234.359 16.169,231.193L2.803,202.611C-0.934,194.619 -0.934,185.381 2.803,177.389L16.169,148.807C17.649,145.642 18.56,142.24 18.861,138.758L21.577,107.323C22.336,98.533 26.956,90.533 34.188,85.48L60.054,67.41C62.919,65.409 65.409,62.919 67.41,60.054L85.48,34.188C90.533,26.956 98.533,22.336 107.323,21.577L138.758,18.861C142.24,18.56 145.642,17.649 148.807,16.169L177.389,2.803Z" + android:fillColor="@color/system_neutral1_200"/> +</vector> diff --git a/core/res/res/drawable-nodpi/clock_hand_hour.xml b/core/res/res/drawable-nodpi/clock_hand_hour.xml new file mode 100644 index 000000000000..de165a429a57 --- /dev/null +++ b/core/res/res/drawable-nodpi/clock_hand_hour.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="380dp" + android:height="380dp" + android:viewportWidth="380" + android:viewportHeight="380"> + <path + android:pathData="M190,96L190,96A16,16 0,0 1,206 112L206,190A16,16 0,0 1,190 206L190,206A16,16 0,0 1,174 190L174,112A16,16 0,0 1,190 96z" + android:fillColor="@color/system_accent1_700"/> +</vector> diff --git a/core/res/res/drawable-nodpi/clock_hand_minute.xml b/core/res/res/drawable-nodpi/clock_hand_minute.xml new file mode 100644 index 000000000000..72cac6e88597 --- /dev/null +++ b/core/res/res/drawable-nodpi/clock_hand_minute.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="380dp" + android:height="380dp" + android:viewportWidth="380" + android:viewportHeight="380"> + <path + android:pathData="M190,60L190,60A16,16 0,0 1,206 76L206,190A16,16 0,0 1,190 206L190,206A16,16 0,0 1,174 190L174,76A16,16 0,0 1,190 60z" + android:fillColor="@color/system_accent2_500"/> +</vector> diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml index b01eb3944b50..1d67570cf485 100644 --- a/core/res/res/drawable-nodpi/platlogo.xml +++ b/core/res/res/drawable-nodpi/platlogo.xml @@ -1,50 +1,36 @@ +<!-- +Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="512dp" - android:height="512dp" - android:viewportWidth="512" - android:viewportHeight="512"> - <path - android:fillColor="#F86734" - android:pathData="M416.23 236.62h-10.67c-1.46 0-2.65-1.19-2.65-2.65v-9.85c0-1.47 1.19-2.65 2.65-2.65h23.37c1.47 0 2.66 1.19 2.66 2.65v66.9c0 1.46-1.2 2.65-2.66 2.65H418.9c-1.47 0-2.66-1.19-2.66-2.65v-54.4z"/> - <path - android:fillColor="#F86734" - android:pathData="M455.51 236.62h-10.67c-1.47 0-2.65-1.19-2.65-2.65v-9.85c0-1.47 1.18-2.65 2.65-2.65h23.37c1.47 0 2.66 1.19 2.66 2.65v66.9c0 1.46-1.2 2.65-2.66 2.65h-10.05c-1.46 0-2.65-1.19-2.65-2.65v-54.4z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M364.12 400.25a4.34 4.34 0 1 0 0 8.68a4.34 4.34 0 1 0 0-8.68z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M275.46 433.53a4.84 4.84 0 1 0 0 9.68a4.84 4.84 0 1 0 0-9.68z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M184.52 418.83a5.36 5.36 0 1 0 0 10.72a5.36 5.36 0 1 0 0-10.72z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M110.42 359.19a5.89 5.89 0 1 0 0 11.78a5.89 5.89 0 1 0 0-11.78z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M75.94 270.17a6.43 6.43 0 1 0 0 12.86a6.43 6.43 0 1 0 0-12.86z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M89.48 178.57a6.98 6.98 0 1 0 0 13.96a6.98 6.98 0 1 0 0-13.96z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M147.97 103.54a7.54 7.54 0 1 0 0 15.08a7.54 7.54 0 1 0 0-15.08z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M236.63 66.7a8.1 8.1 0 1 0 0 16.2a8.1 8.1 0 1 0 0-16.2z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M327.09 78.3a8.66 8.66 0 1 0 0 17.32a8.66 8.66 0 1 0 0-17.32z"/> - <path - android:fillColor="#D6F0FF" - android:pathData="M401.05 136.97a9.22 9.22 0 1 0 0 18.44a9.22 9.22 0 1 0 0-18.44z"/> - <group> - <path - android:fillColor="#3DDB85" - android:pathData="M255.45 129.46a128.11 128.11 0 1 0 0 256.22a128.11 128.11 0 1 0 0-256.22z"/> - <path - android:fillColor="#FFF" - android:pathData="M339.23 236.09a21.48 21.48 0 1 0 0 42.96a21.48 21.48 0 1 0 0-42.96z"/> - </group> + android:width="128dp" + android:height="128dp" + android:viewportWidth="128" + android:viewportHeight="128"> + <path + android:pathData="M64,64m-64,0a64,64 0,1 1,128 0a64,64 0,1 1,-128 0" + android:fillColor="@android:color/system_accent3_500"/> + <path + android:pathData="M32.5,34.15a10,10 0,0 1,9.94 10V93.85" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#fff" + android:strokeLineCap="round"/> + <path + android:pathData="M95.5,93.85H55.71V83.9A19.9,19.9 0,0 1,75.61 64h10a9.94,9.94 0,0 0,9.94 -10,19.9 19.9,0 0,0 -38.69,-6.56A20.77,20.77 0,0 0,56 50.73" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#fff" + android:strokeLineCap="round"/> </vector> diff --git a/core/res/res/drawable-xhdpi/clock_dial.png b/core/res/res/drawable-xhdpi/clock_dial.png Binary files differdeleted file mode 100644 index 6cb60a296ed8..000000000000 --- a/core/res/res/drawable-xhdpi/clock_dial.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/clock_hand_hour.png b/core/res/res/drawable-xhdpi/clock_hand_hour.png Binary files differdeleted file mode 100644 index bc0c5bd4d59f..000000000000 --- a/core/res/res/drawable-xhdpi/clock_hand_hour.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/clock_hand_minute.png b/core/res/res/drawable-xhdpi/clock_hand_minute.png Binary files differdeleted file mode 100644 index 01d611fbbdcd..000000000000 --- a/core/res/res/drawable-xhdpi/clock_hand_minute.png +++ /dev/null diff --git a/core/res/res/drawable/ic_lock.xml b/core/res/res/drawable/ic_lock.xml index 7582d5f82c1d..c30f96330378 100644 --- a/core/res/res/drawable/ic_lock.xml +++ b/core/res/res/drawable/ic_lock.xml @@ -14,14 +14,23 @@ Copyright (C) 2019 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="32.0" - android:viewportHeight="32.0"> + android:width="26dp" + android:height="36dp" + android:viewportWidth="26" + android:viewportHeight="36"> <path android:fillColor="#FF000000" - android:pathData="M16,20m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/> + android:pathData="M13.75 27.5 C15.13,27.5 16.25,26.38 16.25,25 C16.25,23.62 15.13,22.5 13.75,22.5 C12.37,22.5 11.25,23.62 11.25,25 C11.25,26.38 12.37,27.5 13.75,27.5c " /> <path - android:fillColor="#FF000000" - android:pathData="M24,11h-2.3V7.3c0,-3.1 -2.5,-5.7 -5.7,-5.7c-3.1,0 -5.7,2.5 -5.7,5.7V11H8c-1.3,0 -2.3,1 -2.3,2.3v13.3c0,1.3 1,2.3 2.3,2.3h16c1.3,0 2.3,-1 2.3,-2.3V13.3C26.3,12 25.3,11 24,11zM12.3,7.3c0,-2 1.6,-3.7 3.7,-3.7c2,0 3.7,1.6 3.7,3.7V11h-7.3V7.3zM24.3,26.7c0,0.2 -0.1,0.3 -0.3,0.3H8c-0.2,0 -0.3,-0.1 -0.3,-0.3V13.3C7.7,13.1 7.8,13 8,13h16c0.2,0 0.3,0.1 0.3,0.3V26.7z"/> + android:strokeColor="#FF000000" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2.5" + android:pathData="M4.5 15 C4.5,15 23,15 23,15 C24.1,15 25,15.9 25,17 C25,17 25,33 25,33 C25,34.1 24.1,35 23,35 C23,35 4.5,35 4.5,35 C3.4,35 2.5,34.1 2.5,33 C2.5,33 2.5,17 2.5,17 C2.5,15.9 3.4,15 4.5,15c " /> + <path + android:strokeColor="#FF000000" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2.5" + android:pathData="M7.5 15 C7.5,15 7.5,8.61 7.5,8.61 C7.5,5.24 10.3,2.5 13.75,2.5 C17.2,2.5 20,5.24 20,8.61 C20,8.61 20,15 20,15 " /> </vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_lock_open.xml b/core/res/res/drawable/ic_lock_open.xml index e0deb598b1b1..abe6ddebb845 100644 --- a/core/res/res/drawable/ic_lock_open.xml +++ b/core/res/res/drawable/ic_lock_open.xml @@ -14,14 +14,23 @@ Copyright (C) 2019 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="32.0" - android:viewportHeight="32.0"> + android:height="36dp" + android:width="34dp" + android:viewportHeight="36" + android:viewportWidth="34"> <path android:fillColor="#FF000000" - android:pathData="M16,20m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/> + android:pathData="M13.75 27.5 C15.13,27.5 16.25,26.38 16.25,25 C16.25,23.62 15.13,22.5 13.75,22.5 C12.37,22.5 11.25,23.62 11.25,25 C11.25,26.38 12.37,27.5 13.75,27.5c " /> <path - android:fillColor="#FF000000" - android:pathData="M25.3,1.7c-3.1,0 -5.7,2.5 -5.7,5.7V11H8c-1.3,0 -2.3,1 -2.3,2.3v13.3c0,1.3 1,2.3 2.3,2.3h16c1.3,0 2.3,-1 2.3,-2.3V13.3c0,-1.3 -1,-2.3 -2.3,-2.3h-2.3V7.3c0,-2 1.6,-3.7 3.7,-3.7c2,0 3.7,1.6 3.7,3.7V8h2V7.3C31,4.2 28.5,1.7 25.3,1.7zM24.3,13.3v13.3c0,0.2 -0.1,0.3 -0.3,0.3H8c-0.2,0 -0.3,-0.1 -0.3,-0.3V13.3C7.7,13.1 7.8,13 8,13h16C24.2,13 24.3,13.1 24.3,13.3z"/> + android:strokeColor="#FF000000" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2.5" + android:pathData=" M4.5 15 C4.5,15 23,15 23,15 C24.1,15 25,15.9 25,17 C25,17 25,33 25,33 C25,34.1 24.1,35 23,35 C23,35 4.5,35 4.5,35 C3.4,35 2.5,34.1 2.5,33 C2.5,33 2.5,17 2.5,17 C2.5,15.9 3.4,15 4.5,15c " /> + <path + android:strokeColor="#FF000000" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2.5" + android:pathData="M20 15 C20,15 20,8.61 20,8.61 C20,5.24 22.8,2.5 26.25,2.5 C29.7,2.5 32.5,5.24 32.5,8.61 C32.5,8.61 32.5,15 32.5,15 " /> </vector>
\ No newline at end of file diff --git a/core/res/res/layout/notification_template_conversation_header.xml b/core/res/res/layout/notification_template_conversation_header.xml index 389637eb2517..eec49fe97b9d 100644 --- a/core/res/res/layout/notification_template_conversation_header.xml +++ b/core/res/res/layout/notification_template_conversation_header.xml @@ -14,7 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<LinearLayout +<com.android.internal.widget.ConversationHeaderLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/conversation_header" android:layout_width="wrap_content" @@ -27,7 +27,6 @@ android:id="@+id/conversation_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin" android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title" android:textSize="16sp" android:singleLine="true" @@ -40,7 +39,6 @@ android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info" android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" - android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin" android:text="@string/notification_header_divider_symbol" android:singleLine="true" android:visibility="gone" @@ -53,7 +51,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" - android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin" android:singleLine="true" android:visibility="gone" /> @@ -64,7 +61,6 @@ android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info" android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" - android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin" android:text="@string/notification_header_divider_symbol" android:singleLine="true" android:visibility="gone" @@ -96,7 +92,6 @@ android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info" android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" - android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin" android:text="@string/notification_header_divider_symbol" android:singleLine="true" android:visibility="gone" @@ -106,7 +101,7 @@ android:id="@+id/verification_icon" android:layout_width="@dimen/notification_verification_icon_size" android:layout_height="@dimen/notification_verification_icon_size" - android:layout_marginStart="4dp" + android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" android:baseline="10dp" android:scaleType="fitCenter" android:src="@drawable/ic_notifications_alerted" @@ -119,6 +114,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" + android:layout_weight="100" android:showRelative="true" android:singleLine="true" android:visibility="gone" @@ -141,7 +137,7 @@ android:id="@+id/phishing_alert" android:layout_width="@dimen/notification_phishing_alert_size" android:layout_height="@dimen/notification_phishing_alert_size" - android:layout_marginStart="4dp" + android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" android:baseline="10dp" android:scaleType="fitCenter" android:src="@drawable/ic_dialog_alert_material" @@ -153,7 +149,7 @@ android:id="@+id/profile_badge" android:layout_width="@dimen/notification_badge_size" android:layout_height="@dimen/notification_badge_size" - android:layout_marginStart="4dp" + android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" android:baseline="10dp" android:scaleType="fitCenter" android:visibility="gone" @@ -164,11 +160,11 @@ android:id="@+id/alerted_icon" android:layout_width="@dimen/notification_alerted_size" android:layout_height="@dimen/notification_alerted_size" - android:layout_marginStart="4dp" + android:layout_marginStart="@dimen/notification_conversation_header_separating_margin" android:baseline="10dp" android:contentDescription="@string/notification_alerted_content_description" android:scaleType="fitCenter" android:src="@drawable/ic_notifications_alerted" android:visibility="gone" /> -</LinearLayout> +</com.android.internal.widget.ConversationHeaderLinearLayout> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index f05e18fa2ce3..65e4664589f3 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -2288,8 +2288,8 @@ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string> <string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string> <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাওক"</string> - <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ডিভাইচৰ কেমেৰ অৱৰোধৰ পৰা আঁতৰাওক"</string> - <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> আৰু আটাইবোৰ এপ আৰু সেৱাৰ বাবে"</string> + <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাওক"</string> + <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> আৰু আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"অৱৰোধৰ পৰা আঁতৰাওক"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ছেন্সৰ সম্পৰ্কীয় গোপনীয়তাৰ নীতি"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"এপ্লিকেশ্বনৰ চিহ্ন"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 39688221f30d..0970fc50da49 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -2357,7 +2357,7 @@ <string name="dismiss_action" msgid="1728820550388704784">"Адхіліць"</string> <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Разблакіруйце мікрафон прылады"</string> <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Разблакіруйце камеру прылады"</string> - <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Для праграмы <b><xliff:g id="APP">%s</xliff:g></b> і ўсіх праграм і сэрвісаў"</string> + <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Для <b><xliff:g id="APP">%s</xliff:g></b> і ўсіх праграм і сэрвісаў"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Разблакіраваць"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Прыватнасць інфармацыі з датчыка"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Значок праграмы"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 47bcbe189570..2f68cdab4a03 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -815,7 +815,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"অফিসের মোবাইল"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"কার্যক্ষেত্রের পেজার"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"অ্যাসিস্ট্যান্ট"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"কাস্টম"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"জন্মদিন"</string> @@ -1949,10 +1949,10 @@ <string name="maximize_button_text" msgid="4258922519914732645">"বড় করুন"</string> <string name="close_button_text" msgid="10603510034455258">"বন্ধ করুন"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"উত্তর"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"উত্তর দিন"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"ভিডিও"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"বাতিল করুন"</string> - <string name="call_notification_hang_up_action" msgid="9130720590159188131">"কল কেটে দেওয়া"</string> + <string name="call_notification_hang_up_action" msgid="9130720590159188131">"কল কেটে দিন"</string> <string name="call_notification_incoming_text" msgid="6143109825406638201">"ইনকামিং কল"</string> <string name="call_notification_ongoing_text" msgid="3880832933933020875">"চালু থাকা কল"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"ইনকামিং কল স্ক্রিনিং করা হচ্ছে"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 088495e9eee4..542387f2047e 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -2012,7 +2012,7 @@ <string name="app_category_productivity" msgid="1844422703029557883">"Effizienz"</string> <string name="app_category_accessibility" msgid="6643521607848547683">"Bedienungshilfen"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Gerätespeicher"</string> - <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB-Fehlerbehebung"</string> + <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB-Debugging"</string> <string name="time_picker_hour_label" msgid="4208590187662336864">"Stunde"</string> <string name="time_picker_minute_label" msgid="8307452311269824553">"Minute"</string> <string name="time_picker_header_text" msgid="9073802285051516688">"Uhrzeit einstellen"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 93c7bc1df4d1..8c465f174a96 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -2289,7 +2289,7 @@ <string name="dismiss_action" msgid="1728820550388704784">"Cerrar"</string> <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Desbloquea el micrófono del dispositivo"</string> <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Desbloquea la cámara del dispositivo"</string> - <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Para <b><xliff:g id="APP">%s</xliff:g></b> y todos los servicios y las aplicaciones"</string> + <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Para <b><xliff:g id="APP">%s</xliff:g></b> y todas las aplicaciones y servicios"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Desbloquear"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privacidad del sensor"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Icono de aplicación"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 1b5e4b979fff..f388427acab6 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1023,7 +1023,7 @@ <string name="text_copied" msgid="2531420577879738860">"متن در بریدهدان کپی شد."</string> <string name="copied" msgid="4675902854553014676">"کپی شد"</string> <string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> از <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> جایگذاری کرد"</string> - <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> از بریدهدان جایگذاری کرد"</string> + <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> محتوا را از بریدهدان جایگذاری کرد"</string> <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نوشتاری را که کپی کردید جایگذاری کرد"</string> <string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> تصویری را که کپی کردید جایگذاری کرد"</string> <string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> محتوایی را که کپی کردید جایگذاری کرد"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 141da9c1c719..76f54ff26b09 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1949,7 +1949,7 @@ <string name="maximize_button_text" msgid="4258922519914732645">"Maximizar"</string> <string name="close_button_text" msgid="10603510034455258">"Pechar"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"Resposta"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"Contestar"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"Vídeo"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"Rexeitar"</string> <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Colgar"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index c86b8cddb342..17382c453f7f 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1960,7 +1960,7 @@ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item> <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item> </plurals> - <string name="default_notification_channel_label" msgid="3697928973567217330">"Belum dikategorikan"</string> + <string name="default_notification_channel_label" msgid="3697928973567217330">"Tidak dikategorikan"</string> <string name="importance_from_user" msgid="2782756722448800447">"Anda menyetel nilai penting notifikasi ini."</string> <string name="importance_from_person" msgid="4235804979664465383">"Ini penting karena orang-orang yang terlibat."</string> <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Notifikasi aplikasi kustom"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 667dd9c46055..93e25a6b014e 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -2287,10 +2287,10 @@ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"Nú geturðu stækkað hluta skjásins"</string> <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Kveikja á í stillingum"</string> <string name="dismiss_action" msgid="1728820550388704784">"Hunsa"</string> - <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Opna á hljóðnema tækisins"</string> + <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Opna fyrir hljóðnema tækisins"</string> <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Opna fyrir myndavél tækisins"</string> <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Fyrir <b><xliff:g id="APP">%s</xliff:g></b> og öll forrit og þjónustur"</string> - <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Opna á"</string> + <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Opna fyrir"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Persónuvernd skynjara"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Forritstákn"</string> <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Mynd af merki forrits"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index cd8cb90ae608..716e97c70768 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -2011,7 +2011,7 @@ <string name="maximize_button_text" msgid="4258922519914732645">"הגדלה"</string> <string name="close_button_text" msgid="10603510034455258">"סגירה"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"תשובה"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"מענה"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"וידאו"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"דחייה"</string> <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ניתוק"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index a9226379b446..30a62e3d8df0 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -437,7 +437,7 @@ <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"位置情報提供者の追加コマンドアクセス"</string> <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string> <string name="permlab_accessFineLocation" msgid="6426318438195622966">"フォアグラウンドでのみ正確な位置情報にアクセス"</string> - <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"このアプリは、使用中に、位置情報サービスからデバイスの正確な位置情報を取得できます。アプリが位置情報を取得するには、デバイスで位置情報サービスがオンになっている必要があります。この場合、バッテリー使用量が増えることがあります。"</string> + <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"このアプリは、使用中に、位置情報サービスからデバイスの正確な位置情報を取得できます。アプリが位置情報を取得するには、デバイスで位置情報サービスが ON になっている必要があります。この場合、バッテリー使用量が増えることがあります。"</string> <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"フォアグラウンドでのみおおよその位置情報にアクセス"</string> <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"このアプリは、使用中に、位置情報サービスからデバイスのおおよその位置情報を取得できます。アプリが位置情報を取得するには、デバイスで位置情報サービスがオンになっている必要があります。"</string> <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"バックグラウンドでの位置情報へのアクセス"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index a7d6ae0d1fbe..ed2f964d29e7 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -1952,7 +1952,7 @@ <string name="call_notification_answer_action" msgid="5999246836247132937">"ಉತ್ತರಿಸಿ"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"ವೀಡಿಯೊ"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"ನಿರಾಕರಿಸಿ"</string> - <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ಹ್ಯಾಂಗ್ ಅಪ್"</string> + <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ಕರೆ ಕೊನೆಗೊಳಿಸಿ"</string> <string name="call_notification_incoming_text" msgid="6143109825406638201">"ಒಳಬರುವ ಕರೆ"</string> <string name="call_notification_ongoing_text" msgid="3880832933933020875">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಕರೆ"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"ಒಳಬರುವ ಕರೆಯನ್ನು ಸ್ಕ್ರೀನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> @@ -2287,7 +2287,7 @@ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"ನೀವು ಇದೀಗ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಭಾಗವನ್ನು ಹಿಗ್ಗಿಸಬಹುದು"</string> <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಆನ್ ಮಾಡಿ"</string> <string name="dismiss_action" msgid="1728820550388704784">"ವಜಾಗೊಳಿಸಿ"</string> - <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕಿ"</string> + <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ಅನ್ಬ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕಿ"</string> <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> ಮತ್ತು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಹಾಗೂ ಸೇವೆಗಳಿಗಾಗಿ"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index f5d16fcb3f7f..ea8fe228896a 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1949,7 +1949,7 @@ <string name="maximize_button_text" msgid="4258922519914732645">"최대화"</string> <string name="close_button_text" msgid="10603510034455258">"닫기"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"답변"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"통화"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"동영상"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"거절"</string> <string name="call_notification_hang_up_action" msgid="9130720590159188131">"전화 끊기"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 174d7324dda9..421608687033 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -2287,8 +2287,8 @@ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"Эми экрандын бир бөлүгүн чоңойто аласыз"</string> <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Жөндөөлөрдөн күйгүзүү"</string> <string name="dismiss_action" msgid="1728820550388704784">"Жабуу"</string> - <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Түзмөктүн микрофонунун кулпусун ачуу"</string> - <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Түзмөктүн камерасынын кулпусун ачуу"</string> + <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Түзмөктүн микрофонун бөгөттөн чыгаруу"</string> + <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Түзмөктүн камерасын бөгөттөн чыгаруу"</string> <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> жана башка бардык колдонмолор менен кызматтар үчүн"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Бөгөттөн чыгаруу"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Сенсордун купуялыгы"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 34da0f4ec111..b1c0d591c4fb 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -2290,7 +2290,7 @@ <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ຍົກເລີກການບລັອກໄມໂຄຣໂຟນອຸປະກອນ"</string> <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ຍົກເລີກການບລັອກອຸປະກອນກ້ອງຖ່າຍຮູບ"</string> <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"ສຳລັບ <b><xliff:g id="APP">%s</xliff:g></b> ແລະ ແອັບ ແລະ ບໍລິການທັງໝົດ"</string> - <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"ຍົກເລີກການບລັອກ"</string> + <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"ປົດບລັອກ"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ຄວາມເປັນສ່ວນຕົວເຊັນເຊີ"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"ໄອຄອນແອັບພລິເຄຊັນ"</string> <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ຮູບແບຣນແອັບພລິເຄຊັນ"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index c64160c793da..1b224c3dd0f7 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -1955,7 +1955,7 @@ <string name="call_notification_hang_up_action" msgid="9130720590159188131">"കോൾ നിർത്തുക"</string> <string name="call_notification_incoming_text" msgid="6143109825406638201">"ഇൻകമിംഗ് കോൾ"</string> <string name="call_notification_ongoing_text" msgid="3880832933933020875">"സജീവമായ കോൾ"</string> - <string name="call_notification_screening_text" msgid="8396931408268940208">"ഇൻകമിംഗ് കോൾ സ്ക്രീൻ ചെയ്യൽ"</string> + <string name="call_notification_screening_text" msgid="8396931408268940208">"ഇൻകമിംഗ് കോൾ സ്ക്രീൻ ചെയ്യുന്നു"</string> <plurals name="selected_count" formatted="false" msgid="3946212171128200491"> <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു</item> <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു</item> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 36af211f07b3..12f8cd427d7f 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1949,7 +1949,7 @@ <string name="maximize_button_text" msgid="4258922519914732645">"ठुलो बनाउनुहोस्"</string> <string name="close_button_text" msgid="10603510034455258">"बन्द गर्नुहोस्"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"कलको जवाफ दिनु…"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"जवाफ दिनुहोस्"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"भिडियो"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"अस्वीकार गर्नुहोस्"</string> <string name="call_notification_hang_up_action" msgid="9130720590159188131">"फोन राख्नुहोस्"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index a76852f84895..85464afadf56 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -1323,7 +1323,7 @@ </string-array> <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ଏକ ଅଜଣା ନେଟ୍ୱର୍କ ପ୍ରକାର"</string> <string name="accept" msgid="5447154347815825107">"ଗ୍ରହଣ କରନ୍ତୁ"</string> - <string name="decline" msgid="6490507610282145874">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string> + <string name="decline" msgid="6490507610282145874">"ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string> <string name="select_character" msgid="3352797107930786979">"ବର୍ଣ୍ଣ ଲେଖନ୍ତୁ"</string> <string name="sms_control_title" msgid="4748684259903148341">"SMS ମେସେଜ୍ଗୁଡ଼ିକୁ ପଠାଯାଉଛି"</string> <string name="sms_control_message" msgid="6574313876316388239">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ବହୁତ ସଂଖ୍ୟାର SMS ମେସେଜ୍ ପଠାଉଛି। ଏହି ଆପ୍ ମେସେଜ୍ ପଠାଇବା ଜାରି ରଖିବାକୁ ଆପଣ ଅନୁମତି ଦେବେ କି?"</string> @@ -1389,7 +1389,7 @@ <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"ବଗ୍ ରିପୋର୍ଟ ସେୟାର୍ କରାଯାଉଛି…"</string> <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"ଏହି ଡିଭାଇସ୍ର ସମସ୍ୟା ସମାଧାନ କରିବା ପାଇଁ ଆପଣଙ୍କର ଆଡମିନ୍ ଏକ ବଗ୍ ରିପୋର୍ଟ ମାଗିଛନ୍ତି। ଆପ୍ ଓ ଡାଟା ଶେୟର୍ କରାଯାଇପାରେ।"</string> <string name="share_remote_bugreport_action" msgid="7630880678785123682">"ସେୟାର୍ କରନ୍ତୁ"</string> - <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"ପ୍ରତ୍ୟାଖ୍ୟାନ କରନ୍ତୁ"</string> + <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string> <string name="select_input_method" msgid="3971267998568587025">"ଇନପୁଟ୍ ପଦ୍ଧତି ବାଛନ୍ତୁ"</string> <string name="show_ime" msgid="6406112007347443383">"ଫିଜିକାଲ୍ କୀବୋର୍ଡ ସକ୍ରିୟ ଥିବାବେଳେ ଏହାକୁ ସ୍କ୍ରିନ୍ ଉପରେ ରଖନ୍ତୁ"</string> <string name="hardware" msgid="1800597768237606953">"ଭର୍ଚୁଆଲ୍ କୀ’ବୋର୍ଡ ଦେଖାନ୍ତୁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 209c6a1fb88c..86a9c3ffd527 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -815,7 +815,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ਕੰਮ ਦਾ ਮੋਬਾਈਲ"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"ਦਫ਼ਤਰ ਦਾ ਪੇਜਰ"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"ਸਹਾਇਕ"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"ਵਿਉਂਂਤੀ"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"ਜਨਮਦਿਨ"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 57e1cb0e4e74..5a336ae237e5 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -266,8 +266,8 @@ <string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"Som desativado"</string> <string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"O som está ativado"</string> <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"Modo de avião"</string> - <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"O modo de voo está ativado"</string> - <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"O modo de voo está desativado"</string> + <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"Modo de avião ativado"</string> + <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"Modo de avião desativado"</string> <string name="global_action_settings" msgid="4671878836947494217">"Definições"</string> <string name="global_action_assist" msgid="2517047220311505805">"Assistência"</string> <string name="global_action_voice_assist" msgid="6655788068555086695">"Assist. de voz"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index afdf1d9a4b21..67b0ce0d50b1 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -26,7 +26,7 @@ <string name="gigabyteShort" msgid="7515809460261287991">"GB"</string> <string name="terabyteShort" msgid="1822367128583886496">"TB"</string> <string name="petabyteShort" msgid="5651571254228534832">"PB"</string> - <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g>U+00A0<xliff:g id="UNIT">%2$s</xliff:g>"</string> + <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string> <string name="untitled" msgid="3381766946944136678">"<Bez mena>"</string> <string name="emptyPhoneNumber" msgid="5812172618020360048">"(žiadne telefónne číslo)"</string> <string name="unknownName" msgid="7078697621109055330">"Bez názvu"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index bebdf7a71828..93f2d7420124 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -2355,9 +2355,9 @@ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"Zdaj lahko povečate samo del zaslona."</string> <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vklopite v nastavitvah"</string> <string name="dismiss_action" msgid="1728820550388704784">"Opusti"</string> - <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Odblokiranje mikrofona v napravi"</string> - <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Odblokiranje fotoaparata v napravi"</string> - <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Za aplikacijo <b><xliff:g id="APP">%s</xliff:g></b> ter vse aplikacije in storitve"</string> + <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Odblokirajte mikrofon v napravi"</string> + <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Odblokirajte fotoaparat v napravi"</string> + <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Za aplikacijo <b><xliff:g id="APP">%s</xliff:g></b> ter vse aplikacije in storitve."</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Odblokiraj"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Zasebnost pri uporabi tipal"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"Ikona aplikacije"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 3568871008cd..d68c088d5867 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -1949,10 +1949,10 @@ <string name="maximize_button_text" msgid="4258922519914732645">"గరిష్టీకరించు"</string> <string name="close_button_text" msgid="10603510034455258">"మూసివేయి"</string> <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> - <string name="call_notification_answer_action" msgid="5999246836247132937">"సమాధానం ఇవ్వు"</string> + <string name="call_notification_answer_action" msgid="5999246836247132937">"పికప్ చేయండి"</string> <string name="call_notification_answer_video_action" msgid="2086030940195382249">"వీడియో కాల్"</string> - <string name="call_notification_decline_action" msgid="3700345945214000726">"తిరస్కరించండి"</string> - <string name="call_notification_hang_up_action" msgid="9130720590159188131">"కాల్ ముగించు"</string> + <string name="call_notification_decline_action" msgid="3700345945214000726">"కట్ చేయండి"</string> + <string name="call_notification_hang_up_action" msgid="9130720590159188131">"ముగించండి"</string> <string name="call_notification_incoming_text" msgid="6143109825406638201">"ఇన్కమింగ్ కాల్"</string> <string name="call_notification_ongoing_text" msgid="3880832933933020875">"కాల్ కొనసాగుతోంది"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"ఇన్కమింగ్ కాల్ను స్క్రీన్ చేయండి"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index bc1c66447c25..3325e7e96d5e 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1953,8 +1953,8 @@ <string name="call_notification_answer_video_action" msgid="2086030940195382249">"Video"</string> <string name="call_notification_decline_action" msgid="3700345945214000726">"Reddet"</string> <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Kapat"</string> - <string name="call_notification_incoming_text" msgid="6143109825406638201">"Gelen çağrı"</string> - <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Devam eden çağrı"</string> + <string name="call_notification_incoming_text" msgid="6143109825406638201">"Gelen arama"</string> + <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Devam eden arama"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"Gelen arama süzülüyor"</string> <plurals name="selected_count" formatted="false" msgid="3946212171128200491"> <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 794f50eb8069..68a5ce7ee349 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -142,7 +142,7 @@ <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"WLAN"</string> <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"WLAN 通话"</string> <string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string> - <string name="wifi_calling_off_summary" msgid="5626710010766902560">"关闭"</string> + <string name="wifi_calling_off_summary" msgid="5626710010766902560">"已关闭"</string> <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"通过 WLAN 进行通话"</string> <string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"通过移动网络进行通话"</string> <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"仅限 WLAN"</string> @@ -1696,8 +1696,8 @@ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同时按住两个音量键几秒钟,即可开启<xliff:g id="SERVICE">%1$s</xliff:g>无障碍功能。这样做可能会改变您设备的工作方式。\n\n您可以在“设置”>“无障碍”中将此快捷方式更改为开启另一项功能。"</string> <string name="accessibility_shortcut_on" msgid="5463618449556111344">"开启"</string> <string name="accessibility_shortcut_off" msgid="3651336255403648739">"不开启"</string> - <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"开启"</string> - <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"关闭"</string> + <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"已开启"</string> + <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"已关闭"</string> <string name="accessibility_enable_service_title" msgid="3931558336268541484">"要允许<xliff:g id="SERVICE">%1$s</xliff:g>完全控制您的设备吗?"</string> <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"如果您开启<xliff:g id="SERVICE">%1$s</xliff:g>,您的设备将无法使用屏幕锁定功能来增强数据加密效果。"</string> <string name="accessibility_service_warning_description" msgid="291674995220940133">"对于能满足您的无障碍功能需求的应用,可授予其完全控制权限;但对大部分应用来说,都不适合授予此权限。"</string> @@ -2287,10 +2287,10 @@ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"现在您可以放大屏幕上的部分内容"</string> <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在“设置”中开启"</string> <string name="dismiss_action" msgid="1728820550388704784">"关闭"</string> - <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"取消禁用设备麦克风"</string> - <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"取消禁用设备摄像头"</string> - <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"针对<b><xliff:g id="APP">%s</xliff:g></b>及所有应用和服务"</string> - <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"取消禁用"</string> + <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"解锁设备麦克风"</string> + <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"解锁设备摄像头"</string> + <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"允许“<b><xliff:g id="APP">%s</xliff:g></b>”及所有应用和服务使用"</string> + <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"解锁"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"传感器隐私权"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"应用图标"</string> <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"应用品牌图片"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 029ed5b23d84..db43b5b31e7e 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4408,14 +4408,14 @@ M9,10l-2,0l0,-2l-2,0l0,2l-2,0l0,2l2,0l0,2l2,0l0,-2l2,0z </string> - <!-- X path for SignalDrawable as defined on a 24x24 canvas. --> - <string name="config_signalXPath" translatable="false"> - M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09-2.08L20.59,22L22,20.59l-2.08-2.09 L22,16.41z + <!-- Attribution path for SignalDrawable as defined on a 24x24 canvas. --> + <string name="config_signalAttributionPath" translatable="false"> + M20,10h2v8h-2z M20,20h2v2h-2z </string> <!-- config_signalCutout{Height,Width}Fraction define fraction of the 24x24 canvas that - should be cut out to display config_signalXPath.--> - <item name="config_signalCutoutWidthFraction" format="float" type="dimen">11</item> - <item name="config_signalCutoutHeightFraction" format="float" type="dimen">11</item> + should be cut out to display config_signalAttributionPath. --> + <item name="config_signalCutoutWidthFraction" format="float" type="dimen">7</item> + <item name="config_signalCutoutHeightFraction" format="float" type="dimen">17</item> <!-- A dual tone battery meter draws the perimeter path twice - once to define the shape and a second time clipped to the fill level to indicate charge --> @@ -4804,7 +4804,7 @@ <!-- Blur radius for the Option 3 in R.integer.config_letterboxBackgroundType. Values < 0 are ignored and 0 is used. --> - <dimen name="config_letterboxBackgroundWallpaperBlurRadius">100dp</dimen> + <dimen name="config_letterboxBackgroundWallpaperBlurRadius">31dp</dimen> <!-- Alpha of a black translucent scrim showed over wallpaper letterbox background when the Option 3 is selected for R.integer.config_letterboxBackgroundType. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 40555fdaaa45..adb046e76c88 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3369,7 +3369,7 @@ <java-symbol type="string" name="config_batterymeterBoltPath" /> <java-symbol type="string" name="config_batterymeterPowersavePath" /> <java-symbol type="bool" name="config_batterymeterDualTone" /> - <java-symbol type="string" name="config_signalXPath" /> + <java-symbol type="string" name="config_signalAttributionPath" /> <java-symbol type="dimen" name="config_signalCutoutWidthFraction" /> <java-symbol type="dimen" name="config_signalCutoutHeightFraction" /> diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java index 24baa93337ba..cca66420c596 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java @@ -69,11 +69,11 @@ public class BatteryStatsImplTest { when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true); mBatteryStatsImpl = new MockBatteryStatsImpl() .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader) - .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader); + .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader) + .setTrackingCpuByProcStateEnabled(true); } @Test - @SkipPresubmit("b/180015146") public void testUpdateProcStateCpuTimes() { mBatteryStatsImpl.setOnBatteryInternal(true); mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0); @@ -231,7 +231,6 @@ public class BatteryStatsImplTest { } @Test - @SkipPresubmit("b/180015146") public void testCopyFromAllUidsCpuTimes() { mBatteryStatsImpl.setOnBatteryInternal(false); mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0); diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java index 4ef45e2b126b..b59b84bb15ba 100644 --- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java @@ -580,11 +580,11 @@ public class BstatsCpuTimesValidationTest { final long[] cpuTimesMs4 = getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP); assertCpuTimesValid(cpuTimesMs4); actualCpuTimeMs = 0; - for (int i = 0; i < cpuTimesMs.length / 2; ++i) { - actualCpuTimeMs += cpuTimesMs[i]; + for (int i = 0; i < cpuTimesMs4.length / 2; ++i) { + actualCpuTimeMs += cpuTimesMs4[i]; } assertApproximateValue("Incorrect total cpu time, " + msgCpuTimes, - WORK_DURATION_MS, actualCpuTimeMs); + 2 * WORK_DURATION_MS, actualCpuTimeMs); batteryOffScreenOn(); } finally { diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index 80def71ce812..99d576d259ec 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -174,6 +174,11 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { return this; } + public MockBatteryStatsImpl setTrackingCpuByProcStateEnabled(boolean enabled) { + mConstants.TRACK_CPU_TIMES_BY_PROC_STATE = enabled; + return this; + } + public SparseIntArray getPendingUids() { return mPendingUids; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 75dd561ffc61..107a3f880354 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -127,11 +127,13 @@ public class SplashscreenContentDrawer { * parallel. * * @param suggestType Suggest type to create the splash screen view. - * @param consumer Receiving the SplashScreenView object, which will also be executed - * on splash screen thread. Note that the view can be null if failed. + * @param splashScreenViewConsumer Receiving the SplashScreenView object, which will also be + * executed on splash screen thread. Note that the view can be + * null if failed. + * @param bgColorConsumer Receiving the background color once it's estimated complete. */ void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info, - int taskId, Consumer<SplashScreenView> consumer) { + int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) { mSplashscreenWorkerHandler.post(() -> { SplashScreenView contentView; try { @@ -143,7 +145,7 @@ public class SplashscreenContentDrawer { + taskId, e); contentView = null; } - consumer.accept(contentView); + splashScreenViewConsumer.accept(contentView); }); } @@ -160,7 +162,10 @@ public class SplashscreenContentDrawer { com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length); } - private static int getSystemBGColor() { + /** + * @return Current system background color. + */ + public static int getSystemBGColor() { final Context systemContext = ActivityThread.currentApplication(); if (systemContext == null) { Slog.e(TAG, "System context does not exist!"); @@ -170,12 +175,22 @@ public class SplashscreenContentDrawer { return res.getColor(com.android.wm.shell.R.color.splash_window_background_default); } + /** + * Estimate the background color of the app splash screen, this may take a while so use it only + * if there is no starting window exists for that context. + **/ + int estimateTaskBackgroundColor(Context context) { + final SplashScreenWindowAttrs windowAttrs = new SplashScreenWindowAttrs(); + getWindowAttrs(context, windowAttrs); + return peekWindowBGColor(context, windowAttrs); + } + private static Drawable createDefaultBackgroundDrawable() { return new ColorDrawable(getSystemBGColor()); } /** Extract the window background color from {@code attrs}. */ - public static int peekWindowBGColor(Context context, SplashScreenWindowAttrs attrs) { + private static int peekWindowBGColor(Context context, SplashScreenWindowAttrs attrs) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "peekWindowBGColor"); final Drawable themeBGDrawable; if (attrs.mWindowBgColor != 0) { @@ -255,7 +270,7 @@ public class SplashscreenContentDrawer { * Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into * {@code attrs}. */ - public static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) { + private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) { final TypedArray typedArray = context.obtainStyledAttributes( com.android.internal.R.styleable.Window); attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java index 079d68973852..01c9b6630fa6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java @@ -16,6 +16,8 @@ package com.android.wm.shell.startingsurface; +import android.app.TaskInfo; +import android.graphics.Color; /** * Interface to engage starting window feature. */ @@ -27,4 +29,11 @@ public interface StartingSurface { default IStartingWindow createExternalInterface() { return null; } + + /** + * Returns the background color for a starting window if existing. + */ + default int getBackgroundColor(TaskInfo taskInfo) { + return Color.BLACK; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 4dc5447cbe65..243751fe13e8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -26,17 +26,22 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; +import android.app.ActivityThread; +import android.app.TaskInfo; import android.content.Context; import android.content.pm.ActivityInfo; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.os.IBinder; import android.os.RemoteCallback; +import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.util.Slog; @@ -149,6 +154,12 @@ public class StartingSurfaceDrawer { return context.createDisplayContext(targetDisplay); } + private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) { + return splashScreenThemeResId != 0 + ? splashScreenThemeResId + : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource() + : com.android.internal.R.style.Theme_DeviceDefault_DayNight; + } /** * Called when a task need a splash screen starting window. * @@ -170,10 +181,7 @@ public class StartingSurfaceDrawer { final int taskId = taskInfo.taskId; Context context = mContext; // replace with the default theme if the application didn't set - final int theme = windowInfo.splashScreenThemeResId != 0 - ? windowInfo.splashScreenThemeResId - : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource() - : com.android.internal.R.style.Theme_DeviceDefault_DayNight; + final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo); if (DEBUG_SPLASH_SCREEN) { Slog.d(TAG, "addSplashScreen " + activityInfo.packageName + " theme=" + Integer.toHexString(theme) + " task=" + taskInfo.taskId @@ -336,6 +344,10 @@ public class StartingSurfaceDrawer { // the window before first round relayoutWindow, which will happen after insets // animation. mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null); + // Block until we get the background color. + final StartingWindowRecord record = mStartingWindowRecords.get(taskId); + final SplashScreenView contentView = viewSupplier.get(); + record.mBGColor = contentView.getInitBackgroundColor(); } } catch (RuntimeException e) { // don't crash if something else bad happens, for example a @@ -346,11 +358,11 @@ public class StartingSurfaceDrawer { } int getStartingWindowBackgroundColorForTask(int taskId) { - StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId); - if (startingWindowRecord == null || startingWindowRecord.mContentView == null) { - return 0; + final StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId); + if (startingWindowRecord == null) { + return Color.TRANSPARENT; } - return startingWindowRecord.mContentView.getInitBackgroundColor(); + return startingWindowRecord.mBGColor; } private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> { @@ -378,6 +390,43 @@ public class StartingSurfaceDrawer { } } + int estimateTaskBackgroundColor(TaskInfo taskInfo) { + if (taskInfo.topActivityInfo == null) { + return Color.TRANSPARENT; + } + final ActivityInfo activityInfo = taskInfo.topActivityInfo; + final String packageName = activityInfo.packageName; + final int userId = taskInfo.userId; + final Context windowContext; + try { + windowContext = mContext.createPackageContextAsUser( + packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId)); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Failed creating package context with package name " + + packageName + " for user " + taskInfo.userId, e); + return Color.TRANSPARENT; + } + try { + final IPackageManager packageManager = ActivityThread.getPackageManager(); + final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName, + userId); + final int splashScreenThemeId = splashScreenThemeName != null + ? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null) + : 0; + + final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo); + + if (theme != windowContext.getThemeResId()) { + windowContext.setTheme(theme); + } + return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext); + } catch (RuntimeException | RemoteException e) { + Slog.w(TAG, "failed get starting window background color at taskId: " + + taskInfo.taskId, e); + } + return Color.TRANSPARENT; + } + /** * Called when a task need a snapshot starting window. */ @@ -556,19 +605,16 @@ public class StartingSurfaceDrawer { private SplashScreenView mContentView; private boolean mSetSplashScreen; private @StartingWindowType int mSuggestType; - - StartingWindowRecord(IBinder appToken, View decorView, - TaskSnapshotWindow taskSnapshotWindow) { - mAppToken = appToken; - mDecorView = decorView; - mTaskSnapshotWindow = taskSnapshotWindow; - } + private int mBGColor; StartingWindowRecord(IBinder appToken, View decorView, TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) { mAppToken = appToken; mDecorView = decorView; mTaskSnapshotWindow = taskSnapshotWindow; + if (mTaskSnapshotWindow != null) { + mBGColor = mTaskSnapshotWindow.getBackgroundColor(); + } mSuggestType = suggestType; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index eaa89d8e3ab5..e84d498a9258 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -18,18 +18,23 @@ package com.android.wm.shell.startingsurface; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN; +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import android.app.ActivityManager.RunningTaskInfo; +import android.app.TaskInfo; import android.content.Context; +import android.graphics.Color; import android.graphics.Rect; +import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; import android.util.Slog; +import android.util.SparseIntArray; import android.view.SurfaceControl; import android.window.StartingWindowInfo; import android.window.StartingWindowInfo.StartingWindowType; @@ -38,6 +43,7 @@ import android.window.TaskSnapshot; import androidx.annotation.BinderThread; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.TriConsumer; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; @@ -62,10 +68,11 @@ import com.android.wm.shell.common.TransactionPool; public class StartingWindowController implements RemoteCallable<StartingWindowController> { private static final String TAG = StartingWindowController.class.getSimpleName(); - // TODO b/183150443 Keep this flag open for a while, several things might need to adjust. - public static final boolean DEBUG_SPLASH_SCREEN = true; + public static final boolean DEBUG_SPLASH_SCREEN = Build.isDebuggable(); public static final boolean DEBUG_TASK_SNAPSHOT = false; + private static final long TASK_BG_COLOR_RETAIN_TIME_MS = 5000; + private final StartingSurfaceDrawer mStartingSurfaceDrawer; private final StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm; @@ -73,6 +80,11 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl(); private final Context mContext; private final ShellExecutor mSplashScreenExecutor; + /** + * Need guarded because it has exposed to StartingSurface + */ + @GuardedBy("mTaskBackgroundColors") + private final SparseIntArray mTaskBackgroundColors = new SparseIntArray(); public StartingWindowController(Context context, ShellExecutor splashScreenExecutor, StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) { @@ -125,13 +137,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo final TaskSnapshot snapshot = windowInfo.mTaskSnapshot; mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot); - } else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ { - // Don't add a staring window. } - if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) { + if (suggestionType != STARTING_WINDOW_TYPE_NONE) { int taskId = runningTaskInfo.taskId; - int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId); - mTaskLaunchingCallback.accept(taskId, suggestionType, color); + int color = mStartingSurfaceDrawer + .getStartingWindowBackgroundColorForTask(taskId); + if (color != Color.TRANSPARENT) { + synchronized (mTaskBackgroundColors) { + mTaskBackgroundColors.append(taskId, color); + } + } + if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) { + mTaskLaunchingCallback.accept(taskId, suggestionType, color); + } } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); @@ -163,9 +181,13 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo */ public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, boolean playRevealAnimation) { - mSplashScreenExecutor.execute(() -> { - mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation); - }); + mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.removeStartingWindow( + taskId, leash, frame, playRevealAnimation)); + mSplashScreenExecutor.executeDelayed(() -> { + synchronized (mTaskBackgroundColors) { + mTaskBackgroundColors.delete(taskId); + } + }, TASK_BG_COLOR_RETAIN_TIME_MS); } /** @@ -182,6 +204,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this); return mIStartingWindow; } + + @Override + public int getBackgroundColor(TaskInfo taskInfo) { + synchronized (mTaskBackgroundColors) { + final int index = mTaskBackgroundColors.indexOfKey(taskInfo.taskId); + if (index >= 0) { + return mTaskBackgroundColors.valueAt(index); + } + } + final int color = mStartingSurfaceDrawer.estimateTaskBackgroundColor(taskInfo); + return color != Color.TRANSPARENT + ? color : SplashscreenContentDrawer.getSystemBGColor(); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index 382d5806e3c2..6052d3dee891 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -283,6 +283,10 @@ public class TaskSnapshotWindow { mClearWindowHandler = clearWindowHandler; } + int getBackgroundColor() { + return mBackgroundPaint.getColor(); + } + /** * Ask system bar background painter to draw status bar background. * @hide diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index 5061b2369bb2..284f384a3d26 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -97,7 +97,8 @@ public class StartingSurfaceDrawerTests { // listen for addView mAddWindowForTask = taskId; mViewThemeResId = view.getContext().getThemeResId(); - return true; + // Do not wait for background color + return false; } @Override diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index d8735ce57b65..a743d30939d0 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -183,8 +183,10 @@ CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& inSrcRec SkPaint paint; paint.setAlpha(255); paint.setBlendMode(SkBlendMode::kSrc); - canvas->drawImageRect(image, imageSrcRect, imageDstRect, sampling, &paint, - SkCanvas::kFast_SrcRectConstraint); + const bool hasBufferCrop = cropRect.left < cropRect.right && cropRect.top < cropRect.bottom; + auto constraint = + hasBufferCrop ? SkCanvas::kStrict_SrcRectConstraint : SkCanvas::kFast_SrcRectConstraint; + canvas->drawImageRect(image, imageSrcRect, imageDstRect, sampling, &paint, constraint); canvas->restore(); if (!tmpSurface->readPixels(*bitmap, 0, 0)) { diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index ef3a11c13469..c4cdb7db7d86 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -762,9 +762,11 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( // Create an ImageReader wired up to a BufferItemConsumer AImageReader* rawReader; + constexpr auto usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | + AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY; media_status_t result = - AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, - AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, 2, &rawReader); + AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, usage, 2, &rawReader); std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader, AImageReader_delete); diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 44a6e4354608..4e7471d5d888 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -207,12 +207,16 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) { GrDirectContext* context = thread.getGrContext(); - if (context) { + if (context && !bitmap->isHardware()) { ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height()); auto image = bitmap->makeImage(); - if (image.get() && !bitmap->isHardware()) { + if (image.get()) { SkImage_pinAsTexture(image.get(), context); SkImage_unpinAsTexture(image.get(), context); + // A submit is necessary as there may not be a frame coming soon, so without a call + // to submit these texture uploads can just sit in the queue building up until + // we run out of RAM + context->flushAndSubmit(); } } } diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 5c4b9019b0ad..db29e342855b 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -130,6 +130,12 @@ void DrawFrameTask::run() { if (CC_LIKELY(canDrawThisFrame)) { dequeueBufferDuration = context->draw(); } else { + // Do a flush in case syncFrameState performed any texture uploads. Since we skipped + // the draw() call, those uploads (or deletes) will end up sitting in the queue. + // Do them now + if (GrDirectContext* grContext = mRenderThread->getGrContext()) { + grContext->flushAndSubmit(); + } // wait on fences so tasks don't overlap next frame context->waitOnFences(); } diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index f70149111116..9e8a1e141fe1 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -579,7 +579,9 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) std::lock_guard<std::mutex> lock(mGraphicsQueueMutex); mQueueWaitIdle(mGraphicsQueue); } - destroy_semaphore(mDestroySemaphoreContext); + if (mDestroySemaphoreContext) { + destroy_semaphore(mDestroySemaphoreContext); + } surface->presentCurrentBuffer(dirtyRect, fenceFd); mSwapSemaphore = VK_NULL_HANDLE; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index bd3ca5a80f96..3b9c05bbe64f 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -7062,14 +7062,11 @@ public class AudioManager { @TestApi @NonNull public Map<Integer, Boolean> getSurroundFormats() { - Map<Integer, Boolean> surroundFormats = new HashMap<>(); - int status = AudioSystem.getSurroundFormats(surroundFormats); - if (status != AudioManager.SUCCESS) { - // fail and bail! - Log.e(TAG, "getSurroundFormats failed:" + status); - return new HashMap<Integer, Boolean>(); // Always return a map. + try { + return getService().getSurroundFormats(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } - return surroundFormats; } /** @@ -7116,15 +7113,14 @@ public class AudioManager { * * @return a list of surround formats */ - public ArrayList<Integer> getReportedSurroundFormats() { - ArrayList<Integer> reportedSurroundFormats = new ArrayList<>(); - int status = AudioSystem.getReportedSurroundFormats(reportedSurroundFormats); - if (status != AudioManager.SUCCESS) { - // fail and bail! - Log.e(TAG, "getReportedSurroundFormats failed:" + status); - return new ArrayList<Integer>(); // Always return a list. + @TestApi + @NonNull + public List<Integer> getReportedSurroundFormats() { + try { + return getService().getReportedSurroundFormats(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } - return reportedSurroundFormats; } /** diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index c08c368af55a..0b35ebed966a 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -159,6 +159,10 @@ interface IAudioService { oneway void reloadAudioSettings(); + Map getSurroundFormats(); + + List getReportedSurroundFormats(); + boolean setSurroundFormatEnabled(int audioFormat, boolean enabled); boolean isSurroundFormatEnabled(int audioFormat); diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java index 59ef4b890320..8b69d33722c5 100644 --- a/media/java/android/media/tv/tuner/Lnb.java +++ b/media/java/android/media/tv/tuner/Lnb.java @@ -148,6 +148,7 @@ public class Lnb implements AutoCloseable { LnbCallback mCallback; Executor mExecutor; Tuner mTuner; + private final Object mCallbackLock = new Object(); private native int nativeSetVoltage(int voltage); @@ -164,20 +165,26 @@ public class Lnb implements AutoCloseable { private Lnb() {} void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) { - mCallback = callback; - mExecutor = executor; - mTuner = tuner; + synchronized (mCallbackLock) { + mCallback = callback; + mExecutor = executor; + mTuner = tuner; + } } private void onEvent(int eventType) { - if (mExecutor != null && mCallback != null) { - mExecutor.execute(() -> mCallback.onEvent(eventType)); + synchronized (mCallbackLock) { + if (mExecutor != null && mCallback != null) { + mExecutor.execute(() -> mCallback.onEvent(eventType)); + } } } private void onDiseqcMessage(byte[] diseqcMessage) { - if (mExecutor != null && mCallback != null) { - mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage)); + synchronized (mCallbackLock) { + if (mExecutor != null && mCallback != null) { + mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage)); + } } } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 2ea745b44288..325436648e63 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -291,7 +291,7 @@ public class Tuner implements AutoCloseable { @Nullable private OnTuneEventListener mOnTuneEventListener; @Nullable - private Executor mOnTunerEventExecutor; + private Executor mOnTuneEventExecutor; @Nullable private ScanCallback mScanCallback; @Nullable @@ -301,6 +301,10 @@ public class Tuner implements AutoCloseable { @Nullable private Executor mOnResourceLostListenerExecutor; + private final Object mOnTuneEventLock = new Object(); + private final Object mScanCallbackLock = new Object(); + private final Object mOnResourceLostListenerLock = new Object(); + private Integer mDemuxHandle; private Integer mFrontendCiCamHandle; private Integer mFrontendCiCamId; @@ -398,18 +402,22 @@ public class Tuner implements AutoCloseable { */ public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor, @NonNull OnResourceLostListener listener) { - Objects.requireNonNull(executor, "OnResourceLostListener must not be null"); - Objects.requireNonNull(listener, "executor must not be null"); - mOnResourceLostListener = listener; - mOnResourceLostListenerExecutor = executor; + synchronized (mOnResourceLostListenerLock) { + Objects.requireNonNull(executor, "OnResourceLostListener must not be null"); + Objects.requireNonNull(listener, "executor must not be null"); + mOnResourceLostListener = listener; + mOnResourceLostListenerExecutor = executor; + } } /** * Removes the listener for resource lost. */ public void clearResourceLostListener() { - mOnResourceLostListener = null; - mOnResourceLostListenerExecutor = null; + synchronized (mOnResourceLostListenerLock) { + mOnResourceLostListener = null; + mOnResourceLostListenerExecutor = null; + } } /** @@ -618,10 +626,12 @@ public class Tuner implements AutoCloseable { break; } case MSG_RESOURCE_LOST: { - if (mOnResourceLostListener != null + synchronized (mOnResourceLostListenerLock) { + if (mOnResourceLostListener != null && mOnResourceLostListenerExecutor != null) { - mOnResourceLostListenerExecutor.execute( - () -> mOnResourceLostListener.onResourceLost(Tuner.this)); + mOnResourceLostListenerExecutor.execute( + () -> mOnResourceLostListener.onResourceLost(Tuner.this)); + } } break; } @@ -652,8 +662,10 @@ public class Tuner implements AutoCloseable { */ public void setOnTuneEventListener(@NonNull @CallbackExecutor Executor executor, @NonNull OnTuneEventListener eventListener) { - mOnTuneEventListener = eventListener; - mOnTunerEventExecutor = executor; + synchronized (mOnTuneEventLock) { + mOnTuneEventListener = eventListener; + mOnTuneEventExecutor = executor; + } } /** @@ -663,9 +675,10 @@ public class Tuner implements AutoCloseable { * @see #setOnTuneEventListener(Executor, OnTuneEventListener) */ public void clearOnTuneEventListener() { - mOnTuneEventListener = null; - mOnTunerEventExecutor = null; - + synchronized (mOnTuneEventLock) { + mOnTuneEventListener = null; + mOnTuneEventExecutor = null; + } } /** @@ -747,32 +760,34 @@ public class Tuner implements AutoCloseable { @Result public int scan(@NonNull FrontendSettings settings, @ScanType int scanType, @NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) { - /** - * Scan can be called again for blink scan if scanCallback and executor are same as before. - */ - if (((mScanCallback != null) && (mScanCallback != scanCallback)) + synchronized (mScanCallbackLock) { + // Scan can be called again for blink scan if scanCallback and executor are same as + //before. + if (((mScanCallback != null) && (mScanCallback != scanCallback)) || ((mScanCallbackExecutor != null) && (mScanCallbackExecutor != executor))) { - throw new IllegalStateException( + throw new IllegalStateException( "Different Scan session already in progress. stopScan must be called " + "before a new scan session can be " + "started."); - } - mFrontendType = settings.getType(); - if (mFrontendType == FrontendSettings.TYPE_DTMB) { - if (!TunerVersionChecker.checkHigherOrEqualVersionTo( - TunerVersionChecker.TUNER_VERSION_1_1, "Scan with DTMB Frontend")) { - return RESULT_UNAVAILABLE; } - } - if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { - mScanCallback = scanCallback; - mScanCallbackExecutor = executor; - mFrontendInfo = null; - FrameworkStatsLog + mFrontendType = settings.getType(); + if (mFrontendType == FrontendSettings.TYPE_DTMB) { + if (!TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, + "Scan with DTMB Frontend")) { + return RESULT_UNAVAILABLE; + } + } + if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { + mScanCallback = scanCallback; + mScanCallbackExecutor = executor; + mFrontendInfo = null; + FrameworkStatsLog .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCANNING); - return nativeScan(settings.getType(), settings, scanType); + return nativeScan(settings.getType(), settings, scanType); + } + return RESULT_UNAVAILABLE; } - return RESULT_UNAVAILABLE; } /** @@ -788,14 +803,15 @@ public class Tuner implements AutoCloseable { */ @Result public int cancelScanning() { - FrameworkStatsLog - .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, + synchronized (mScanCallbackLock) { + FrameworkStatsLog.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCAN_STOPPED); - int retVal = nativeStopScan(); - mScanCallback = null; - mScanCallbackExecutor = null; - return retVal; + int retVal = nativeStopScan(); + mScanCallback = null; + mScanCallbackExecutor = null; + return retVal; + } } private boolean requestFrontend() { @@ -1050,8 +1066,10 @@ public class Tuner implements AutoCloseable { private void onFrontendEvent(int eventType) { Log.d(TAG, "Got event from tuning. Event type: " + eventType); - if (mOnTunerEventExecutor != null && mOnTuneEventListener != null) { - mOnTunerEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType)); + synchronized (mOnTuneEventLock) { + if (mOnTuneEventExecutor != null && mOnTuneEventListener != null) { + mOnTuneEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType)); + } } Log.d(TAG, "Wrote Stats Log for the events from tuning."); @@ -1072,114 +1090,149 @@ public class Tuner implements AutoCloseable { private void onLocked() { Log.d(TAG, "Wrote Stats Log for locked event from scanning."); - FrameworkStatsLog - .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, - FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED); + FrameworkStatsLog.write( + FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, + FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED); - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onLocked()); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onLocked()); + } } } private void onScanStopped() { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped()); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped()); + } } } private void onProgress(int percent) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent)); + } } } private void onFrequenciesReport(int[] frequency) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReported(frequency)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReported(frequency)); + } } } private void onSymbolRates(int[] rate) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRatesReported(rate)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRatesReported(rate)); + } } } private void onHierarchy(int hierarchy) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchyReported(hierarchy)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchyReported(hierarchy)); + } } } private void onSignalType(int signalType) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onSignalTypeReported(signalType)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onSignalTypeReported(signalType)); + } } } private void onPlpIds(int[] plpIds) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIdsReported(plpIds)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIdsReported(plpIds)); + } } } private void onGroupIds(int[] groupIds) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIdsReported(groupIds)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIdsReported(groupIds)); + } } } private void onInputStreamIds(int[] inputStreamIds) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onInputStreamIdsReported(inputStreamIds)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onInputStreamIdsReported(inputStreamIds)); + } } } private void onDvbsStandard(int dvbsStandandard) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onDvbsStandardReported(dvbsStandandard)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onDvbsStandardReported(dvbsStandandard)); + } } } private void onDvbtStandard(int dvbtStandard) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onDvbtStandardReported(dvbtStandard)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onDvbtStandardReported(dvbtStandard)); + } } } private void onAnalogSifStandard(int sif) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandardReported(sif)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandardReported(sif)); + } } } private void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onAtsc3PlpInfosReported(atsc3PlpInfos)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onAtsc3PlpInfosReported(atsc3PlpInfos)); + } } } private void onModulationReported(int modulation) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onModulationReported(modulation)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onModulationReported(modulation)); + } } } private void onPriorityReported(boolean isHighPriority) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onPriorityReported(isHighPriority)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onPriorityReported(isHighPriority)); + } } } private void onDvbcAnnexReported(int dvbcAnnex) { - if (mScanCallbackExecutor != null && mScanCallback != null) { - mScanCallbackExecutor.execute( - () -> mScanCallback.onDvbcAnnexReported(dvbcAnnex)); + synchronized (mScanCallbackLock) { + if (mScanCallbackExecutor != null && mScanCallback != null) { + mScanCallbackExecutor.execute( + () -> mScanCallback.onDvbcAnnexReported(dvbcAnnex)); + } } } diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java index d70b8c29622e..1f805d761d49 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java +++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java @@ -85,6 +85,7 @@ public class DvrPlayback implements AutoCloseable { private static int sInstantId = 0; private int mSegmentId = 0; private int mUnderflow; + private final Object mListenerLock = new Object(); private native int nativeAttachFilter(Filter filter); private native int nativeDetachFilter(Filter filter); @@ -106,16 +107,20 @@ public class DvrPlayback implements AutoCloseable { /** @hide */ public void setListener( @NonNull Executor executor, @NonNull OnPlaybackStatusChangedListener listener) { - mExecutor = executor; - mListener = listener; + synchronized (mListenerLock) { + mExecutor = executor; + mListener = listener; + } } private void onPlaybackStatusChanged(int status) { if (status == PLAYBACK_STATUS_EMPTY) { mUnderflow++; } - if (mExecutor != null && mListener != null) { - mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status)); + synchronized (mListenerLock) { + if (mExecutor != null && mListener != null) { + mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status)); + } } } diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java index 0f9f2e7f89a1..2b694668eb03 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java +++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java @@ -48,6 +48,7 @@ public class DvrRecorder implements AutoCloseable { private int mSegmentId = 0; private int mOverflow; private Boolean mIsStopped = true; + private final Object mListenerLock = new Object(); private native int nativeAttachFilter(Filter filter); private native int nativeDetachFilter(Filter filter); @@ -69,16 +70,20 @@ public class DvrRecorder implements AutoCloseable { /** @hide */ public void setListener( @NonNull Executor executor, @NonNull OnRecordStatusChangedListener listener) { - mExecutor = executor; - mListener = listener; + synchronized (mListenerLock) { + mExecutor = executor; + mListener = listener; + } } private void onRecordStatusChanged(int status) { if (status == Filter.STATUS_OVERFLOW) { mOverflow++; } - if (mExecutor != null && mListener != null) { - mExecutor.execute(() -> mListener.onRecordStatusChanged(status)); + synchronized (mListenerLock) { + if (mExecutor != null && mListener != null) { + mExecutor.execute(() -> mListener.onRecordStatusChanged(status)); + } } } diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java index 2f3e2d8d5dd9..33742ffd99bf 100644 --- a/media/java/android/media/tv/tuner/filter/Filter.java +++ b/media/java/android/media/tv/tuner/filter/Filter.java @@ -227,6 +227,7 @@ public class Filter implements AutoCloseable { private long mNativeContext; private FilterCallback mCallback; private Executor mExecutor; + private final Object mCallbackLock = new Object(); private final long mId; private int mMainType; private int mSubtype; @@ -253,14 +254,18 @@ public class Filter implements AutoCloseable { } private void onFilterStatus(int status) { - if (mCallback != null && mExecutor != null) { - mExecutor.execute(() -> mCallback.onFilterStatusChanged(this, status)); + synchronized (mCallbackLock) { + if (mCallback != null && mExecutor != null) { + mExecutor.execute(() -> mCallback.onFilterStatusChanged(this, status)); + } } } private void onFilterEvent(FilterEvent[] events) { - if (mCallback != null && mExecutor != null) { - mExecutor.execute(() -> mCallback.onFilterEvent(this, events)); + synchronized (mCallbackLock) { + if (mCallback != null && mExecutor != null) { + mExecutor.execute(() -> mCallback.onFilterEvent(this, events)); + } } } @@ -272,13 +277,17 @@ public class Filter implements AutoCloseable { /** @hide */ public void setCallback(FilterCallback cb, Executor executor) { - mCallback = cb; - mExecutor = executor; + synchronized (mCallbackLock) { + mCallback = cb; + mExecutor = executor; + } } /** @hide */ public FilterCallback getCallback() { - return mCallback; + synchronized (mCallbackLock) { + return mCallback; + } } /** diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 93a54445a033..693a027bd0e2 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -44,70 +44,14 @@ using Transaction = SurfaceComposerClient::Transaction; LOG_ALWAYS_FATAL_IF(!static_cast<const Rect&>(name).isValid(), \ "invalid arg passed as " #name " argument"); -static bool getWideColorSupport(const sp<SurfaceControl>& surfaceControl) { - sp<SurfaceComposerClient> client = surfaceControl->getClient(); - - const sp<IBinder> display = client->getInternalDisplayToken(); - if (display == nullptr) { - ALOGE("unable to get wide color support for disconnected internal display"); - return false; - } - - bool isWideColorDisplay = false; - status_t err = client->isWideColorDisplay(display, &isWideColorDisplay); - if (err) { - ALOGE("unable to get wide color support"); - return false; - } - return isWideColorDisplay; -} - -static bool getHdrSupport(const sp<SurfaceControl>& surfaceControl) { - sp<SurfaceComposerClient> client = surfaceControl->getClient(); - - const sp<IBinder> display = client->getInternalDisplayToken(); - if (display == nullptr) { - ALOGE("unable to get hdr capabilities for disconnected internal display"); - return false; - } - - ui::DynamicDisplayInfo info; - if (status_t err = client->getDynamicDisplayInfo(display, &info); err != NO_ERROR) { - ALOGE("unable to get hdr capabilities"); - return err; - } - - return !info.hdrCapabilities.getSupportedHdrTypes().empty(); -} - -static bool isDataSpaceValid(const sp<SurfaceControl>& surfaceControl, ADataSpace dataSpace) { - static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN)); - static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) == static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR)); - static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB)); - static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB)); - static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); - static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); - - switch (static_cast<android_dataspace_t>(dataSpace)) { - case HAL_DATASPACE_UNKNOWN: - case HAL_DATASPACE_V0_SRGB: - return true; - // These data space need wide gamut support. - case HAL_DATASPACE_V0_SCRGB_LINEAR: - case HAL_DATASPACE_V0_SCRGB: - case HAL_DATASPACE_DISPLAY_P3: - return getWideColorSupport(surfaceControl); - // These data space need HDR support. - case HAL_DATASPACE_BT2020_PQ: - if (!getHdrSupport(surfaceControl)) { - ALOGE("Invalid dataspace - device does not support hdr"); - return false; - } - return true; - default: - return false; - } -} +static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN)); +static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) == + static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR)); +static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB)); +static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB)); +static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == + static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); +static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { return reinterpret_cast<Transaction*>(aSurfaceTransaction); @@ -580,10 +524,6 @@ void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransac CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - if (!isDataSpaceValid(surfaceControl, aDataSpace)) { - ALOGE("Failed to set buffer dataspace - invalid dataspace"); - return; - } Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace)); } @@ -650,10 +590,6 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - if (!isDataSpaceValid(surfaceControl, dataspace)) { - ALOGE("Failed to set buffer dataspace - invalid dataspace"); - return; - } Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); half3 color; diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp index 472e0a4347fc..03dd707a1d09 100644 --- a/native/webview/plat_support/draw_functor.cpp +++ b/native/webview/plat_support/draw_functor.cpp @@ -77,7 +77,18 @@ void draw_gl(int functor, void* data, const uirenderer::DrawGlInfo& draw_gl_params, const uirenderer::WebViewOverlayData& overlay_params) { float gabcdef[7]; - draw_gl_params.color_space_ptr->transferFn(gabcdef); + if (draw_gl_params.color_space_ptr) { + draw_gl_params.color_space_ptr->transferFn(gabcdef); + } else { + // Assume sRGB. + gabcdef[0] = SkNamedTransferFn::kSRGB.g; + gabcdef[1] = SkNamedTransferFn::kSRGB.a; + gabcdef[2] = SkNamedTransferFn::kSRGB.b; + gabcdef[3] = SkNamedTransferFn::kSRGB.c; + gabcdef[4] = SkNamedTransferFn::kSRGB.d; + gabcdef[5] = SkNamedTransferFn::kSRGB.e; + gabcdef[6] = SkNamedTransferFn::kSRGB.f; + } AwDrawFn_DrawGLParams params = { .version = kAwDrawFnVersion, .clip_left = draw_gl_params.clipLeft, @@ -147,7 +158,18 @@ void drawVk(int functor, void* data, const uirenderer::WebViewOverlayData& overlay_params) { SupportData* support = static_cast<SupportData*>(data); float gabcdef[7]; - draw_vk_params.color_space_ptr->transferFn(gabcdef); + if (draw_vk_params.color_space_ptr) { + draw_vk_params.color_space_ptr->transferFn(gabcdef); + } else { + // Assume sRGB. + gabcdef[0] = SkNamedTransferFn::kSRGB.g; + gabcdef[1] = SkNamedTransferFn::kSRGB.a; + gabcdef[2] = SkNamedTransferFn::kSRGB.b; + gabcdef[3] = SkNamedTransferFn::kSRGB.c; + gabcdef[4] = SkNamedTransferFn::kSRGB.d; + gabcdef[5] = SkNamedTransferFn::kSRGB.e; + gabcdef[6] = SkNamedTransferFn::kSRGB.f; + } AwDrawFn_DrawVkParams params{ .version = kAwDrawFnVersion, .width = draw_vk_params.width, diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml index 2cf872cc7c71..1dcd3375c1cf 100644 --- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml @@ -20,7 +20,7 @@ <string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string> <string name="profile_name_watch" msgid="576290739483672360">"montre"</string> - <string name="confirmation_title" msgid="8455544820286920304">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pour gérer votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> + <string name="confirmation_title" msgid="8455544820286920304">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à gérer votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_summary" msgid="2059360676631420073">"Cette application est nécessaire pour gérer votre <xliff:g id="PROFILE_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%2$s</xliff:g>"</string> <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string> <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string> diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk Binary files differindex e88e1ba97ca7..0c3c4bb24208 100644 --- a/packages/CtsShim/apk/arm/CtsShim.apk +++ b/packages/CtsShim/apk/arm/CtsShim.apk diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk Binary files differindex f35732cec024..ee42d081f2f2 100644 --- a/packages/CtsShim/apk/arm/CtsShimPriv.apk +++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk Binary files differindex e88e1ba97ca7..0c3c4bb24208 100644 --- a/packages/CtsShim/apk/x86/CtsShim.apk +++ b/packages/CtsShim/apk/x86/CtsShim.apk diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk Binary files differindex 3d9f749f4e48..2bb3750b200d 100644 --- a/packages/CtsShim/apk/x86/CtsShimPriv.apk +++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk diff --git a/packages/PrintSpooler/res/values-ta/strings.xml b/packages/PrintSpooler/res/values-ta/strings.xml index 4bb167a07010..eaf05b104046 100644 --- a/packages/PrintSpooler/res/values-ta/strings.xml +++ b/packages/PrintSpooler/res/values-ta/strings.xml @@ -102,7 +102,7 @@ <item msgid="4061931020926489228">"உறுவப்படம்"</item> <item msgid="3199660090246166812">"நிலத்தோற்றம்"</item> </string-array> - <string name="print_write_error_message" msgid="5787642615179572543">"கோப்பில் எழுத முடியவில்லை"</string> + <string name="print_write_error_message" msgid="5787642615179572543">"ஃபைலில் எழுத முடியவில்லை"</string> <string name="print_error_default_message" msgid="8602678405502922346">"செயல்படவில்லை. மீண்டும் முயலவும்."</string> <string name="print_error_retry" msgid="1426421728784259538">"மீண்டும் முயலவும்"</string> <string name="print_error_printer_unavailable" msgid="8985614415253203381">"இப்போது பிரிண்டர் இல்லை."</string> diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp index e50019680deb..2f911c4e6546 100644 --- a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp @@ -18,6 +18,7 @@ android_library { "androidx.core_core", "com.google.android.material_material", "SettingsLibSettingsTransition", + "SettingsLibUtils", ], sdk_version: "system_current", min_sdk_version: "29", diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java index a1cd37189b51..84a6b36e3d7c 100644 --- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java @@ -28,6 +28,8 @@ import androidx.annotation.Nullable; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.FragmentActivity; +import com.android.settingslib.utils.BuildCompatUtils; + import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.resources.TextAppearanceConfig; @@ -44,10 +46,15 @@ public class CollapsingToolbarBaseActivity extends FragmentActivity { private CollapsingToolbarLayout mCollapsingToolbarLayout; @Nullable private AppBarLayout mAppBarLayout; + private int mCustomizeLayoutResId = 0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (mCustomizeLayoutResId > 0 && !BuildCompatUtils.isAtLeastS()) { + super.setContentView(mCustomizeLayoutResId); + return; + } // Force loading font synchronously for collapsing toolbar layout TextAppearanceConfig.setShouldLoadFontSynchronously(true); super.setContentView(R.layout.collapsing_toolbar_base_layout); @@ -81,12 +88,27 @@ public class CollapsingToolbarBaseActivity extends FragmentActivity { @Override public void setContentView(View view) { - ((ViewGroup) findViewById(R.id.content_frame)).addView(view); + final ViewGroup parent = findViewById(R.id.content_frame); + if (parent != null) { + parent.addView(view); + } } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { - ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); + final ViewGroup parent = findViewById(R.id.content_frame); + if (parent != null) { + parent.addView(view, params); + } + } + + /** + * This method allows an activity to replace the default layout with a customize layout. Notice + * that it will no longer apply the features being provided by this class when this method + * gets called. + */ + protected void setCustomizeContentView(int layoutResId) { + mCustomizeLayoutResId = layoutResId; } @Override diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 3814ed5b78fa..f2ab2f852dc6 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -452,7 +452,7 @@ <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ថេប្លេតអាចនឹងបិទក្នុងពេលបន្តិចទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ឧបករណ៍អាចនឹងបិទក្នុងពេលបន្តិចទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> - <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"នៅសល់ <xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string> + <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="7956120998372505295">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានដាក់កម្រិតការសាកថ្មជាបណ្ដោះអាសន្ន"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index ea6716595d16..864f177fcec9 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -452,13 +452,13 @@ <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"टॅबलेट लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"डिव्हाइस लवकरच बंद होऊ शकते (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> - <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहे"</string> + <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="7956120998372505295">"<xliff:g id="LEVEL">%1$s</xliff:g> • चार्जिंग तात्पुरते मर्यादित आहे"</string> <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> - <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"हळूहळू चार्ज होत आहे"</string> + <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"हळू चार्ज होत आहे"</string> <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेसने चार्ज होत आहे"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज होत नाही"</string> <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट केले, चार्ज होत नाही"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 0397eb8eaa1a..bb94c2476720 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -458,7 +458,7 @@ <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> - <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"बिस्तारै चार्ज गरिँदै"</string> + <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ढिलो चार्ज हुँदै छ"</string> <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस तरिकाले चार्ज गरिँदै छ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज भइरहेको छैन"</string> <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट गरिएको छ, चार्ज भइरहेको छैन"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index aecfd6247b9f..cf6013f969a6 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -458,7 +458,7 @@ <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> - <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"آہستہ چارج ہو رہا ہے"</string> + <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"آہستہ چارج ہو رہی ہے"</string> <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"وائرلیس طریقے سے چارج ہو رہی ہے"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"چارج نہیں ہو رہا ہے"</string> <string name="battery_info_status_not_charging" msgid="3371084153747234837">"منسلک ہے، چارج نہیں ہو رہی ہے"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml index 970efa67e075..400973b4e095 100644 --- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml @@ -170,7 +170,7 @@ <item msgid="3691785423374588514">"1M"</item> </string-array> <string-array name="select_logd_size_summaries"> - <item msgid="409235464399258501">"关闭"</item> + <item msgid="409235464399258501">"已关闭"</item> <item msgid="4195153527464162486">"每个日志缓冲区 64K"</item> <item msgid="7464037639415220106">"每个日志缓冲区 256K"</item> <item msgid="8539423820514360724">"每个日志缓冲区 1M"</item> @@ -184,7 +184,7 @@ <item msgid="7300881231043255746">"仅限内核"</item> </string-array> <string-array name="select_logpersist_summaries"> - <item msgid="97587758561106269">"关闭"</item> + <item msgid="97587758561106269">"已关闭"</item> <item msgid="7126170197336963369">"所有日志缓冲区"</item> <item msgid="7167543126036181392">"所有非无线电日志缓冲区"</item> <item msgid="5135340178556563979">"仅限内核日志缓冲区"</item> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index ac49b9913c44..e9914510debd 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -276,7 +276,7 @@ <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"正在流式传输:<xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"私人 DNS"</string> <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"选择私人 DNS 模式"</string> - <string name="private_dns_mode_off" msgid="7065962499349997041">"关闭"</string> + <string name="private_dns_mode_off" msgid="7065962499349997041">"已关闭"</string> <string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"自动"</string> <string name="private_dns_mode_provider" msgid="3619040641762557028">"私人 DNS 提供商主机名"</string> <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"输入 DNS 提供商的主机名"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index c3caa6d9577c..6d8a0b04bd5c 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -458,7 +458,7 @@ <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> - <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充電"</string> + <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"慢速充電中"</string> <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"無線充電中"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string> <string name="battery_info_status_not_charging" msgid="3371084153747234837">"已連接,非充電中"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java index 3b41fa99d6c4..4d0804e1bbb7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java +++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java @@ -72,9 +72,9 @@ public class SignalDrawable extends DrawableWrapper { private final int mLightModeFillColor; private final Path mCutoutPath = new Path(); private final Path mForegroundPath = new Path(); - private final Path mXPath = new Path(); - private final Matrix mXScaleMatrix = new Matrix(); - private final Path mScaledXPath = new Path(); + private final Path mAttributionPath = new Path(); + private final Matrix mAttributionScaleMatrix = new Matrix(); + private final Path mScaledAttributionPath = new Path(); private final Handler mHandler; private final float mCutoutWidthFraction; private final float mCutoutHeightFraction; @@ -85,10 +85,10 @@ public class SignalDrawable extends DrawableWrapper { public SignalDrawable(Context context) { super(context.getDrawable(com.android.internal.R.drawable.ic_signal_cellular)); - final String xPathString = context.getString( - com.android.internal.R.string.config_signalXPath); - mXPath.set(PathParser.createPathFromPathData(xPathString)); - updateScaledXPath(); + final String attributionPathString = context.getString( + com.android.internal.R.string.config_signalAttributionPath); + mAttributionPath.set(PathParser.createPathFromPathData(attributionPathString)); + updateScaledAttributionPath(); mCutoutWidthFraction = context.getResources().getFloat( com.android.internal.R.dimen.config_signalCutoutWidthFraction); mCutoutHeightFraction = context.getResources().getFloat( @@ -104,13 +104,14 @@ public class SignalDrawable extends DrawableWrapper { setDarkIntensity(0); } - private void updateScaledXPath() { + private void updateScaledAttributionPath() { if (getBounds().isEmpty()) { - mXScaleMatrix.setScale(1f, 1f); + mAttributionScaleMatrix.setScale(1f, 1f); } else { - mXScaleMatrix.setScale(getBounds().width() / VIEWPORT, getBounds().height() / VIEWPORT); + mAttributionScaleMatrix.setScale( + getBounds().width() / VIEWPORT, getBounds().height() / VIEWPORT); } - mXPath.transform(mXScaleMatrix, mScaledXPath); + mAttributionPath.transform(mAttributionScaleMatrix, mScaledAttributionPath); } @Override @@ -177,7 +178,7 @@ public class SignalDrawable extends DrawableWrapper { @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); - updateScaledXPath(); + updateScaledAttributionPath(); invalidateSelf(); } @@ -221,7 +222,7 @@ public class SignalDrawable extends DrawableWrapper { mCutoutPath.rLineTo(cutX, 0); mCutoutPath.rLineTo(0, cutY); canvas.drawPath(mCutoutPath, mTransparentPaint); - canvas.drawPath(mScaledXPath, mForegroundPaint); + canvas.drawPath(mScaledAttributionPath, mForegroundPaint); } if (isRtl) { canvas.restore(); diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index ae6165b80e74..60226084c70d 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -123,7 +123,6 @@ public class SecureSettings { Settings.Secure.SCREENSAVER_COMPONENTS, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, - Settings.Secure.LOCKDOWN_IN_POWER_MENU, Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index e09d4201e83e..6d7fb027ee99 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -177,7 +177,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.SCREENSAVER_COMPONENTS, COMMA_SEPARATED_COMPONENT_LIST_VALIDATOR); VALIDATORS.put(Secure.SCREENSAVER_ACTIVATE_ON_DOCK, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.LOCKDOWN_IN_POWER_MENU, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.VOLUME_HUSH_GESTURE, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put( diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index e5eecb2068e0..073b4d00653d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2224,9 +2224,6 @@ class SettingsProtoDumpUtil { Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, SecureSettingsProto.LOCK_TO_APP_EXIT_LOCKED); dumpSetting(s, p, - Settings.Secure.LOCKDOWN_IN_POWER_MENU, - SecureSettingsProto.LOCKDOWN_IN_POWER_MENU); - dumpSetting(s, p, Settings.Secure.LONG_PRESS_TIMEOUT, SecureSettingsProto.LONG_PRESS_TIMEOUT); diff --git a/packages/Shell/res/values-ta/strings.xml b/packages/Shell/res/values-ta/strings.xml index a906abede3fd..72698bac38e7 100644 --- a/packages/Shell/res/values-ta/strings.xml +++ b/packages/Shell/res/values-ta/strings.xml @@ -28,11 +28,11 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ஸ்கிரீன்ஷாட் இன்றி பிழை அறிக்கையை பகிர தேர்ந்தெடுக்கவும்/ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"பிழை அறிக்கைகளில் முறைமையின் பல்வேறு பதிவுக் கோப்புகளின் தரவு (இதில் முக்கியமானவை என நீங்கள் கருதும் பயன்பாடின் உபயோகம், இருப்பிடத் தரவு போன்றவை அடங்கும்) இருக்கும். நீங்கள் நம்பும் நபர்கள் மற்றும் பயன்பாடுகளுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"பிழை அறிக்கைகளில் முறைமையின் பல்வேறு பதிவு ஃபைல்களின் தரவு (இதில் முக்கியமானவை என நீங்கள் கருதும் பயன்பாடின் உபயோகம், இருப்பிடத் தரவு போன்றவை அடங்கும்) இருக்கும். நீங்கள் நம்பும் நபர்கள் மற்றும் பயன்பாடுகளுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"மீண்டும் காட்டாதே"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"பிழை அறிக்கைகள்"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"பிழை அறிக்கையைப் படிக்க முடியவில்லை"</string> - <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"பிழை அறிக்கை விவரங்களை ஜிப் கோப்பில் சேர்க்க முடியவில்லை"</string> + <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"பிழை அறிக்கை விவரங்களை ஜிப் ஃபைலில் சேர்க்க முடியவில்லை"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"பெயரிடப்படாதது"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"விவரங்கள்"</string> <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ஸ்கிரீன்ஷாட்"</string> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 8963ddaece35..1b2aefcd6ff0 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -451,6 +451,7 @@ <!-- started from SensoryPrivacyService --> <activity android:name=".sensorprivacy.SensorUseStartedActivity" android:exported="true" + android:launchMode="singleTop" android:permission="android.permission.MANAGE_SENSOR_PRIVACY" android:theme="@style/Theme.SystemUI.Dialog.Alert" android:finishOnCloseSystemDialogs="true"> diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp index 761b1f460bb5..1b15d20d2c52 100644 --- a/packages/SystemUI/animation/Android.bp +++ b/packages/SystemUI/animation/Android.bp @@ -36,7 +36,6 @@ android_library { static_libs: [ "PluginCoreLib", - "WindowManager-Shell", ], manifest: "AndroidManifest.xml", diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index ac9298dc9e89..a50efd731cf6 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -7,6 +7,7 @@ import android.app.ActivityManager import android.app.ActivityTaskManager import android.app.AppGlobals import android.app.PendingIntent +import android.app.TaskInfo import android.content.Context import android.graphics.Matrix import android.graphics.PorterDuff @@ -16,7 +17,6 @@ import android.graphics.RectF import android.graphics.drawable.GradientDrawable import android.os.Looper import android.os.RemoteException -import android.os.UserHandle import android.util.Log import android.util.MathUtils import android.view.IRemoteAnimationFinishedCallback @@ -31,20 +31,18 @@ import android.view.animation.AnimationUtils import android.view.animation.PathInterpolator import com.android.internal.annotations.VisibleForTesting import com.android.internal.policy.ScreenDecorationsUtils -import com.android.wm.shell.startingsurface.SplashscreenContentDrawer -import com.android.wm.shell.startingsurface.SplashscreenContentDrawer.SplashScreenWindowAttrs import kotlin.math.roundToInt +private const val TAG = "ActivityLaunchAnimator" + /** * A class that allows activities to be started in a seamless way from a view that is transforming * nicely into the starting window. */ class ActivityLaunchAnimator( - private val keyguardHandler: KeyguardHandler, + private val callback: Callback, context: Context ) { - private val TAG = this::class.java.simpleName - companion object { const val ANIMATION_DURATION = 500L private const val ANIMATION_DURATION_FADE_OUT_CONTENT = 150L @@ -120,7 +118,7 @@ class ActivityLaunchAnimator( Log.d(TAG, "Starting intent with a launch animation") val runner = Runner(controller) - val isOnKeyguard = keyguardHandler.isOnKeyguard() + val isOnKeyguard = callback.isOnKeyguard() // Pass the RemoteAnimationAdapter to the intent starter only if we are not on the keyguard. val animationAdapter = if (!isOnKeyguard) { @@ -163,7 +161,7 @@ class ActivityLaunchAnimator( // Hide the keyguard using the launch animation instead of the default unlock animation. if (isOnKeyguard) { - keyguardHandler.hideKeyguardWithAnimation(runner) + callback.hideKeyguardWithAnimation(runner) } } } @@ -212,7 +210,7 @@ class ActivityLaunchAnimator( fun startPendingIntent(animationAdapter: RemoteAnimationAdapter?): Int } - interface KeyguardHandler { + interface Callback { /** Whether we are currently on the keyguard or not. */ fun isOnKeyguard(): Boolean @@ -221,6 +219,9 @@ class ActivityLaunchAnimator( /** Enable/disable window blur so they don't overlap with the window launch animation **/ fun setBlursDisabledForAppLaunch(disabled: Boolean) + + /* Get the background color of [task]. */ + fun getBackgroundColor(task: TaskInfo): Int } /** @@ -233,11 +234,21 @@ class ActivityLaunchAnimator( /** * Return a [Controller] that will animate and expand [view] into the opening window. * - * Important: The view must be attached to the window when calling this function and - * during the animation. + * Important: The view must be attached to a [ViewGroup] when calling this function and + * during the animation. For safety, this method will return null when it is not. */ @JvmStatic - fun fromView(view: View, cujType: Int? = null): Controller { + fun fromView(view: View, cujType: Int? = null): Controller? { + if (view.parent !is ViewGroup) { + // TODO(b/192194319): Throw instead of just logging. + Log.wtf( + TAG, + "Skipping animation as view $view is not attached to a ViewGroup", + Exception() + ) + return null + } + return GhostedViewLaunchAnimatorController(view, cujType) } } @@ -474,7 +485,7 @@ class ActivityLaunchAnimator( // which is usually the same color of the app background. We first fade in this layer // to hide the expanding view, then we fade it out with SRC mode to draw a hole in the // launch container and reveal the opening window. - val windowBackgroundColor = extractSplashScreenBackgroundColor(window) + val windowBackgroundColor = callback.getBackgroundColor(window.taskInfo) val windowBackgroundLayer = GradientDrawable().apply { setColor(windowBackgroundColor) alpha = 0 @@ -490,7 +501,7 @@ class ActivityLaunchAnimator( animator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationStart(animation: Animator?, isReverse: Boolean) { Log.d(TAG, "Animation started") - keyguardHandler.setBlursDisabledForAppLaunch(true) + callback.setBlursDisabledForAppLaunch(true) controller.onLaunchAnimationStart(isExpandingFullyAbove) // Add the drawable to the launch container overlay. Overlays always draw @@ -501,7 +512,7 @@ class ActivityLaunchAnimator( override fun onAnimationEnd(animation: Animator?) { Log.d(TAG, "Animation ended") - keyguardHandler.setBlursDisabledForAppLaunch(false) + callback.setBlursDisabledForAppLaunch(false) iCallback?.invoke() controller.onLaunchAnimationEnd(isExpandingFullyAbove) launchContainerOverlay.remove(windowBackgroundLayer) @@ -553,36 +564,6 @@ class ActivityLaunchAnimator( animator.start() } - /** Extract the background color of the app splash screen. */ - private fun extractSplashScreenBackgroundColor(window: RemoteAnimationTarget): Int { - val taskInfo = window.taskInfo - val windowPackage = taskInfo.topActivity.packageName - val userId = taskInfo.userId - val windowContext = context.createPackageContextAsUser( - windowPackage, Context.CONTEXT_RESTRICTED, UserHandle.of(userId)) - val activityInfo = taskInfo.topActivityInfo - val splashScreenThemeName = packageManager.getSplashScreenTheme(windowPackage, userId) - val splashScreenThemeId = if (splashScreenThemeName != null) { - windowContext.resources.getIdentifier(splashScreenThemeName, null, null) - } else { - 0 - } - - val themeResId = when { - splashScreenThemeId != 0 -> splashScreenThemeId - activityInfo.themeResource != 0 -> activityInfo.themeResource - else -> com.android.internal.R.style.Theme_DeviceDefault_DayNight - } - - if (themeResId != windowContext.themeResId) { - windowContext.setTheme(themeResId) - } - - val windowAttrs = SplashScreenWindowAttrs() - SplashscreenContentDrawer.getWindowAttrs(windowContext, windowAttrs) - return SplashscreenContentDrawer.peekWindowBGColor(windowContext, windowAttrs) - } - private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) { val screenBounds = window.screenSpaceBounds val centerX = (screenBounds.left + screenBounds.right) / 2f diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt index ffb7ab4eff7c..b4ffb3f6cf4e 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt @@ -9,6 +9,7 @@ import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.graphics.drawable.InsetDrawable import android.graphics.drawable.LayerDrawable +import android.util.Log import android.view.GhostView import android.view.View import android.view.ViewGroup @@ -17,13 +18,15 @@ import android.widget.FrameLayout import com.android.internal.jank.InteractionJankMonitor import kotlin.math.min +private const val TAG = "GhostedViewLaunchAnimatorController" + /** * A base implementation of [ActivityLaunchAnimator.Controller] which creates a [ghost][GhostView] * of [ghostedView] as well as an expandable background view, which are drawn and animated instead * of the ghosted view. * - * Important: [ghostedView] must be attached to the window when calling this function and during the - * animation. + * Important: [ghostedView] must be attached to a [ViewGroup] when calling this function and during + * the animation. * * Note: Avoid instantiating this directly and call [ActivityLaunchAnimator.Controller.fromView] * whenever possible instead. @@ -113,6 +116,13 @@ open class GhostedViewLaunchAnimatorController( } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { + if (ghostedView.parent !is ViewGroup) { + // This should usually not happen, but let's make sure we don't crash if the view was + // detached right before we started the animation. + Log.w(TAG, "Skipping animation as ghostedView is not attached to a ViewGroup") + return + } + backgroundView = FrameLayout(launchContainer.context) launchContainerOverlay.add(backgroundView) @@ -138,7 +148,7 @@ open class GhostedViewLaunchAnimatorController( progress: Float, linearProgress: Float ) { - val ghostView = this.ghostView!! + val ghostView = this.ghostView ?: return val backgroundView = this.backgroundView!! if (!state.visible) { @@ -173,6 +183,11 @@ open class GhostedViewLaunchAnimatorController( } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { + if (ghostView == null) { + // We didn't actually run the animation. + return + } + cujType?.let { InteractionJankMonitor.getInstance().end(it) } backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java index 95c2d2efcd89..6d1408d5d212 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java @@ -72,7 +72,8 @@ public interface DetailAdapter { } /** - * @return if detail panel should animate when shown or closed + * Indicates whether the detail view wants to animate when shown. This has no affect over the + * closing animation. Detail panels will always animate when closed. */ default boolean shouldAnimate() { return true; diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index 34c892675a14..5ecbc9d31ac1 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -37,7 +37,7 @@ <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電中"</string> <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string> - <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string> + <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string> <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電暫時受限"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string> diff --git a/packages/SystemUI/res/anim/fp_to_unlock.xml b/packages/SystemUI/res/anim/fp_to_unlock.xml new file mode 100644 index 000000000000..a348208f48c7 --- /dev/null +++ b/packages/SystemUI/res/anim/fp_to_unlock.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android"> + <aapt:attr name="android:drawable"> + <vector android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46"> + <group android:name="_R_G"> + <group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5"> + <group android:name="_R_G_L_1_G" android:translateX="30.75" android:translateY="25.75"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " /> + <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " /> + <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " /> + <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " /> + </group> + </group> + <group android:name="_R_G_L_0_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5"> + <group android:name="_R_G_L_0_G" android:translateX="47.357" android:translateY="53.25" android:pivotX="2.75" android:pivotY="2.75" android:scaleX="1.41866" android:scaleY="1.41866"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#b7f29f" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M2.75 5.25 C4.13,5.25 5.25,4.13 5.25,2.75 C5.25,1.37 4.13,0.25 2.75,0.25 C1.37,0.25 0.25,1.37 0.25,2.75 C0.25,4.13 1.37,5.25 2.75,5.25c " /> + </group> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="0" android:valueFrom="M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " android:valueTo="M30.81 32.26 C30.56,32.49 30.27,38.76 29.96,38.9 C29.77,39.46 29.13,39.94 28.57,40.26 C28.15,40.51 26.93,40.65 26.4,40.65 C26.18,40.65 11.91,40.62 11.71,40.58 C10.68,40.53 9.06,39.79 8.89,38.88 C8.6,38.74 8.34,32.48 8.1,32.27 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="143" android:startOffset="107" android:valueFrom="M30.81 32.26 C30.56,32.49 30.27,38.76 29.96,38.9 C29.77,39.46 29.13,39.94 28.57,40.26 C28.15,40.51 26.93,40.65 26.4,40.65 C26.18,40.65 11.91,40.62 11.71,40.58 C10.68,40.53 9.06,39.79 8.89,38.88 C8.6,38.74 8.34,32.48 8.1,32.27 " android:valueTo="M30.64 30.14 C30.64,30.14 30.64,38.14 30.64,38.14 C30.64,38.77 30.36,39.32 29.91,39.69 C29.57,39.97 29.12,40.14 28.64,40.14 C28.64,40.14 10.14,40.14 10.14,40.14 C9.04,40.14 8.14,39.25 8.14,38.14 C8.14,38.14 8.14,30.14 8.14,30.14 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.331,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="strokeAlpha" android:duration="140" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="strokeAlpha" android:duration="50" android:startOffset="140" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="0" android:valueFrom="M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " android:valueTo="M18.93 32.18 C17.11,32.68 16.62,30.26 16.62,30.26 C16.62,28.78 17.81,27.59 19.39,27.59 C20.96,27.59 22.15,28.78 22.15,30.26 C22.15,30.26 22.15,30.34 22.15,30.34 C22.15,30.89 21.11,32.54 19.57,32.19 C19.19,32.1 20.48,31.09 20.34,30.71 C20.34,30.71 20.02,29.88 20.02,29.88 C19.88,29.5 19.53,29.25 19.15,29.25 C18.63,29.25 18,29.67 18,30.22 C18,30.57 18.06,31.08 18.32,31.51 C18.49,31.8 19.02,32.25 19.79,32.04 C20.41,31.7 20.38,31.36 20.38,31.36 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="107" android:valueFrom="M18.93 32.18 C17.11,32.68 16.62,30.26 16.62,30.26 C16.62,28.78 17.81,27.59 19.39,27.59 C20.96,27.59 22.15,28.78 22.15,30.26 C22.15,30.26 22.15,30.34 22.15,30.34 C22.15,30.89 21.11,32.54 19.57,32.19 C19.19,32.1 20.48,31.09 20.34,30.71 C20.34,30.71 20.02,29.88 20.02,29.88 C19.88,29.5 19.53,29.25 19.15,29.25 C18.63,29.25 18,29.67 18,30.22 C18,30.57 18.06,31.08 18.32,31.51 C18.49,31.8 19.02,32.25 19.79,32.04 C20.41,31.7 20.38,31.36 20.38,31.36 " android:valueTo="M19.42 31.53 C18.15,31.52 18.11,30.33 18.11,30.33 C18.11,29.59 18.66,28.98 19.4,28.98 C20.13,28.98 20.69,29.59 20.69,30.33 C20.69,30.33 20.69,30.37 20.69,30.37 C20.69,30.64 20.49,30.87 20.25,30.87 C20.07,30.87 19.91,30.74 19.84,30.55 C19.84,30.55 19.69,30.14 19.69,30.14 C19.63,29.94 19.46,29.82 19.28,29.82 C19.04,29.82 18.61,30.02 18.61,30.29 C18.61,30.43 18.6,30.75 18.76,31.03 C18.87,31.21 19.21,31.77 19.96,31.41 C20.69,31.01 20.69,30.34 20.69,30.34 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_2_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="250" android:startOffset="0" android:valueFrom="M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " android:valueTo="M8.14 30.22 C8.14,30.22 8.14,22.22 8.14,22.22 C8.14,21.71 8.33,21.25 8.64,20.9 C9,20.48 9.54,20.22 10.14,20.22 C10.14,20.22 28.64,20.22 28.64,20.22 C29.75,20.22 30.64,21.11 30.64,22.22 C30.64,22.22 30.64,30.14 30.64,30.14 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.189,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_3_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="95" android:startOffset="0" android:valueFrom="M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " android:valueTo="M11.47 14.84 C11.47,14.84 12.21,11.43 13.54,9.84 C14.84,8.28 16.68,7.22 19.35,7.22 C22.01,7.22 23.98,8.4 25.19,10.18 C26.39,11.96 27.25,14.84 27.25,14.84 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="24" android:startOffset="95" android:valueFrom="M11.47 14.84 C11.47,14.84 12.21,11.43 13.54,9.84 C14.84,8.28 16.68,7.22 19.35,7.22 C22.01,7.22 23.98,8.4 25.19,10.18 C26.39,11.96 27.25,14.84 27.25,14.84 " android:valueTo="M12.11 16.85 C12.11,16.85 12.82,12.71 13.37,11.5 C14.17,9.24 16.38,7.53 19.35,7.53 C22.32,7.53 24.61,9.32 25.35,11.72 C25.61,12.64 26.62,16.85 26.62,16.85 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.833,0.767 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="81" android:startOffset="119" android:valueFrom="M12.11 16.85 C12.11,16.85 12.82,12.71 13.37,11.5 C14.17,9.24 16.38,7.53 19.35,7.53 C22.32,7.53 24.61,9.32 25.35,11.72 C25.61,12.64 26.62,16.85 26.62,16.85 " android:valueTo="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.261,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="233" android:startOffset="200" android:valueFrom="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueTo="M37.91 20.05 C37.91,20.05 37.89,14.16 37.89,14.16 C37.89,10.79 35.15,8.05 31.86,8.03 C28.46,8.01 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.123,0 0.23,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="fillAlpha" android:duration="120" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="fillAlpha" android:duration="20" android:startOffset="120" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleX" android:duration="120" android:startOffset="0" android:valueFrom="1.4186600000000003" android:valueTo="1.4186600000000003" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="120" android:startOffset="0" android:valueFrom="1.4186600000000003" android:valueTo="1.4186600000000003" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleX" android:duration="130" android:startOffset="120" android:valueFrom="1.4186600000000003" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="130" android:startOffset="120" android:valueFrom="1.4186600000000003" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="517" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" /> + </set> + </aapt:attr> + </target> +</animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/lock_to_unlock.xml b/packages/SystemUI/res/anim/lock_to_unlock.xml new file mode 100644 index 000000000000..ec51c0171709 --- /dev/null +++ b/packages/SystemUI/res/anim/lock_to_unlock.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android"> + <aapt:attr name="android:drawable"> + <vector android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G_N_10_N_11_T_0" android:translateX="-27.5" android:translateY="-17.5"> + <group android:name="_R_G_L_2_G_N_10_T_1" android:translateX="50.25" android:translateY="61"> + <group android:name="_R_G_L_2_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5"> + <group android:name="_R_G_L_2_G" android:translateX="-0.375" android:translateY="-22.375"> + <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " /> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_1_G_N_10_N_11_T_0" android:translateX="-27.5" android:translateY="-17.5"> + <group android:name="_R_G_L_1_G_N_10_T_1" android:translateX="50.25" android:translateY="61"> + <group android:name="_R_G_L_1_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5"> + <group android:name="_R_G_L_1_G" android:translateX="5" android:translateY="-22.5"> + <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " /> + </group> + </group> + </group> + </group> + <group android:name="_R_G_L_0_G_N_10_N_11_T_0" android:translateX="-27.5" android:translateY="-17.5"> + <group android:name="_R_G_L_0_G_N_10_T_1" android:translateX="50.25" android:translateY="61"> + <group android:name="_R_G_L_0_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5"> + <group android:name="_R_G_L_0_G" android:translateX="11" android:translateY="-0.25" android:pivotX="2.75" android:pivotY="2.75" android:scaleX="1" android:scaleY="1"> + <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#b7f29f" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.75 5.25 C4.13,5.25 5.25,4.13 5.25,2.75 C5.25,1.37 4.13,0.25 2.75,0.25 C1.37,0.25 0.25,1.37 0.25,2.75 C0.25,4.13 1.37,5.25 2.75,5.25c " /> + </group> + </group> + </group> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> + <target android:name="_R_G_L_2_G_N_10_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="0" android:valueFrom="61" android:valueTo="57" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.369,0 0.6,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="133" android:valueFrom="57" android:valueTo="62.125" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.436,0 0.58,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="267" android:valueFrom="62.125" android:valueTo="61" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.449,0 0.469,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " android:valueTo="M2.5 9.94 C2.5,9.94 2.5,3.55 2.5,3.55 C2.5,0.17 5.3,-2.56 8.75,-2.56 C12.2,-2.56 15,0.17 15,3.55 C15,3.55 15,15 15,15 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.552,0 0.453,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="pathData" android:duration="333" android:startOffset="67" android:valueFrom="M2.5 9.94 C2.5,9.94 2.5,3.55 2.5,3.55 C2.5,0.17 5.3,-2.56 8.75,-2.56 C12.2,-2.56 15,0.17 15,3.55 C15,3.55 15,15 15,15 " android:valueTo="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.476,0 0.396,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_10_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="0" android:valueFrom="61" android:valueTo="57" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.369,0 0.6,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="133" android:valueFrom="57" android:valueTo="62.125" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.436,0 0.58,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="267" android:valueFrom="62.125" android:valueTo="61" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.449,0 0.469,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="0" android:valueFrom="1" android:valueTo="0.8200000000000001" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.415,0 0.338,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="0" android:valueFrom="1" android:valueTo="0.8200000000000001" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.415,0 0.338,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="100" android:valueFrom="0.8200000000000001" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.249,0 0.529,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="100" android:valueFrom="0.8200000000000001" android:valueTo="1" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.249,0 0.529,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_10_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="0" android:valueFrom="61" android:valueTo="57" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.369,0 0.6,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="133" android:startOffset="133" android:valueFrom="57" android:valueTo="62.125" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.436,0 0.58,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="267" android:valueFrom="62.125" android:valueTo="61" android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.449,0 0.469,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" android:duration="517" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" /> + </set> + </aapt:attr> + </target> +</animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml index 99e8116cb681..3c9e44e2dba9 100644 --- a/packages/SystemUI/res/layout/auth_biometric_contents.xml +++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml @@ -52,6 +52,7 @@ android:layout_width="@dimen/biometric_dialog_biometric_icon_size" android:layout_height="@dimen/biometric_dialog_biometric_icon_size" android:layout_gravity="center" + android:contentDescription="@null" android:scaleType="fitXY" /> </FrameLayout> diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml index 892f64b3123b..404365629aba 100644 --- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml +++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml @@ -131,6 +131,7 @@ <TextView android:id="@+id/messages_count" android:gravity="end" + android:layout_marginStart="-32dp" android:paddingStart="8dp" android:paddingEnd="8dp" android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title" @@ -147,6 +148,7 @@ android:id="@+id/predefined_icon" android:tint="?android:attr/textColorSecondary" android:gravity="end|center_vertical" + android:layout_marginStart="-24dp" android:layout_width="@dimen/regular_predefined_icon" android:layout_height="@dimen/regular_predefined_icon" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index dbbf641e4bf7..1a912023e33c 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -52,9 +52,12 @@ <include layout="@layout/dock_info_bottom_area_overlay" /> <com.android.keyguard.LockIconView + android:id="@+id/lock_icon_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:id="@+id/lock_icon_view" /> + android:padding="48px" + android:layout_gravity="center" + android:scaleType="centerCrop"/> <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/udfps_keyguard_view.xml b/packages/SystemUI/res/layout/udfps_keyguard_view.xml index 33baa4e07dc7..8834ac040b54 100644 --- a/packages/SystemUI/res/layout/udfps_keyguard_view.xml +++ b/packages/SystemUI/res/layout/udfps_keyguard_view.xml @@ -30,16 +30,15 @@ android:visibility="gone"/> <!-- Fingerprint --> - <!-- AOD dashed fingerprint icon with moving dashes --> <com.airbnb.lottie.LottieAnimationView android:id="@+id/udfps_aod_fp" android:layout_width="match_parent" android:layout_height="match_parent" + android:padding="48px" android:layout_gravity="center" android:scaleType="centerCrop" app:lottie_autoPlay="false" - android:padding="16dp" app:lottie_loop="true" app:lottie_rawRes="@raw/udfps_aod_fp"/> @@ -48,10 +47,10 @@ android:id="@+id/udfps_lockscreen_fp" android:layout_width="match_parent" android:layout_height="match_parent" + android:padding="48px" android:layout_gravity="center" android:scaleType="centerCrop" app:lottie_autoPlay="false" app:lottie_loop="false" - android:padding="16dp" app:lottie_rawRes="@raw/udfps_lockscreen_fp"/> </com.android.systemui.biometrics.UdfpsKeyguardView> diff --git a/packages/SystemUI/res/raw/udfps_aod_fp.json b/packages/SystemUI/res/raw/udfps_aod_fp.json index cdac33244345..3247fe74fcfe 100644 --- a/packages/SystemUI/res/raw/udfps_aod_fp.json +++ b/packages/SystemUI/res/raw/udfps_aod_fp.json @@ -1,1095 +1,1324 @@ { - "v": "5.7.8", - "fr": 60, - "ip": 0, - "op": 361, - "w": 180, - "h": 185, - "nm": "fingerprint_burn_in_Loop", - "ddd": 0, - "assets": [], - "layers": [ + "v":"5.7.8", + "fr":60, + "ip":0, + "op":361, + "w":46, + "h":65, + "nm":"fingerprint_burn_in_Loop_02", + "ddd":0, + "assets":[ + + ], + "layers":[ { - "ddd": 0, - "ind": 1, - "ty": 4, - "nm": "Layer 1 Outlines 10", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":2, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 9", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 ], [ - -3.684, + -1.701, + 0.42 + ], + [ + -1.757, 0 ], [ - -2.883, - -1.583 + -1.577, + -0.381 + ], + [ + -1.485, + -0.816 ] ], - "o": [ + "o":[ + [ + 1.455, + -0.799 + ], [ - 2.883, - -1.583 + 1.608, + -0.397 ], [ - 3.683, + 1.719, 0 ], [ + 1.739, + 0.42 + ], + [ 0, 0 ] ], - "v": [ + "v":[ [ - -10.417, - 1.25 + -9.818, + 1.227 ], [ - 0.001, - -1.25 + -5.064, + -0.618 + ], + [ + 0, + -1.227 + ], + [ + 4.96, + -0.643 ], [ - 10.417, - 1.25 + 9.818, + 1.227 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 17, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 246 - ] - }, - { - "t": 360, - "s": [ - 1326 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false + }, + { + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 7.477 + ], + "ix":2 + }, + "a":{ + "a":0, + "k":[ + 0, + 0 + ], + "ix":1 + }, + "s":{ + "a":0, + "k":[ + 100, + 100 + ], + "ix":3 + }, + "r":{ + "a":0, + "k":0, + "ix":6 + }, + "o":{ + "a":0, + "k":100, + "ix":7 + }, + "sk":{ + "a":0, + "k":0, + "ix":4 + }, + "sa":{ + "a":0, + "k":0, + "ix":5 + }, + "nm":"Transform" + } + ], + "nm":"Top", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":17, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 246 + ] + }, + { + "t":360, + "s":[ + 1326 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false + }, + { + "ty":"gr", + "it":[ + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":17, + "ix":2 + }, + "o":{ + "a":0, + "k":0, + "ix":3 + }, + "m":1, + "ix":1, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.999, - 7.5 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 0, + 0 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 3", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Group 1", + "np":1, + "cix":2, + "bm":0, + "ix":3, + "mn":"ADBE Vector Group", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 2, - "ty": 4, - "nm": "Layer 1 Outlines 5", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":3, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 8", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 ], [ - -3.684, + -1.701, + 0.42 + ], + [ + -1.757, 0 ], [ - -2.883, - -1.583 + -1.577, + -0.381 + ], + [ + -1.485, + -0.816 ] ], - "o": [ + "o":[ + [ + 1.455, + -0.799 + ], [ - 2.883, - -1.583 + 1.608, + -0.397 ], [ - 3.683, + 1.719, 0 ], [ + 1.739, + 0.42 + ], + [ 0, 0 ] ], - "v": [ + "v":[ [ - -10.417, - 1.25 + -9.818, + 1.227 ], [ - 0.001, - -1.25 + -5.064, + -0.618 + ], + [ + 0, + -1.227 + ], + [ + 4.96, + -0.643 ], [ - 10.417, - 1.25 + 9.818, + 1.227 ] ], - "c": false + "c":false }, - "ix": 2 + "ix":2 }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 54, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 360, - "s": [ - 1080 - ] - } - ], - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.999, - 7.5 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 7.477 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 3", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Top", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":54, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 0 + ] + }, + { + "t":360, + "s":[ + 1080 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 3, - "ty": 4, - "nm": "Layer 1 Outlines 8", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":4, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 7", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 ], [ - -5.883, + -2.446, + 1.161 + ], + [ + -1.168, + 0.275 + ], + [ + -1.439, 0 ], [ - -2.367, - -3.933 + -1.301, + -0.304 + ], + [ + -1.225, + -0.66 + ], + [ + -1.11, + -1.844 ] ], - "o": [ + "o":[ + [ + 1.23, + -2.044 + ], [ - 2.367, - -3.933 + 1.024, + -0.486 ], [ - 5.883, + 1.312, + -0.31 + ], + [ + 1.425, 0 ], [ + 1.454, + 0.34 + ], + [ + 2.122, + 1.143 + ], + [ 0, 0 ] ], - "v": [ + "v":[ + [ + -13.091, + 3.273 + ], [ - -13.75, - 3.333 + -7.438, + -1.646 + ], + [ + -4.14, + -2.797 ], [ 0, - -3.333 + -3.273 + ], + [ + 4.104, + -2.805 ], [ - 13.75, - 3.333 + 8.141, + -1.29 + ], + [ + 13.091, + 3.273 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 38.235, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 170 - ] - }, - { - "t": 360, - "s": [ - 890 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 20, - 16.25 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 16.069 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 2", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Mid Top", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":38.2, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 170 + ] + }, + { + "t":360, + "s":[ + 890 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 4, - "ty": 4, - "nm": "Layer 1 Outlines 4", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":5, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 6", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 ], [ - -5.883, + -2.446, + 1.161 + ], + [ + -1.168, + 0.275 + ], + [ + -1.439, 0 ], [ - -2.367, - -3.933 + -1.301, + -0.304 + ], + [ + -1.225, + -0.66 + ], + [ + -1.11, + -1.844 ] ], - "o": [ + "o":[ + [ + 1.23, + -2.044 + ], [ - 2.367, - -3.933 + 1.024, + -0.486 ], [ - 5.883, + 1.312, + -0.31 + ], + [ + 1.425, 0 ], [ + 1.454, + 0.34 + ], + [ + 2.122, + 1.143 + ], + [ 0, 0 ] ], - "v": [ + "v":[ + [ + -13.091, + 3.273 + ], + [ + -7.438, + -1.646 + ], [ - -13.75, - 3.333 + -4.14, + -2.797 ], [ 0, - -3.333 + -3.273 + ], + [ + 4.104, + -2.805 + ], + [ + 8.141, + -1.29 ], [ - 13.75, - 3.333 + 13.091, + 3.273 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 34.235, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 360, - "s": [ - 720 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 20, - 16.25 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 16.069 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 2", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Mid Top", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":34.2, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 0 + ] + }, + { + "t":360, + "s":[ + 720 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 5, - "ty": 4, - "nm": "Layer 1 Outlines 7", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":6, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 5", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 @@ -1099,61 +1328,61 @@ 0 ], [ - -6.65, + -6.53, 0 ], [ 0, - -5.9 + -5.793 ], [ 0, 0 ], [ - 2.333, + 2.159, 0 ], [ - 0.633, - 1.601 + 0.59, + 1.489 ], [ 0, 0 ], [ - 1.717, + 1.587, 0 ], [ 0, - 0 + -2.16 ], [ - 0, - -2.2 + -0.81, + -1.363 ], [ - -2.15, - -1.716 + -0.844, + -0.674 ], [ 0, 0 ] ], - "o": [ + "o":[ [ - -0.767, - -2.134 + -0.753, + -2.095 ], [ 0, - -5.917 + -5.793 ], [ - 6.65, + 6.529, 0 ], [ @@ -1162,10 +1391,10 @@ ], [ 0, - 2.333 + 2.16 ], [ - -1.734, + -1.604, 0 ], [ @@ -1173,20 +1402,20 @@ 0 ], [ - -0.634, - -1.599 + -0.589, + -1.489 ], [ - 0, + -2.161, 0 ], [ - -2.2, - 0 + 0, + 1.62 ], [ - 0, - 2.75 + 0.54, + 0.909 ], [ 0, @@ -1197,274 +1426,274 @@ 0 ] ], - "v": [ + "v":[ [ - -11.108, - 5.825 + -10.702, + 5.728 ], [ - -11.875, - 1.525 + -11.454, + 1.506 ], [ - -0.208, - -9.175 + 0.001, + -9 ], [ - 11.875, - 1.525 + 11.454, + 1.506 ], [ - 11.875, - 1.592 + 11.454, + 1.817 ], [ - 7.659, - 5.808 + 7.544, + 5.728 ], [ - 3.742, - 3.158 + 3.926, + 3.273 ], [ - 2.526, - 0.141 + 2.618, + 0 ], [ - -1.391, - -2.508 + -0.997, + -2.454 ], [ - -1.641, - -2.508 + -4.91, + 1.457 ], [ - -5.625, - 1.475 + -3.657, + 6.014 ], [ - -2.225, - 8.558 + -1.57, + 8.412 ], [ - -1.458, - 9.175 + -0.818, + 9 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 35, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - -159 - ] - }, - { - "t": 360, - "s": [ - 201 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 4, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.992, - 28.758 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 28.341 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 4", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Inside to dot ", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":35, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + -159 + ] + }, + { + "t":360, + "s":[ + 201 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 6, - "ty": 4, - "nm": "Layer 1 Outlines 6", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":7, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 4", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 @@ -1474,61 +1703,61 @@ 0 ], [ - -6.65, + -6.53, 0 ], [ 0, - -5.9 + -5.793 ], [ 0, 0 ], [ - 2.333, + 2.159, 0 ], [ - 0.633, - 1.601 + 0.59, + 1.489 ], [ 0, 0 ], [ - 1.717, + 1.587, 0 ], [ 0, - 0 + -2.16 ], [ - 0, - -2.2 + -0.81, + -1.363 ], [ - -2.15, - -1.716 + -0.844, + -0.674 ], [ 0, 0 ] ], - "o": [ + "o":[ [ - -0.767, - -2.134 + -0.753, + -2.095 ], [ 0, - -5.917 + -5.793 ], [ - 6.65, + 6.529, 0 ], [ @@ -1537,10 +1766,10 @@ ], [ 0, - 2.333 + 2.16 ], [ - -1.734, + -1.604, 0 ], [ @@ -1548,20 +1777,20 @@ 0 ], [ - -0.634, - -1.599 + -0.589, + -1.489 ], [ - 0, + -2.161, 0 ], [ - -2.2, - 0 + 0, + 1.62 ], [ - 0, - 2.75 + 0.54, + 0.909 ], [ 0, @@ -1572,274 +1801,274 @@ 0 ] ], - "v": [ + "v":[ [ - -11.108, - 5.825 + -10.702, + 5.728 ], [ - -11.875, - 1.525 + -11.454, + 1.506 ], [ - -0.208, - -9.175 + 0.001, + -9 ], [ - 11.875, - 1.525 + 11.454, + 1.506 ], [ - 11.875, - 1.592 + 11.454, + 1.817 ], [ - 7.659, - 5.808 + 7.544, + 5.728 ], [ - 3.742, - 3.158 + 3.926, + 3.273 ], [ - 2.526, - 0.141 + 2.618, + 0 ], [ - -1.391, - -2.508 + -0.997, + -2.454 ], [ - -1.641, - -2.508 + -4.91, + 1.457 ], [ - -5.625, - 1.475 + -3.657, + 6.014 ], [ - -2.225, - 8.558 + -1.57, + 8.412 ], [ - -1.458, - 9.175 + -0.818, + 9 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 9, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 135 - ] - }, - { - "t": 360, - "s": [ - 495 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 4, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.992, - 28.758 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 28.341 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 4", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Inside to dot ", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":9, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 135 + ] + }, + { + "t":360, + "s":[ + 495 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 7, - "ty": 4, - "nm": "Layer 1 Outlines 3", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":8, + "ty":4, + "nm":"Fingerprint_20210701 Outlines 3", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 @@ -1849,61 +2078,61 @@ 0 ], [ - -6.65, + -6.53, 0 ], [ 0, - -5.9 + -5.793 ], [ 0, 0 ], [ - 2.333, + 2.159, 0 ], [ - 0.633, - 1.601 + 0.59, + 1.489 ], [ 0, 0 ], [ - 1.717, + 1.587, 0 ], [ 0, - 0 + -2.16 ], [ - 0, - -2.2 + -0.81, + -1.363 ], [ - -2.15, - -1.716 + -0.844, + -0.674 ], [ 0, 0 ] ], - "o": [ + "o":[ [ - -0.767, - -2.134 + -0.753, + -2.095 ], [ 0, - -5.917 + -5.793 ], [ - 6.65, + 6.529, 0 ], [ @@ -1912,10 +2141,10 @@ ], [ 0, - 2.333 + 2.16 ], [ - -1.734, + -1.604, 0 ], [ @@ -1923,20 +2152,20 @@ 0 ], [ - -0.634, - -1.599 + -0.589, + -1.489 ], [ - 0, + -2.161, 0 ], [ - -2.2, - 0 + 0, + 1.62 ], [ - 0, - 2.75 + 0.54, + 0.909 ], [ 0, @@ -1947,499 +2176,527 @@ 0 ] ], - "v": [ + "v":[ [ - -11.108, - 5.825 + -10.702, + 5.728 ], [ - -11.875, - 1.525 + -11.454, + 1.506 ], [ - -0.208, - -9.175 + 0.001, + -9 ], [ - 11.875, - 1.525 + 11.454, + 1.506 ], [ - 11.875, - 1.592 + 11.454, + 1.817 ], [ - 7.659, - 5.808 + 7.544, + 5.728 ], [ - 3.742, - 3.158 + 3.926, + 3.273 ], [ - 2.526, - 0.141 + 2.618, + 0 ], [ - -1.391, - -2.508 + -0.997, + -2.454 ], [ - -1.641, - -2.508 + -4.91, + 1.457 ], [ - -5.625, - 1.475 + -3.657, + 6.014 ], [ - -2.225, - 8.558 + -1.57, + 8.412 ], [ - -1.458, - 9.175 + -0.818, + 9 ] ], - "c": false + "c":false }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 30, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 360, - "s": [ - 360 - ] - } - ], - "ix": 3 + "ix":2 }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 4, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.992, - 28.758 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 28.341 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 4", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Inside to dot ", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":30, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 0 + ] + }, + { + "t":360, + "s":[ + 360 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 }, { - "ddd": 0, - "ind": 8, - "ty": 4, - "nm": "Layer 1 Outlines 2", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 + "ddd":0, + "ind":9, + "ty":4, + "nm":"Fingerprint_20210701 Outlines", + "sr":1, + "ks":{ + "o":{ + "a":0, + "k":100, + "ix":11 }, - "r": { - "a": 0, - "k": 0, - "ix": 10 + "r":{ + "a":0, + "k":0, + "ix":10 }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, + "p":{ + "a":0, + "k":[ + 23.091, + 32.5, 0 ], - "ix": 2, - "l": 2 + "ix":2, + "l":2 }, - "a": { - "a": 0, - "k": [ - 20, - 25, + "a":{ + "a":0, + "k":[ + 19.341, + 24.25, 0 ], - "ix": 1, - "l": 2 + "ix":1, + "l":2 }, - "s": { - "a": 0, - "k": [ - 350, - 350, + "s":{ + "a":0, + "k":[ + 100, + 100, 100 ], - "ix": 6, - "l": 2 + "ix":6, + "l":2 } }, - "ao": 0, - "shapes": [ + "ao":0, + "shapes":[ { - "ty": "gr", - "it": [ + "ty":"gr", + "it":[ { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ + "ind":0, + "ty":"sh", + "ix":1, + "ks":{ + "a":0, + "k":{ + "i":[ [ 0, 0 ], [ - 3.2, + 1.307, + -0.561 + ], + [ + 0.894, + -0.16 + ], + [ + 0.706, 0 ], [ - 2.217, - 2.066 + 0.844, + 0.193 + ], + [ + 0.728, + 0.334 + ], + [ + 0.967, + 0.901 ] ], - "o": [ + "o":[ [ - -2.217, - 2.066 + -1.038, + 0.967 ], [ - -3.2, + -0.817, + 0.351 + ], + [ + -0.673, + 0.12 + ], + [ + -0.9, 0 ], [ + -0.794, + -0.182 + ], + [ + -1.203, + -0.551 + ], + [ 0, 0 ] ], - "v": [ + "v":[ [ - 8.75, - -1.667 + 8.182, + -1.636 ], [ - 0, - 1.667 + 4.642, + 0.681 + ], + [ + 2.07, + 1.453 + ], + [ + -0.001, + 1.636 + ], + [ + -2.621, + 1.341 + ], + [ + -4.909, + 0.563 ], [ - -8.75, - -1.667 + -8.182, + -1.636 ] ], - "c": false + "c":false }, - "ix": 2 + "ix":2 }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false + "nm":"Path 1", + "mn":"ADBE Vector Shape - Group", + "hd":false }, { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 69, - "ix": 2 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 360, - "s": [ - 720 - ] - } - ], - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ + "ty":"st", + "c":{ + "a":0, + "k":[ 1, 1, 1, 1 ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 1, - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "d": [ - { - "n": "d", - "nm": "dash", - "v": { - "a": 0, - "k": 0, - "ix": 1 - } - }, - { - "n": "o", - "nm": "offset", - "v": { - "a": 0, - "k": 25, - "ix": 7 - } - } - ], - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false + "ix":3 + }, + "o":{ + "a":0, + "k":100, + "ix":4 + }, + "w":{ + "a":0, + "k":1, + "ix":5 + }, + "lc":2, + "lj":1, + "ml":10, + "bm":0, + "nm":"Stroke 1", + "mn":"ADBE Vector Graphic - Stroke", + "hd":false }, { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 20, - 42.083 + "ty":"tr", + "p":{ + "a":0, + "k":[ + 19.341, + 40.614 ], - "ix": 2 + "ix":2 }, - "a": { - "a": 0, - "k": [ + "a":{ + "a":0, + "k":[ 0, 0 ], - "ix": 1 + "ix":1 }, - "s": { - "a": 0, - "k": [ + "s":{ + "a":0, + "k":[ 100, 100 ], - "ix": 3 + "ix":3 }, - "r": { - "a": 0, - "k": 0, - "ix": 6 + "r":{ + "a":0, + "k":0, + "ix":6 }, - "o": { - "a": 0, - "k": 100, - "ix": 7 + "o":{ + "a":0, + "k":100, + "ix":7 }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 + "sk":{ + "a":0, + "k":0, + "ix":4 }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 + "sa":{ + "a":0, + "k":0, + "ix":5 }, - "nm": "Transform" + "nm":"Transform" } ], - "nm": "Group 1", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false + "nm":"Bottom", + "np":2, + "cix":2, + "bm":0, + "ix":1, + "mn":"ADBE Vector Group", + "hd":false + }, + { + "ty":"tm", + "s":{ + "a":0, + "k":0, + "ix":1 + }, + "e":{ + "a":0, + "k":69, + "ix":2 + }, + "o":{ + "a":1, + "k":[ + { + "i":{ + "x":[ + 0.833 + ], + "y":[ + 0.833 + ] + }, + "o":{ + "x":[ + 0.167 + ], + "y":[ + 0.167 + ] + }, + "t":0, + "s":[ + 0 + ] + }, + { + "t":360, + "s":[ + 720 + ] + } + ], + "ix":3 + }, + "m":1, + "ix":2, + "nm":"Trim Paths 1", + "mn":"ADBE Vector Filter - Trim", + "hd":false } ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 + "ip":0, + "op":600, + "st":0, + "bm":0 } ], - "markers": [ + "markers":[ { - "tm": 210, - "cm": "2", - "dr": 0 + "tm":210, + "cm":"2", + "dr":0 }, { - "tm": 255, - "cm": "1", - "dr": 0 + "tm":255, + "cm":"1", + "dr":0 } ] }
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json index cef433ef95d2..a25a47595fe7 100644 --- a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json +++ b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json @@ -1,1017 +1 @@ -{ - "v": "5.7.8", - "fr": 60, - "ip": 0, - "op": 46, - "w": 180, - "h": 185, - "nm": "fingerprint_build_on", - "ddd": 0, - "assets": [], - "layers": [ - { - "ddd": 0, - "ind": 1, - "ty": 4, - "nm": "fingerprint_build_on", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 - }, - "r": { - "a": 0, - "k": 0, - "ix": 10 - }, - "p": { - "a": 0, - "k": [ - 91.456, - 92.206, - 0 - ], - "ix": 2, - "l": 2 - }, - "a": { - "a": 0, - "k": [ - 20, - 25, - 0 - ], - "ix": 1, - "l": 2 - }, - "s": { - "a": 0, - "k": [ - 350, - 350, - 100 - ], - "ix": 6, - "l": 2 - } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0, - 0 - ], - [ - 3.2, - 0 - ], - [ - 2.217, - 2.066 - ] - ], - "o": [ - [ - -2.217, - 2.066 - ], - [ - -3.2, - 0 - ], - [ - 0, - 0 - ] - ], - "v": [ - [ - 8.75, - -1.667 - ], - [ - 0, - 1.667 - ], - [ - -8.75, - -1.667 - ] - ], - "c": false - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 100, - "ix": 2 - }, - "o": { - "a": 0, - "k": 0, - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ - 1, - 1, - 1, - 1 - ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0 - ], - "y": [ - 1 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 24, - "s": [ - 2.5 - ] - } - ], - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "d": [ - { - "n": "d", - "nm": "dash", - "v": { - "a": 0, - "k": 0, - "ix": 1 - } - }, - { - "n": "o", - "nm": "offset", - "v": { - "a": 0, - "k": 0, - "ix": 7 - } - } - ], - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 20, - 42.083 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 0, - "k": 100, - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - }, - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0, - 0 - ], - [ - -5.883, - 0 - ], - [ - -2.367, - -3.933 - ] - ], - "o": [ - [ - 2.367, - -3.933 - ], - [ - 5.883, - 0 - ], - [ - 0, - 0 - ] - ], - "v": [ - [ - -13.75, - 3.333 - ], - [ - 0, - -3.333 - ], - [ - 13.75, - 3.333 - ] - ], - "c": false - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 100, - "ix": 2 - }, - "o": { - "a": 0, - "k": 0, - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ - 1, - 1, - 1, - 1 - ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0 - ], - "y": [ - 1 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 24, - "s": [ - 2.5 - ] - } - ], - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 20, - 16.25 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 0, - "k": 100, - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "Group 2", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 2, - "mn": "ADBE Vector Group", - "hd": false - }, - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0, - 0 - ], - [ - -3.684, - 0 - ], - [ - -2.883, - -1.583 - ] - ], - "o": [ - [ - 2.883, - -1.583 - ], - [ - 3.683, - 0 - ], - [ - 0, - 0 - ] - ], - "v": [ - [ - -10.417, - 1.25 - ], - [ - 0.001, - -1.25 - ], - [ - 10.417, - 1.25 - ] - ], - "c": false - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 100, - "ix": 2 - }, - "o": { - "a": 0, - "k": 0, - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ - 1, - 1, - 1, - 1 - ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0 - ], - "y": [ - 1 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 24, - "s": [ - 2.5 - ] - } - ], - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.999, - 7.5 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 0, - "k": 100, - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "Group 3", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 3, - "mn": "ADBE Vector Group", - "hd": false - }, - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - -6.65, - 0 - ], - [ - 0, - -5.9 - ], - [ - 0, - 0 - ], - [ - 2.333, - 0 - ], - [ - 0.633, - 1.601 - ], - [ - 0, - 0 - ], - [ - 1.717, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - -2.2 - ], - [ - -2.15, - -1.716 - ], - [ - 0, - 0 - ] - ], - "o": [ - [ - -0.767, - -2.134 - ], - [ - 0, - -5.917 - ], - [ - 6.65, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 2.333 - ], - [ - -1.734, - 0 - ], - [ - 0, - 0 - ], - [ - -0.634, - -1.599 - ], - [ - 0, - 0 - ], - [ - -2.2, - 0 - ], - [ - 0, - 2.75 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ] - ], - "v": [ - [ - -11.108, - 5.825 - ], - [ - -11.875, - 1.525 - ], - [ - -0.208, - -9.175 - ], - [ - 11.875, - 1.525 - ], - [ - 11.875, - 1.592 - ], - [ - 7.659, - 5.808 - ], - [ - 3.742, - 3.158 - ], - [ - 2.526, - 0.141 - ], - [ - -1.391, - -2.508 - ], - [ - -1.641, - -2.508 - ], - [ - -5.625, - 1.475 - ], - [ - -2.225, - 8.558 - ], - [ - -1.458, - 9.175 - ] - ], - "c": false - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "tm", - "s": { - "a": 0, - "k": 0, - "ix": 1 - }, - "e": { - "a": 0, - "k": 100, - "ix": 2 - }, - "o": { - "a": 0, - "k": 0, - "ix": 3 - }, - "m": 1, - "ix": 2, - "nm": "Trim Paths 1", - "mn": "ADBE Vector Filter - Trim", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ - 1, - 1, - 1, - 1 - ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0 - ], - "y": [ - 1 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 0, - "s": [ - 0 - ] - }, - { - "t": 24, - "s": [ - 2.5 - ] - } - ], - "ix": 5 - }, - "lc": 2, - "lj": 1, - "ml": 10, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 19.992, - 28.758 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 0, - "k": 100, - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "Group 4", - "np": 3, - "cix": 2, - "bm": 0, - "ix": 4, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 600, - "st": 0, - "bm": 0 - } - ], - "markers": [ - { - "tm": 210, - "cm": "2", - "dr": 0 - }, - { - "tm": 255, - "cm": "1", - "dr": 0 - } - ] -}
\ No newline at end of file +{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index d9a3da392fc5..d60d0823af17 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> መልዕክት ልከዋል፦ <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ምስል ልኳል"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> የሁኔታ ዝማኔ አለው፦ <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"የሚገኙ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"የባትሪ መለኪያዎን የማንበብ ችግር"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ለበለጠ መረጃ መታ ያድርጉ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ምንም ማንቂያ አልተቀናበረም"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index bfcfd9bd41d5..6195e5fdb062 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -1173,8 +1173,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"تم إرسال رسالة من <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"تم إرسال صورة من <xliff:g id="NAME">%1$s</xliff:g>."</string> <string name="new_status_content_description" msgid="6046637888641308327">"تم تعديل حالة <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"متاح"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"حدثت مشكلة أثناء قراءة مقياس مستوى شحن البطارية."</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"انقر للحصول على مزيد من المعلومات."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"لم يتم ضبط منبّه."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 316c87b18df0..bc5a91a6b859 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -427,7 +427,7 @@ <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> - <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰ অৱৰোধৰ পৰা আঁতৰাবনে?"</string> + <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইচৰ কেমেৰা আৰু মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"এইটোৱে আপোনাৰ মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এইটোৱে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>এ এটা বাৰ্তা পঠিয়াইছে: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>এ এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>ৰ এটা স্থিতিৰ আপডে’ট আছে: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"উপলব্ধ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"আপোনাৰ বেটাৰী মিটাৰ পঢ়োঁতে সমস্যা হৈছে"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"অধিক তথ্যৰ বাবে টিপক"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"কোনো এলাৰ্ম ছেট কৰা হোৱা নাই"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index ede3b1697fd7..54790897af76 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -429,9 +429,9 @@ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonu blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerası blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası və mikrofonu blokdan çıxarılsın?"</string> - <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Bu, mikrofonunuzdan istifadə etməyə icazə verilən bütün tətbiq və xidmətlər üçün girişi blokdan çıxarır."</string> - <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Bu, kameranızdan istifadə etməyə icazə verilən bütün tətbiq və xidmətlər üçün girişi blokdan çıxarır."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Bu, kamera və ya mikrofonunuzdan istifadə etməyə icazə verilən bütün tətbiq və xidmətlər üçün girişi blokdan çıxarır."</string> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tətbiqləri cəld dəyişmək üçün sağa çəkin"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> mesaj göndərdi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> şəkil göndərdi"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> status güncəlləməsi edib: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Əlçatan"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Batareya ölçüsünü oxuyarkən problem yarandı"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ətraflı məlumat üçün toxunun"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Siqnal ayarlanmayıb"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 8cbc8bd31e41..491cdcd6917d 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -1161,8 +1161,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> прыслаў паведамленне: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> адправіў відарыс"</string> <string name="new_status_content_description" msgid="6046637888641308327">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> абнавіў стан: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Даступна"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Праблема з чытаннем індыкатара зараду акумулятара"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Націсніце, каб убачыць больш"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Няма будзільнікаў"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 2fe583a6abc7..46aea0634555 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> একটি মেসেজ পাঠিয়েছেন: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> একটি ছবি পাঠিয়েছেন"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> একটি স্ট্যাটাস আপডেট করেছেন: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"উপস্থিত আছেন"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ব্যাটারির মিটারের রিডিং নেওয়ার সময় সমস্যা হয়েছে"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"আরও তথ্যের জন্য ট্যাপ করুন"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"কোনও অ্যালার্ম সেট করা নেই"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index abd4fddaee25..37fdbc1faaa3 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ha enviat un missatge: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ha enviat una imatge"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> té una actualització d\'estat: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponible"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Hi ha hagut un problema en llegir el mesurador de la bateria"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toca per obtenir més informació"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Cap alarma configurada"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 06f6a35199e4..feb0dae9779e 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> har sendt en besked: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> har sendt et billede"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> har opdateret sin status: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Tilgængelig"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Der er problemer med at aflæse dit batteriniveau"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tryk for at få flere oplysninger"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ingen alarm er indstillet"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 0e602645c1f7..99a90cc1471e 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έστειλε ένα μήνυμα: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έστειλε μια εικόνα"</string> <string name="new_status_content_description" msgid="6046637888641308327">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έχει μια ενημέρωση κατάστασης: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Διαθέσιμος"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Υπάρχει κάποιο πρόβλημα με την ανάγνωση του μετρητή μπαταρίας"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Πατήστε για περισσότερες πληροφορίες."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Δεν ορίστηκε ξυπνητ."</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index b5b82c8ed2b4..a431258e742d 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Quieres desbloquear la cámara y el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar el micrófono."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara o el micrófono."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción permite que todas las aplicaciones y servicios que tengan permiso puedan usar la cámara o el micrófono."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de app"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra a la derecha para cambiar aplicaciones rápidamente"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> envió un mensaje: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> envió una imagen"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> actualizó su estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponible"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema al leer el medidor de batería"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Presiona para obtener más información"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"No se estableció alarma"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 9cdfe0a2cfdb..0fa33e739c30 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -429,9 +429,9 @@ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Desbloquear el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Desbloquear la cámara del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Desbloquear la cámara y el micrófono del dispositivo?"</string> - <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Si lo haces, todos los servicios y todas las aplicaciones que tengan permiso podrán usar tu micrófono."</string> - <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todos los servicios y todas las aplicaciones que tengan permiso podrán usar tu cámara."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todos los servicios y todas las aplicaciones que tengan permiso podrán usar tu cámara o tu micrófono."</string> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu micrófono."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara o tu micrófono."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de aplicación"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra hacia la derecha para cambiar rápidamente de aplicación"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 60bb0a1bd9e8..e9638538170c 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kumotaanko laitteen kameran ja mikrofonin esto?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää mikrofoniasi."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa eston kaikkien sellaisten sovellusten ja palveluiden osalta, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vaihda sovellusta pyyhkäisemällä ylös"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vaihda sovellusta nopeasti vetämällä oikealle"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> lähetti viestin: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> lähetti kuvan"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> on päivittänyt tilansa: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Saatavilla"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Ongelma akkumittarin lukemisessa"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Saat lisätietoja napauttamalla"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ei herätyksiä"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 74ff58e0649f..457ab8a88cd1 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé un message : <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé une image"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> a mis à jour son état : <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponible"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Un problème est survenu lors de la lecture du niveau de charge de la pile"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Touchez pour en savoir plus"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Aucune alarme définie"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 3ef870471407..a1c50d8c85a2 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le micro de l\'appareil ?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre micro."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayer l\'écran vers le haut pour changer d\'application"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Déplacer vers la droite pour changer rapidement d\'application"</string> @@ -1139,7 +1139,7 @@ <string name="audio_status" msgid="4237055636967709208">"Écoute du contenu"</string> <string name="game_status" msgid="1340694320630973259">"Joue"</string> <string name="empty_user_name" msgid="3389155775773578300">"Amis"</string> - <string name="empty_status" msgid="5938893404951307749">"Chattez ce soir !"</string> + <string name="empty_status" msgid="5938893404951307749">"Bavardons ce soir !"</string> <string name="status_before_loading" msgid="1500477307859631381">"Le contenu s\'affichera bientôt"</string> <string name="missed_call" msgid="4228016077700161689">"Appel manqué"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"+ de <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé un message : <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé une image"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> a mis à jour son statut : <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponible"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Un problème est survenu au niveau de la lecture de votre outil de mesure de batterie"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Appuyer pour en savoir plus"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Pas d\'alarme définie"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index ee23e949ba5a..b5018d13ff2e 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou unha mensaxe: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou unha imaxe"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> cambiou de estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Dispoñible"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Produciuse un problema ao ler o medidor da batería"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toca para obter máis información"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Sen alarmas postas"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 59eceb7e0338..b29a52807f0a 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ સંદેશ મોકલવામાં આવ્યો: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ છબી મોકલવામાં આવી"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા નવી સ્ટેટસ અપડેટ પોસ્ટ કરવામાં આવી: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ઉપલબ્ધ છે"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"તમારું બૅટરી મીટર વાંચવામાં સમસ્યા આવી"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"વધુ માહિતી માટે ટૅપ કરો"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"કોઈ અલાર્મ સેટ નથી"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 9ae4721d8aa0..1d56cd66cb62 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -428,10 +428,10 @@ <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आप डिवाइस के माइक्रोफ़ोन को अनब्लॉक करना चाहते हैं?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आप डिवाइस के कैमरे को अनब्लॉक करना चाहते हैं?"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस के कैमरे और माइक्रोफ़ोन को अनब्लॉक करना चाहते हैं?"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ऐसा करने से, माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें माइक्रोफ़ोन का इस्तेमाल करने की अनुमति दी गई है."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरे या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे या माइक्रोफ़ोन का इस्तेमाल करने की अनुमति दी गई है."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरा या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें ये इस्तेमाल करने की अनुमति है."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ऐप्लिकेशन को झटपट स्विच करने के लिए उसे दाईं ओर खींचें और छोड़ें"</string> @@ -1149,7 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ने एक मैसेज भेजा है: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ने एक इमेज भेजी है"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ने स्टेटस अपडेट किया है: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <string name="person_available" msgid="2318599327472755472">"ऑनलाइन हैं"</string> + <string name="person_available" msgid="2318599327472755472">"ऑनलाइन है"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"आपके डिवाइस के बैटरी मीटर की रीडिंग लेने में समस्या आ रही है"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ज़्यादा जानकारी के लिए टैप करें"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"कोई अलार्म सेट नहीं है"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index d3c9f6fa2f26..f7728d2f39cb 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> üzenetet küldött: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> képet küldött"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> frissítette állapotát: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Elérhető"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Probléma merült fel az akkumulátor-töltésmérő olvasásakor"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Koppintással további információkat érhet el."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nincs ébresztés"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 227bf4d22d3e..ef20347a2576 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Berhenti memblokir kamera dan mikrofon perangkat?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan mikrofon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Langkah ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Geser ke atas untuk beralih aplikasi"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tarik ke kanan untuk beralih aplikasi dengan cepat"</string> @@ -1127,7 +1127,7 @@ <string name="over_two_weeks_timestamp" msgid="6300507859007874050">"Lebih dari 2 minggu lalu"</string> <string name="birthday_status" msgid="2596961629465396761">"Ulang Tahun"</string> <string name="birthday_status_content_description" msgid="682836371128282925">"Hari ini ulang tahun <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="upcoming_birthday_status" msgid="2005452239256870351">"Ulang tahun segera"</string> + <string name="upcoming_birthday_status" msgid="2005452239256870351">"Segera ulang tahun"</string> <string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"Ulang tahun <xliff:g id="NAME">%1$s</xliff:g> sebentar lagi"</string> <string name="anniversary_status" msgid="1790034157507590838">"Hari Peringatan"</string> <string name="anniversary_status_content_description" msgid="8212171790843327442">"Hari ini hari jadi <xliff:g id="NAME">%1$s</xliff:g>"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> mengirim pesan: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> mengirim gambar"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> memposting pembaruan status: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Online"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Terjadi masalah saat membaca indikator baterai"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ketuk untuk informasi selengkapnya"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm tidak disetel"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index e65097ef288c..b2e21981b844 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> sendi skilaboð: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> sendi mynd"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> er með stöðuuppfærslu: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Tiltækt"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Vandamál við að lesa stöðu rafhlöðu"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ýttu til að fá frekari upplýsingar"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Enginn vekjari"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 65c23d47e043..731d36ca36c1 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -1161,8 +1161,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"התקבלה הודעה מ<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> שלח/ה תמונה"</string> <string name="new_status_content_description" msgid="6046637888641308327">"הסטטוס של <xliff:g id="NAME">%1$s</xliff:g> עודכן: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"אונליין"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"בעיה בקריאת מדדי הסוללה"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"יש להקיש כדי להציג מידע נוסף"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"לא הוגדרה התראה"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 5ce3fe571bdd..aff2521a7bad 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>-მა გაგზავნა შეტყობინება: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>-მ(ა) სურათი გამოგზავნა"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>-მა განაახლა სტატუსი: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ხელმისაწვდომია"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"თქვენი ბატარეის მზომის წაკითხვასთან დაკავშირებით პრობლემა დაფიქსირდა"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"შეეხეთ მეტი ინფორმაციისთვის"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"მაღვიძარა არ არის"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index cba176d5953b..674f6a04393c 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> хабар жіберді: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> сурет жіберді."</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ағымдағы күйін жаңартты: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Желіде"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Батарея зарядының дерегі алынбай жатыр"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Толығырақ ақпарат алу үшін түртіңіз."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Оятқыш орнатылмаған."</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index cc6b15372e92..264f24834b04 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -428,7 +428,7 @@ <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ನಿಲ್ಲಿಸಿ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಅನ್ಬ್ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಅಥವಾ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಿದ್ದಾರೆ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಚಿತ್ರವನ್ನು ಕಳುಹಿಸಿದ್ದಾರೆ"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಸ್ಥಿತಿಯ ಅಪ್ಡೇಟ್ ಹೊಂದಿದ್ದಾರೆ: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ಲಭ್ಯವಿದೆ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ನಿಮ್ಮ ಬ್ಯಾಟರಿ ಮೀಟರ್ ಓದುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ಅಲಾರಾಂ ಸೆಟ್ ಆಗಿಲ್ಲ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 20a7c5f1545c..db96984a2a42 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>님이 메시지를 보냈습니다: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>님이 이미지를 보냈습니다."</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>님의 상태가 업데이트되었습니다: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"사용 가능"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"배터리 수준을 읽는 중에 문제가 발생함"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"탭하여 자세한 정보를 확인하세요."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"설정된 알람 없음"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 34d799c2a25b..42d684ea34f0 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -426,8 +426,8 @@ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Экрандан видео жаздырып алуу"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Баштадык"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Токтотуу"</string> - <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонунун кулпусун ачасызбы?"</string> - <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасынын кулпусун ачасызбы?"</string> + <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонун бөгөттөн чыгарасызбы?"</string> + <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасын бөгөттөн чыгарасызбы?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Түзмөктүн камерасы менен микрофону бөгөттөн чыгарылсынбы?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераны колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> билдирүү жөнөттү: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> сүрөт жөнөттү"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> жаңы абалы тууралуу жарыялады: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Онлайн"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Батареяңыздын кубаты аныкталбай жатат"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Кеңири маалымат алуу үчүн таптап коюңуз"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ойготкуч коюлган жок"</string> diff --git a/packages/SystemUI/res/values-land-television/dimens.xml b/packages/SystemUI/res/values-land-television/dimens.xml index a9bc9e5cd638..8fc46125b477 100644 --- a/packages/SystemUI/res/values-land-television/dimens.xml +++ b/packages/SystemUI/res/values-land-television/dimens.xml @@ -22,7 +22,7 @@ <dimen name="volume_dialog_panel_transparent_padding">24dp</dimen> <dimen name="volume_dialog_slider_width">4dp</dimen> <dimen name="volume_dialog_slider_corner_radius">@dimen/volume_dialog_slider_width</dimen> - <dimen name="volume_dialog_background_blur_radius">100dp</dimen> + <dimen name="volume_dialog_background_blur_radius">31dp</dimen> <dimen name="volume_tool_tip_right_margin">136dp</dimen> <dimen name="tv_volume_dialog_bubble_size">36dp</dimen> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 8a47dddce06f..d6b8fa2b4d0b 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ຍົກເລີກການບລັອກກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ໄມໂຄຣໂຟນຂອງທ່ານ."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຂອງທ່ານ."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະປົດບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ປັດຂື້ນເພື່ອສະຫຼັບແອັບ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ລາກໄປຂວາເພື່ອສະຫຼັບແອັບດ່ວນ"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ສົ່ງຂໍ້ຄວາມ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ສົ່ງຮູບພາບແລ້ວ"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ອັບເດດສະຖານະ: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ອອນລາຍ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ເກີດບັນຫາໃນການອ່ານຕົວວັດແທກແບັດເຕີຣີຂອງທ່ານ"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ແຕະເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ບໍ່ໄດ້ຕັ້ງໂມງປຸກ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 11d363ed59ef..19e8fbfd623c 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -1161,8 +1161,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> išsiuntė pranešimą: „<xliff:g id="NOTIFICATION">%2$s</xliff:g>“"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> išsiuntė vaizdą"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atnaujino būseną: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Pasiekiama"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nuskaitant akumuliatoriaus skaitiklį iškilo problema"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Palieskite, kad sužinotumėte daugiau informacijos"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenustatyta signalų"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 63f85fb4c76d..f0d26c837c48 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -432,8 +432,8 @@ <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vai vēlaties atbloķēt ierīces kameru?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vai atbloķēt ierīces kameru un mikrofonu?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Visas lietotnes un pakalpojumi, kurām ir atļauts izmantot mikrofonu, varēs tam piekļūt."</string> - <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kurām ir atļauts izmantot kameru, varēs tai piekļūt."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kurām ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru, varēs tai piekļūt."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Velciet augšup, lai pārslēgtu lietotnes"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lai ātri pārslēgtu lietotnes, velciet pa labi"</string> @@ -1155,8 +1155,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> nosūtīja ziņojumu: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> nosūtīja attēlu"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atjaunināja statusu: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Pieejams"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nevar iegūt informāciju par akumulatora uzlādes līmeni."</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Pieskarieties, lai iegūtu plašāku informāciju."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nav iestatīts signāls"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 5392d52526f3..719f519f3405 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> испрати порака: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> испрати слика"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> има ажурирање на статусот: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Достапен"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Проблем при читањето на мерачот на батеријата"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Допрете за повеќе информации"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Не е поставен аларм"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index bf27df9c63f9..9578370b151b 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -272,10 +272,10 @@ <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"ब्लूटूथ कनेक्ट केले."</string> <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"ब्लूटूथ बंद केले."</string> <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"ब्लूटूथ सुरू केले."</string> - <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"स्थान अहवाल बंद."</string> - <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"स्थान अहवाल सुरू."</string> - <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"स्थान अहवाल बंद केला."</string> - <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"स्थान अहवाल सुरू केला."</string> + <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"स्थान अहवाल देणे बंद."</string> + <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"स्थान अहवाल देणे सुरू."</string> + <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"स्थान अहवाल देणे बंद केले."</string> + <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"स्थान अहवाल देणे सुरू केले."</string> <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g> साठी अलार्म सेट केला."</string> <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"पॅनल बंद करा."</string> <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"अधिक वेळ."</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> यांनी मेसेज पाठवला: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> यांनी इमेज पाठवली"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> यांनी स्टेटस अपडेट केले: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"उपलब्ध आहे"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"तुमचे बॅटरी मीटर वाचताना समस्या आली"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"अधिक माहितीसाठी टॅप करा"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"अलार्म सेट केला नाही"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 1d16edcdc49c..684d71850351 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> menghantar mesej: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> menghantar imej"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> mempunyai kemaskinian status: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Tersedia"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Masalah membaca meter bateri anda"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ketik untuk mendapatkan maklumat lanjut"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Tiada penggera"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index c92a45e8dbcc..d588d271fb6f 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -376,7 +376,7 @@ <string name="quick_settings_cast_title" msgid="2279220930629235211">"မျက်နှာပြင် ကာ့စ်လုပ်ခြင်း"</string> <string name="quick_settings_casting" msgid="1435880708719268055">"ကာစ်တင်"</string> <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"အမည်မတပ် ကိရိယာ"</string> - <string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"ကာစ်တ် လုပ်ရန် အသင့် ရှိနေပြီ"</string> + <string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"ကာစ် လုပ်ရန် အသင့် ရှိနေပြီ"</string> <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ကိရိယာများ မရှိ"</string> <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi ချိတ်ဆက်ထားခြင်းမရှိပါ"</string> <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"အလင်းတောက်ပမှု"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index ee9b105d881d..d719123dcb36 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -1149,7 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ले एउटा म्यासेज पठाउनुभएको छ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ले एउटा फोटो पठाउनुभयो"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ले स्ट्याटस अपडेट गर्नुभएको छ: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <string name="person_available" msgid="2318599327472755472">"उपलब्ध"</string> + <string name="person_available" msgid="2318599327472755472">"उपलब्ध हुनुहुन्छ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"डिभाइसको ब्याट्रीको मिटर रिडिङ क्रममा समस्या भयो"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"थप जानकारी प्राप्त गर्न ट्याप गर्नुहोस्"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"अलार्म राखिएको छैन"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 2ad54f7fd75a..b8a104fc5a04 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ମେସେଜ୍ ପଠାଇଛନ୍ତି: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ଛବି ପଠାଇଛନ୍ତି"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ସ୍ଥିତି ଅପଡେଟ୍ କରିଛନ୍ତି: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ଉପଲବ୍ଧ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ଆପଣଙ୍କ ବ୍ୟାଟେରୀ ମିଟର୍ ପଢ଼ିବାରେ ସମସ୍ୟା ହେଉଛି"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ଅଧିକ ସୂଚନା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ଆଲାରାମ ସେଟ୍ ହୋଇନାହିଁ"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 3f2e4810dbd2..45c4f0f0267d 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -431,7 +431,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ਨੇ ਸੁਨੇਹਾ ਭੇਜਿਆ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ਨੇ ਇੱਕ ਚਿੱਤਰ ਭੇਜਿਆ ਹੈ"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ਨੇ ਸਥਿਤੀ ਅੱਪਡੇਟ ਕੀਤੀ ਹੈ: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"ਉਪਲਬਧ"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ਤੁਹਾਡੇ ਬੈਟਰੀ ਮੀਟਰ ਨੂੰ ਪੜ੍ਹਨ ਵਿੱਚ ਸਮੱਸਿਆ ਹੋ ਰਹੀ ਹੈ"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ਕੋਈ ਅਲਾਰਮ ਸੈੱਟ ਨਹੀਂ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 990b461fe0f9..b8da6bbedc53 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -748,10 +748,10 @@ <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Stan:</b> zmieniono na Ciche"</string> <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Stan:</b> podniesiono ważność"</string> <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Stan:</b> obniżono ważność"</string> - <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady"</string> - <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady, jako dymek"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady, przerywa działanie trybu Nie przeszkadzać"</string> - <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekran blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string> + <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady"</string> + <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, przerywa działanie trybu Nie przeszkadzać"</string> + <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string> <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string> <string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string> <string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 16965af689cc..15c28741b75e 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma mensagem: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma imagem"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> tem uma atualização de estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponível"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Ocorreu um problema ao ler o medidor da bateria"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toque para obter mais informações"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenhum alarme defin."</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 346323685e83..cf957a45dbdd 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -1155,8 +1155,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a trimis un mesaj: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a trimis o imagine"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> are o nouă stare: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Disponibil"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problemă la citirea măsurării bateriei"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Atingeți pentru mai multe informații"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nicio alarmă setată"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 8b0d70e4a8e4..9fd91f191837 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -1161,9 +1161,8 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> отправил сообщение: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> отправил изображение"</string> <string name="new_status_content_description" msgid="6046637888641308327">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> обновил статус: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> - <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не удается получить данные об уровне заряда батареи"</string> + <string name="person_available" msgid="2318599327472755472">"Онлайн"</string> + <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не удалось узнать уровень заряда батареи"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Нажмите, чтобы узнать больше."</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Будильников нет"</string> <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Сканер отпечатков пальцев"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 4967718196ef..14aa0a7bc303 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -1161,8 +1161,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> poslal(a) správu: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> poslal(a) obrázok"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> má aktualizáciu statusu: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"K dispozícii"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pri čítaní meradla batérie sa vyskytol problém"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Klepnutím si zobrazíte ďalšie informácie"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Žiadny budík"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index ad8e2659b612..5ce3cd43eef9 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> dërgoi një mesazh: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> dërgoi një imazh"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ka një përditësim të statusit: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"I disponueshëm"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem me leximin e matësit të baterisë"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Trokit për më shumë informacione"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nuk është caktuar asnjë alarm"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index c0588f666e39..7e0dbd7e462e 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> skickade ett meddelande: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> skickade en bild"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> har gjort en statusuppdatering: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Tillgänglig"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Batteriindikatorn visas inte"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tryck för mer information"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Inget inställt alarm"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 409eced5a67d..2bc29234f5b3 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> మెసేజ్ను పంపారు: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ఇమేజ్ను పంపారు"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>, స్టేటస్ను గురించిన అప్డేట్ను కలిగి ఉన్నారు: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"అందుబాటులో ఉంది"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"మీ బ్యాటరీ మీటర్ను చదవడంలో సమస్య"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"మరింత సమాచారం కోసం ట్యాప్ చేయండి"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"అలారం సెట్ చేయలేదు"</string> diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml index c258fcc4273a..76c620d53ccf 100644 --- a/packages/SystemUI/res/values-television/dimens.xml +++ b/packages/SystemUI/res/values-television/dimens.xml @@ -38,7 +38,7 @@ <dimen name="bottom_sheet_min_height">208dp</dimen> <dimen name="bottom_sheet_margin">24dp</dimen> - <dimen name="bottom_sheet_background_blur_radius">120dp</dimen> + <dimen name="bottom_sheet_background_blur_radius">37dp</dimen> <dimen name="privacy_chip_margin">12dp</dimen> <dimen name="privacy_chip_icon_margin_in_between">9dp</dimen> @@ -56,4 +56,4 @@ <dimen name="privacy_chip_dot_bg_height">18dp</dimen> <dimen name="privacy_chip_dot_bg_radius">9dp</dimen> -</resources>
\ No newline at end of file +</resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 6e0662693d4a..69b499985632 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ส่งข้อความ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ส่งรูปภาพ"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> มีการอัปเดตสถานะ: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"มี"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"พบปัญหาในการอ่านเครื่องวัดแบตเตอรี่"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"แตะดูข้อมูลเพิ่มเติม"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ไม่มีการตั้งปลุก"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 9a83c227bf32..d65f16dba762 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Nagpadala si <xliff:g id="NAME">%1$s</xliff:g> ng mensahe: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"Nagpadala si <xliff:g id="NAME">%1$s</xliff:g> ng larawan"</string> <string name="new_status_content_description" msgid="6046637888641308327">"May update sa status si <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Available"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nagkaproblema sa pagbabasa ng iyong battery meter"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"I-tap para sa higit pang impormasyon"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Walang alarm"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index ac6ecd09b8d7..bbae9c950a89 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> bir mesaj gönderdi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> bir resim gönderdi"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>, durumunu güncelledi: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Müsait"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pil ölçeriniz okunurken sorun oluştu"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Daha fazla bilgi için dokunun"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm ayarlanmadı"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 2e9f24029341..d4d18162e07f 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -433,9 +433,9 @@ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Надати доступ до камери пристрою?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Надати доступ до камери й мікрофона?"</string> - <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Усі додатки та сервіси, які можуть користуватися вашим мікрофоном, отримають доступ."</string> - <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, які можуть користуватися вашою камерою, отримають доступ."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, які можуть користуватися вашою камерою чи мікрофоном, отримають доступ."</string> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Усі додатки та сервіси, яким дозволено користуватися вашим мікрофоном, отримають доступ."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою, отримають доступ."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою чи мікрофоном, отримають доступ."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Проводьте пальцем угору, щоб переходити між додатками"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетягуйте праворуч, щоб швидко переходити між додатками"</string> @@ -1161,9 +1161,8 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> надсилає повідомлення: \"<xliff:g id="NOTIFICATION">%2$s</xliff:g>\""</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> надсилає зображення"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> публікує новий статус: \"<xliff:g id="STATUS">%2$s</xliff:g>\""</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> - <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не вдалось отримати дані лічильника акумулятора"</string> + <string name="person_available" msgid="2318599327472755472">"Онлайн"</string> + <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не вдалось отримати дані про рівень заряду акумулятора"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Натисніть, щоб дізнатися більше"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Немає будильників"</string> <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Сканер відбитків пальців"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index ffcd9a750abf..e8cb65725514 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> نے ایک پیغام بھیجا: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> نے ایک تصویر بھیجی"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> نے اسٹیٹس کو اپ ڈیٹ کر دیا ہے: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"دستیاب ہے"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"آپ کے بیٹری میٹر کو پڑھنے میں دشواری"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"مزید معلومات کے لیے تھپتھپائیں"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"کوئی الارم سیٹ نہیں ہے"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index bc186362ad86..de7fbcbe553f 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> đã gửi một tin nhắn: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> đã gửi một hình ảnh"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> đã cập nhật trạng thái: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Đang trực tuyến"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Đã xảy ra vấn đề khi đọc dung lượng pin của bạn"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Nhấn để biết thêm thông tin"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Chưa đặt chuông báo"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ae118bc22ead..e432c620c3ab 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -211,8 +211,8 @@ <string name="accessibility_two_bars" msgid="1335676987274417121">"信号强度为两格。"</string> <string name="accessibility_three_bars" msgid="819417766606501295">"信号强度为三格。"</string> <string name="accessibility_signal_full" msgid="5920148525598637311">"信号满格。"</string> - <string name="accessibility_desc_on" msgid="2899626845061427845">"开启。"</string> - <string name="accessibility_desc_off" msgid="8055389500285421408">"关闭。"</string> + <string name="accessibility_desc_on" msgid="2899626845061427845">"已开启。"</string> + <string name="accessibility_desc_off" msgid="8055389500285421408">"已关闭。"</string> <string name="accessibility_desc_connected" msgid="3082590384032624233">"已连接。"</string> <string name="accessibility_desc_connecting" msgid="8011433412112903614">"正在连接。"</string> <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string> @@ -221,7 +221,7 @@ <string name="accessibility_no_sim" msgid="1140839832913084973">"无 SIM 卡。"</string> <string name="accessibility_cell_data" msgid="172950885786007392">"移动数据"</string> <string name="accessibility_cell_data_on" msgid="691666434519443162">"移动数据已开启"</string> - <string name="cell_data_off" msgid="4886198950247099526">"关闭"</string> + <string name="cell_data_off" msgid="4886198950247099526">"已关闭"</string> <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"蓝牙网络共享。"</string> <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飞行模式。"</string> <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已开启。"</string> @@ -426,12 +426,12 @@ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"屏幕录制"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"开始"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string> - <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要取消禁用设备麦克风吗?"</string> - <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要取消禁用设备摄像头吗?"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要取消禁用设备摄像头和麦克风吗?"</string> + <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解锁设备麦克风吗?"</string> + <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解锁设备摄像头吗?"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解锁设备摄像头和麦克风吗?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"这将会为所有获准使用您麦克风的应用和服务启用这项权限。"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"这将会为所有获准使用您摄像头的应用和服务启用这项权限。"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您摄像头或麦克风的应用和服务启用这项权限。"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您的摄像头或麦克风的应用和服务启用这项权限。"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑动可切换应用"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖动可快速切换应用"</string> @@ -706,8 +706,8 @@ <string name="do_not_silence" msgid="4982217934250511227">"不静音"</string> <string name="do_not_silence_block" msgid="4361847809775811849">"不静音也不屏蔽"</string> <string name="tuner_full_importance_settings" msgid="1388025816553459059">"高级通知设置"</string> - <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"开启"</string> - <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"关闭"</string> + <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"已开启"</string> + <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"已关闭"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"通知"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"您将不会再看到这些通知"</string> @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>发送了一条消息:<xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>发送了一张图片"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>更新了状态:<xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"在线"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"读取电池计量器时出现问题"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"点按即可了解详情"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"未设置闹钟"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 98b90cc13457..7e9d2fe6873a 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>傳送了一則訊息:<xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>傳送了一張圖片"</string> <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>更新了狀態:<xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"線上"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"讀取電池計量器時發生問題"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"輕觸即可瞭解詳情"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"未設定鬧鐘"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 6ced59776adf..eac6f7455078 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -1149,8 +1149,7 @@ <string name="new_notification_text_content_description" msgid="2915029960094389291">"U-<xliff:g id="NAME">%1$s</xliff:g> uthumele umlayezo: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> <string name="new_notification_image_content_description" msgid="6017506886810813123">"U-<xliff:g id="NAME">%1$s</xliff:g> uthumele isithombe"</string> <string name="new_status_content_description" msgid="6046637888641308327">"U-<xliff:g id="NAME">%1$s</xliff:g> unesibuyekezo sesimo: <xliff:g id="STATUS">%2$s</xliff:g>"</string> - <!-- no translation found for person_available (2318599327472755472) --> - <skip /> + <string name="person_available" msgid="2318599327472755472">"Iyatholakala"</string> <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Kube khona inkinga ngokufunda imitha yakho yebhethri"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Thepha ukuze uthole olunye ulwazi"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Akukho alamu esethiwe"</string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 0a3e0c8c351e..7485ef858620 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1246,7 +1246,7 @@ <!-- Blur radius on status bar window and power menu --> <dimen name="min_window_blur_radius">1px</dimen> - <dimen name="max_window_blur_radius">72px</dimen> + <dimen name="max_window_blur_radius">23px</dimen> <!-- How much into a DisplayCutout's bounds we can go, on each side --> <dimen name="display_cutout_margin_consumption">0px</dimen> @@ -1480,6 +1480,8 @@ <dimen name="content_text_size_for_large">14sp</dimen> <dimen name="below_name_text_padding">16dp</dimen> <dimen name="above_notification_text_padding">22dp</dimen> + <dimen name="before_messages_count_padding">40dp</dimen> + <dimen name="before_predefined_icon_padding">30dp</dimen> <dimen name="regular_predefined_icon">18dp</dimen> <dimen name="larger_predefined_icon">24dp</dimen> <dimen name="largest_predefined_icon">32dp</dimen> diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml index 5bd95ebc1c41..3dbd9903b62e 100644 --- a/packages/SystemUI/res/values/dimens_tv.xml +++ b/packages/SystemUI/res/values/dimens_tv.xml @@ -16,5 +16,5 @@ --> <resources> <dimen name="tv_notification_panel_width">360dp</dimen> - <dimen name="tv_notification_blur_radius">100dp</dimen> -</resources>
\ No newline at end of file + <dimen name="tv_notification_blur_radius">31dp</dimen> +</resources> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskInfoCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskInfoCompat.java deleted file mode 100644 index 7b9ebc0d4656..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskInfoCompat.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 com.android.systemui.shared.system; - -import android.app.ActivityManager; -import android.app.PictureInPictureParams; -import android.app.TaskInfo; -import android.content.ComponentName; -import android.content.pm.ActivityInfo; -import android.graphics.Rect; - -public class TaskInfoCompat { - - public static int getUserId(TaskInfo info) { - return info.userId; - } - - public static int getActivityType(TaskInfo info) { - return info.configuration.windowConfiguration.getActivityType(); - } - - public static int getWindowingMode(TaskInfo info) { - return info.configuration.windowConfiguration.getWindowingMode(); - } - - public static Rect getWindowConfigurationBounds(TaskInfo info) { - return info.configuration.windowConfiguration.getBounds(); - } - - public static boolean supportsSplitScreenMultiWindow(TaskInfo info) { - return info.supportsSplitScreenMultiWindow; - } - - public static ComponentName getTopActivity(TaskInfo info) { - return info.topActivity; - } - - public static ActivityManager.TaskDescription getTaskDescription(TaskInfo info) { - return info.taskDescription; - } - - public static ActivityInfo getTopActivityInfo(TaskInfo info) { - return info.topActivityInfo; - } - - public static boolean isAutoEnterPipEnabled(PictureInPictureParams params) { - return params.isAutoEnterEnabled(); - } - - public static Rect getPipSourceRectHint(PictureInPictureParams params) { - return params.getSourceRectHint(); - } -} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java index 933a919efaad..92f8454fc93e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java @@ -27,6 +27,7 @@ import android.text.method.TextKeyListener; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; +import android.view.WindowInsets; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -227,12 +228,16 @@ public class KeyguardPasswordViewController super.onPause(); }); } - mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0); + if (mPasswordEntry.isAttachedToWindow()) { + mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime()); + } } @Override public void onStartingToHide() { - mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0); + if (mPasswordEntry.isAttachedToWindow()) { + mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime()); + } } private void updateSwitchImeButton() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 2096c310744d..72e502816534 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -79,18 +79,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV dozeParameters, unlockedScreenOffAnimationController, /* animateYPos= */ true); mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mSmartspaceTransitionController = smartspaceTransitionController; - - mKeyguardStateController.addCallback(new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - // If we explicitly re-show the keyguard, make sure that all the child views are - // visible. They might have been animating out as part of the SmartSpace shared - // element transition. - if (keyguardStateController.isShowing()) { - mView.setChildrenAlphaExcludingClockView(1f); - } - } - }); } @Override @@ -102,12 +90,14 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV protected void onViewAttached() { mKeyguardUpdateMonitor.registerCallback(mInfoCallback); mConfigurationController.addCallback(mConfigurationListener); + mKeyguardStateController.addCallback(mKeyguardStateControllerCallback); } @Override protected void onViewDetached() { mKeyguardUpdateMonitor.removeCallback(mInfoCallback); mConfigurationController.removeCallback(mConfigurationListener); + mKeyguardStateController.removeCallback(mKeyguardStateControllerCallback); } /** @@ -276,6 +266,19 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV } }; + private KeyguardStateController.Callback mKeyguardStateControllerCallback = + new KeyguardStateController.Callback() { + @Override + public void onKeyguardShowingChanged() { + // If we explicitly re-show the keyguard, make sure that all the child views are + // visible. They might have been animating out as part of the SmartSpace shared + // element transition. + if (mKeyguardStateController.isShowing()) { + mView.setChildrenAlphaExcludingClockView(1f); + } + } + }; + /** * Rect that specifies how KSV should be clipped, on its parent's coordinates. */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bd000b2effa3..e6e2ac980889 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -285,7 +285,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting protected boolean mTelephonyCapable; - private final boolean mAcquiredHapticEnabled; + private final boolean mAcquiredHapticEnabled = false; @Nullable private final Vibrator mVibrator; // Device provisioning state @@ -1413,11 +1413,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting public void playAcquiredHaptic() { if (mAcquiredHapticEnabled && mVibrator != null) { - String effect = Settings.Global.getString( - mContext.getContentResolver(), - "udfps_acquired_type"); - mVibrator.vibrate(UdfpsController.getVibration(effect, - UdfpsController.EFFECT_TICK), + mVibrator.vibrate(UdfpsController.EFFECT_CLICK, UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES); } } @@ -1730,8 +1726,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mLockPatternUtils = lockPatternUtils; mAuthController = authController; dumpManager.registerDumpable(getClass().getName(), this); - mAcquiredHapticEnabled = Settings.Global.getInt(mContext.getContentResolver(), - "udfps_acquired", 0) == 1; mVibrator = vibrator; mHandler = new Handler(mainLooper) { diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 7bbb63f02f14..5957be3c271b 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -24,10 +24,13 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; -import android.graphics.drawable.InsetDrawable; import android.hardware.biometrics.BiometricSourceType; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.media.AudioAttributes; +import android.os.Process; +import android.os.Vibrator; import android.util.DisplayMetrics; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; @@ -44,6 +47,7 @@ import com.android.settingslib.Utils; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.biometrics.UdfpsController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.FalsingManager; @@ -68,6 +72,13 @@ import javax.inject.Inject; */ @StatusBarComponent.StatusBarScope public class LockIconViewController extends ViewController<LockIconView> implements Dumpable { + + private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = + new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + .build(); + @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final KeyguardViewController mKeyguardViewController; @NonNull private final StatusBarStateController mStatusBarStateController; @@ -79,10 +90,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull private final DelayableExecutor mExecutor; private boolean mUdfpsEnrolled; - @NonNull private final Drawable mUnlockIcon; + @NonNull private final AnimatedVectorDrawable mFpToUnlockIcon; + @NonNull private final AnimatedVectorDrawable mLockToUnlockIcon; @NonNull private final Drawable mLockIcon; + @NonNull private final Drawable mUnlockIcon; @NonNull private final CharSequence mUnlockedLabel; @NonNull private final CharSequence mLockedLabel; + @Nullable private final Vibrator mVibrator; private boolean mIsDozing; private boolean mIsBouncerShowing; @@ -119,7 +133,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull DumpManager dumpManager, @NonNull AccessibilityManager accessibilityManager, @NonNull ConfigurationController configurationController, - @NonNull @Main DelayableExecutor executor + @NonNull @Main DelayableExecutor executor, + @Nullable Vibrator vibrator ) { super(view); mStatusBarStateController = statusBarStateController; @@ -131,16 +146,21 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mAccessibilityManager = accessibilityManager; mConfigurationController = configurationController; mExecutor = executor; + mVibrator = vibrator; final Context context = view.getContext(); - mUnlockIcon = new InsetDrawable(context.getResources().getDrawable( - com.android.internal.R.drawable.ic_lock_open, context.getTheme()), - context.getResources().getDimensionPixelSize( - com.android.systemui.R.dimen.udfps_unlock_icon_inset)); - mLockIcon = new InsetDrawable(context.getResources().getDrawable( - com.android.internal.R.drawable.ic_lock, context.getTheme()), - context.getResources().getDimensionPixelSize( - com.android.systemui.R.dimen.udfps_unlock_icon_inset)); + mUnlockIcon = mView.getContext().getResources().getDrawable( + R.anim.lock_to_unlock, + mView.getContext().getTheme()); + ((AnimatedVectorDrawable) mUnlockIcon).start(); + mLockIcon = mView.getContext().getResources().getDrawable( + R.anim.lock_to_unlock, + mView.getContext().getTheme()); + mFpToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( + R.anim.fp_to_unlock, mView.getContext().getTheme()); + mLockToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( + R.anim.lock_to_unlock, + mView.getContext().getTheme()); mUnlockedLabel = context.getResources().getString(R.string.accessibility_unlock_button); mLockedLabel = context.getResources().getString(R.string.accessibility_lock_icon); dumpManager.registerDumpable("LockIconViewController", this); @@ -212,6 +232,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme return; } + boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon; + boolean wasShowingLockIcon = mShowLockIcon; + boolean wasShowingUnlockIcon = mShowUnlockIcon; mShowLockIcon = !mCanDismissLockScreen && !mUserUnlockedWithBiometric && isLockScreen() && (!mUdfpsEnrolled || !mRunningFPS); mShowUnlockIcon = mCanDismissLockScreen && isLockScreen(); @@ -222,7 +245,19 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setVisibility(View.VISIBLE); mView.setContentDescription(mLockedLabel); } else if (mShowUnlockIcon) { - mView.setImageDrawable(mUnlockIcon); + if (!wasShowingUnlockIcon) { + if (wasShowingFpIcon) { + mView.setImageDrawable(mFpToUnlockIcon); + mFpToUnlockIcon.forceAnimationOnUI(); + mFpToUnlockIcon.start(); + } else if (wasShowingLockIcon) { + mView.setImageDrawable(mLockToUnlockIcon); + mLockToUnlockIcon.forceAnimationOnUI(); + mLockToUnlockIcon.start(); + } else { + mView.setImageDrawable(mUnlockIcon); + } + } mView.setVisibility(View.VISIBLE); mView.setContentDescription(mUnlockedLabel); } else { @@ -272,8 +307,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private void updateColors() { final int color = Utils.getColorAttrDefaultColor(mView.getContext(), R.attr.wallpaperTextColorAccent); - mUnlockIcon.setTint(color); + mFpToUnlockIcon.setTint(color); + mLockToUnlockIcon.setTint(color); mLockIcon.setTint(color); + mUnlockIcon.setTint(color); } private void updateConfiguration() { @@ -401,7 +438,16 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @Override public void onKeyguardShowingChanged() { + // Reset values in case biometrics were removed (ie: pin/pattern/password => swipe). + // If biometrics were removed, local vars mCanDismissLockScreen and + // mUserUnlockedWithBiometric may not be updated. + mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen(); updateKeyguardShowing(); + if (mIsKeyguardShowing) { + mUserUnlockedWithBiometric = + mKeyguardUpdateMonitor.getUserUnlockedWithBiometric( + KeyguardUpdateMonitor.getCurrentUser()); + } mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled(); updateVisibility(); } @@ -447,6 +493,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme // intercept all following touches until we see MotionEvent.ACTION_CANCEL UP or // MotionEvent.ACTION_UP (see #onTouchEvent) mDownDetected = true; + if (mVibrator != null) { + mVibrator.vibrate( + Process.myUid(), + getContext().getOpPackageName(), + UdfpsController.EFFECT_CLICK, + "lockIcon-onDown", + VIBRATION_SONIFICATION_ATTRIBUTES); + } return true; } @@ -455,6 +509,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme return; } + if (mVibrator != null) { + mVibrator.vibrate( + Process.myUid(), + getContext().getOpPackageName(), + UdfpsController.EFFECT_CLICK, + "lockIcon-onLongPress", + VIBRATION_SONIFICATION_ATTRIBUTES); + } onAffordanceClick(); } diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java index 099e6f4b5341..57407f1f34c0 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java @@ -88,13 +88,10 @@ public class NumPadButton extends AlphaOptimizedImageButton { * Reload colors from resources. **/ public void reloadColors() { - if (mAnimator != null) { - mAnimator.reloadColors(getContext()); - } else { - // Needed for old style pin - int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary) - .getDefaultColor(); - ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(textColor)); - } + if (mAnimator != null) mAnimator.reloadColors(getContext()); + + int textColor = Utils.getColorAttrDefaultColor(getContext(), + android.R.attr.colorBackground); + ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(textColor)); } } diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 104d711f46fb..c70281dc7be8 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -140,6 +140,7 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; import dagger.Lazy; @@ -199,6 +200,12 @@ public class Dependency { public static final String ALLOW_NOTIFICATION_LONG_PRESS_NAME = "allow_notif_longpress"; /** + * A provider of {@link EdgeBackGestureHandler}. + */ + public static final String EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME = + "edge_back_gesture_handler_provider"; + + /** * Key for getting a background Looper for background work. */ public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME); @@ -233,6 +240,12 @@ public class Dependency { */ public static final DependencyKey<String> LEAK_REPORT_EMAIL = new DependencyKey<>(LEAK_REPORT_EMAIL_NAME); + /** + * Key for retrieving an Provider<EdgeBackGestureHandler>. + */ + public static final DependencyKey<Provider<EdgeBackGestureHandler>> + EDGE_BACK_GESTURE_HANDLER_PROVIDER = + new DependencyKey<>(EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME); private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>(); @@ -359,7 +372,7 @@ public class Dependency { @Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager; @Inject Lazy<SystemStatusAnimationScheduler> mSystemStatusAnimationSchedulerLazy; @Inject Lazy<PrivacyDotViewController> mPrivacyDotViewControllerLazy; - @Inject Lazy<EdgeBackGestureHandler> mEdgeBackGestureHandler; + @Inject Provider<EdgeBackGestureHandler> mEdgeBackGestureHandlerProvider; @Inject Lazy<UiEventLogger> mUiEventLogger; @Inject Lazy<FeatureFlags> mFeatureFlagsLazy; @@ -574,7 +587,7 @@ public class Dependency { mProviders.put(SystemStatusAnimationScheduler.class, mSystemStatusAnimationSchedulerLazy::get); mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get); - mProviders.put(EdgeBackGestureHandler.class, mEdgeBackGestureHandler::get); + mProviders.put(EDGE_BACK_GESTURE_HANDLER_PROVIDER, () -> mEdgeBackGestureHandlerProvider); mProviders.put(UiEventLogger.class, mUiEventLogger::get); mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java index 45ee4ad9ae50..ee602bc9cb78 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java @@ -23,6 +23,8 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; +import androidx.annotation.Nullable; + import com.android.systemui.R; public class AuthBiometricFingerprintView extends AuthBiometricView { @@ -94,12 +96,37 @@ public class AuthBiometricFingerprintView extends AuthBiometricView { mIconView.setImageDrawable(icon); + final CharSequence iconContentDescription = getIconContentDescription(newState); + if (iconContentDescription != null) { + mIconView.setContentDescription(iconContentDescription); + } + if (animation != null && shouldAnimateForTransition(lastState, newState)) { animation.forceAnimationOnUI(); animation.start(); } } + @Nullable + private CharSequence getIconContentDescription(int newState) { + switch (newState) { + case STATE_IDLE: + case STATE_AUTHENTICATING_ANIMATING_IN: + case STATE_AUTHENTICATING: + case STATE_PENDING_CONFIRMATION: + case STATE_AUTHENTICATED: + return mContext.getString( + R.string.accessibility_fingerprint_dialog_fingerprint_icon); + + case STATE_ERROR: + case STATE_HELP: + return mContext.getString(R.string.biometric_dialog_try_again); + + default: + return null; + } + } + private boolean shouldAnimateForTransition(int oldState, int newState) { switch (newState) { case STATE_HELP: diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index bebf813e1833..60b06378a61a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -636,7 +636,6 @@ public abstract class AuthBiometricView extends LinearLayout { mIndicatorView.setText(message); mIndicatorView.setTextColor(mTextColorError); mIndicatorView.setVisibility(View.VISIBLE); - mIndicatorView.setSelected(true); mHandler.postDelayed(resetMessageRunnable, mInjector.getDelayAfterError()); Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 068640622294..6ddf24875000 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -17,7 +17,6 @@ package com.android.systemui.biometrics; import static android.hardware.fingerprint.IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD; -import static android.os.VibrationEffect.Composition.PRIMITIVE_LOW_TICK; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkNotNull; @@ -27,7 +26,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -42,13 +40,12 @@ import android.media.AudioAttributes; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.VibrationEffect; import android.os.Vibrator; -import android.provider.Settings; -import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; @@ -73,6 +70,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.Execution; @@ -110,6 +108,7 @@ public class UdfpsController implements DozeReceiver { private final DelayableExecutor mFgExecutor; @NonNull private final StatusBar mStatusBar; @NonNull private final StatusBarStateController mStatusBarStateController; + @NonNull private final KeyguardStateController mKeyguardStateController; @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager; @NonNull private final DumpManager mDumpManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -152,6 +151,7 @@ public class UdfpsController implements DozeReceiver { private boolean mScreenOn; private Runnable mAodInterruptRunnable; private boolean mOnFingerDown; + private boolean mAttemptedToDismissKeyguard; @VisibleForTesting public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = @@ -160,16 +160,8 @@ public class UdfpsController implements DozeReceiver { .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); - public static final VibrationEffect EFFECT_TICK = - VibrationEffect.get(VibrationEffect.EFFECT_TICK); - private static final VibrationEffect EFFECT_TEXTURE_TICK = - VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); - @VisibleForTesting - static final VibrationEffect EFFECT_CLICK = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); - private static final VibrationEffect EFFECT_HEAVY = - VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); - private static final VibrationEffect EFFECT_DOUBLE_CLICK = - VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); + public static final VibrationEffect EFFECT_CLICK = + VibrationEffect.get(VibrationEffect.EFFECT_CLICK); private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { @Override @@ -391,8 +383,12 @@ public class UdfpsController implements DozeReceiver { // ACTION_DOWN, in that case we should just reuse the old instance. mVelocityTracker.clear(); } - if (isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView)) { + + boolean withinSensorArea = + isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView); + if (withinSensorArea) { Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0); + Log.v(TAG, "onTouch | action down"); // The pointer that causes ACTION_DOWN is always at index 0. // We need to persist its ID to track it during ACTION_MOVE that could include // data for many other pointers because of multi-touch support. @@ -400,6 +396,11 @@ public class UdfpsController implements DozeReceiver { mVelocityTracker.addMovement(event); handled = true; } + if ((withinSensorArea || fromUdfpsView) && shouldTryToDismissKeyguard()) { + Log.v(TAG, "onTouch | dismiss keyguard from ACTION_DOWN"); + mKeyguardViewManager.notifyKeyguardAuthenticated(false /* strongAuth */); + mAttemptedToDismissKeyguard = true; + } Trace.endSection(); break; @@ -410,8 +411,10 @@ public class UdfpsController implements DozeReceiver { ? event.getPointerId(0) : event.findPointerIndex(mActivePointerId); if (idx == event.getActionIndex()) { - if (isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx), - fromUdfpsView)) { + boolean actionMoveWithinSensorArea = + isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx), + fromUdfpsView); + if (actionMoveWithinSensorArea) { if (mVelocityTracker == null) { // touches could be injected, so the velocity tracker may not have // been initialized (via ACTION_DOWN). @@ -437,7 +440,6 @@ public class UdfpsController implements DozeReceiver { mTouchLogTime = SystemClock.elapsedRealtime(); mPowerManager.userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - playStartHaptic(); handled = true; } else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) { Log.v(TAG, "onTouch | finger move: " + touchInfo); @@ -447,6 +449,12 @@ public class UdfpsController implements DozeReceiver { Log.v(TAG, "onTouch | finger outside"); onFingerUp(); } + if ((fromUdfpsView || actionMoveWithinSensorArea) + && shouldTryToDismissKeyguard()) { + Log.v(TAG, "onTouch | dismiss keyguard from ACTION_MOVE"); + mKeyguardViewManager.notifyKeyguardAuthenticated(false /* strongAuth */); + mAttemptedToDismissKeyguard = true; + } } Trace.endSection(); break; @@ -461,6 +469,7 @@ public class UdfpsController implements DozeReceiver { mVelocityTracker = null; } Log.v(TAG, "onTouch | finger up"); + mAttemptedToDismissKeyguard = false; onFingerUp(); mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION); Trace.endSection(); @@ -472,6 +481,13 @@ public class UdfpsController implements DozeReceiver { return handled; } + private boolean shouldTryToDismissKeyguard() { + return mView.getAnimationViewController() != null + && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController + && mKeyguardStateController.canDismissLockScreen() + && !mAttemptedToDismissKeyguard; + } + @Inject public UdfpsController(@NonNull Context context, @NonNull Execution execution, @@ -492,7 +508,8 @@ public class UdfpsController implements DozeReceiver { @NonNull ScreenLifecycle screenLifecycle, @Nullable Vibrator vibrator, @NonNull UdfpsHapticsSimulator udfpsHapticsSimulator, - @NonNull Optional<UdfpsHbmProvider> hbmProvider) { + @NonNull Optional<UdfpsHbmProvider> hbmProvider, + @NonNull KeyguardStateController keyguardStateController) { mContext = context; mExecution = execution; // TODO (b/185124905): inject main handler and vibrator once done prototyping @@ -506,6 +523,7 @@ public class UdfpsController implements DozeReceiver { mFgExecutor = fgExecutor; mStatusBar = statusBar; mStatusBarStateController = statusBarStateController; + mKeyguardStateController = keyguardStateController; mKeyguardViewManager = statusBarKeyguardViewManager; mDumpManager = dumpManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; @@ -552,18 +570,12 @@ public class UdfpsController implements DozeReceiver { @VisibleForTesting public void playStartHaptic() { if (mVibrator != null) { - final ContentResolver contentResolver = - mContext.getContentResolver(); - // TODO: these settings checks should eventually be removed after ux testing - // (b/185124905) - int startEnabled = Settings.Global.getInt(contentResolver, - "udfps_start", 1); - if (startEnabled > 0) { - String startEffectSetting = Settings.Global.getString( - contentResolver, "udfps_start_type"); - mVibrator.vibrate(getVibration(startEffectSetting, - EFFECT_CLICK), VIBRATION_SONIFICATION_ATTRIBUTES); - } + mVibrator.vibrate( + Process.myUid(), + mContext.getOpPackageName(), + EFFECT_CLICK, + "udfps-onStart", + VIBRATION_SONIFICATION_ATTRIBUTES); } } @@ -636,9 +648,12 @@ public class UdfpsController implements DozeReceiver { // Gets the size based on the current rotation of the display. mContext.getDisplay().getRealSize(p); - // Transform dimensions if the device is in landscape mode. + // Transform dimensions if the device is in landscape mode switch (mContext.getDisplay().getRotation()) { case Surface.ROTATION_90: + if (animation instanceof UdfpsKeyguardViewController) { + break; + } mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius - paddingX; mCoreLayoutParams.y = p.y - mSensorProps.sensorLocationX - mSensorProps.sensorRadius @@ -646,6 +661,9 @@ public class UdfpsController implements DozeReceiver { break; case Surface.ROTATION_270: + if (animation instanceof UdfpsKeyguardViewController) { + break; + } mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius - paddingX; mCoreLayoutParams.y = mSensorProps.sensorLocationX - mSensorProps.sensorRadius @@ -654,6 +672,7 @@ public class UdfpsController implements DozeReceiver { default: // Do nothing to stay in portrait mode. + // Keyguard is always in portrait mode. } // avoid announcing window title mCoreLayoutParams.accessibilityTitle = " "; @@ -684,6 +703,7 @@ public class UdfpsController implements DozeReceiver { mView.setSensorProperties(mSensorProps); mView.setHbmProvider(mHbmProvider); UdfpsAnimationViewController animation = inflateUdfpsAnimation(reason); + mAttemptedToDismissKeyguard = false; animation.init(); mView.setAnimationViewController(animation); mOrientationListener.enable(); @@ -691,7 +711,8 @@ public class UdfpsController implements DozeReceiver { // This view overlaps the sensor area, so prevent it from being selectable // during a11y. if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR - || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) { + || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING + || reason == IUdfpsOverlayController.REASON_AUTH_BP) { mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); } @@ -846,6 +867,9 @@ public class UdfpsController implements DozeReceiver { Log.w(TAG, "Null view in onFingerDown"); return; } + if (!mOnFingerDown) { + playStartHaptic(); + } mOnFingerDown = true; mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major); Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); @@ -873,38 +897,6 @@ public class UdfpsController implements DozeReceiver { } } - /** - * get vibration to play given string - * used for testing purposes (b/185124905) - */ - public static VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) { - if (TextUtils.isEmpty(effect)) { - return defaultEffect; - } - - switch (effect.toLowerCase()) { - case "click": - return EFFECT_CLICK; - case "heavy": - return EFFECT_HEAVY; - case "texture_tick": - return EFFECT_TEXTURE_TICK; - case "tick": - return EFFECT_TICK; - case "double_tap": - return EFFECT_DOUBLE_CLICK; - default: - try { - int primitive = Integer.parseInt(effect); - if (primitive <= PRIMITIVE_LOW_TICK && primitive > -1) { - return VibrationEffect.startComposition().addPrimitive(primitive).compose(); - } - } catch (NumberFormatException e) { - } - return defaultEffect; - } - } - private void updateTouchListener() { if (mView == null) { return; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java index 412b77698159..6a918a6c8d39 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java @@ -21,11 +21,8 @@ import android.annotation.Nullable; import android.content.Context; import android.graphics.PointF; import android.hardware.fingerprint.IUdfpsOverlayController; -import android.media.AudioAttributes; import android.os.Build; import android.os.UserHandle; -import android.os.VibrationEffect; -import android.os.Vibrator; import android.provider.Settings; import android.util.Log; import android.util.TypedValue; @@ -50,12 +47,6 @@ public class UdfpsEnrollHelper { // Enroll with two center touches before going to guided enrollment private static final int NUM_CENTER_TOUCHES = 2; - private static final AudioAttributes VIBRATION_SONFICATION_ATTRIBUTES = - new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) - .build(); - interface Listener { void onEnrollmentProgress(int remaining, int totalSteps); void onLastStepAcquired(); @@ -66,9 +57,6 @@ public class UdfpsEnrollHelper { private final int mEnrollReason; private final boolean mAccessibilityEnabled; @NonNull private final List<PointF> mGuidedEnrollmentPoints; - @NonNull private final Vibrator mVibrator; - @NonNull private final VibrationEffect mEffectClick = - VibrationEffect.get(VibrationEffect.EFFECT_CLICK); private int mTotalSteps = -1; private int mRemainingSteps = -1; @@ -82,7 +70,6 @@ public class UdfpsEnrollHelper { public UdfpsEnrollHelper(@NonNull Context context, int reason) { mContext = context; mEnrollReason = reason; - mVibrator = context.getSystemService(Vibrator.class); final AccessibilityManager am = context.getSystemService(AccessibilityManager.class); mAccessibilityEnabled = am.isEnabled(); @@ -141,7 +128,6 @@ public class UdfpsEnrollHelper { if (remaining != mRemainingSteps) { mLocationsEnrolled++; - vibrateSuccess(); } mRemainingSteps = remaining; @@ -202,11 +188,6 @@ public class UdfpsEnrollHelper { if (mRemainingSteps <= 2 && mRemainingSteps >= 0) { mListener.onLastStepAcquired(); - vibrateSuccess(); } } - - private void vibrateSuccess() { - mVibrator.vibrate(mEffectClick, VIBRATION_SONFICATION_ATTRIBUTES); - } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java index e82f648503b9..eb02aa0d9cdf 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.StatusBarState; import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieProperty; import com.airbnb.lottie.model.KeyPath; + /** * View corresponding with udfps_keyguard_view.xml */ @@ -138,9 +139,12 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { mAodFp.setTranslationX(mBurnInOffsetX); mAodFp.setTranslationY(mBurnInOffsetY); mAodFp.setProgress(mBurnInProgress); + mAodFp.setAlpha(255 * mInterpolatedDarkAmount); mLockScreenFp.setTranslationX(mBurnInOffsetX); mLockScreenFp.setTranslationY(mBurnInOffsetY); + mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount); + mLockScreenFp.setAlpha((1f - mInterpolatedDarkAmount) * 255); } void requestUdfps(boolean request, int color) { @@ -158,7 +162,12 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { } void updateColor() { + mWallpaperTextColor = Utils.getColorAttrDefaultColor(mContext, + R.attr.wallpaperTextColorAccent); + mTextColorPrimary = Utils.getColorAttrDefaultColor(mContext, + android.R.attr.textColorPrimary); mLockScreenFp.invalidate(); + mBgProtection.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg)); } private boolean showingUdfpsBouncer() { @@ -207,14 +216,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { mHintAnimator.cancel(); mInterpolatedDarkAmount = eased; updateBurnInOffsets(); - mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount); - mAodFp.setAlpha(mInterpolatedDarkAmount); - - if (linear == 1f) { - mLockScreenFp.setVisibility(View.INVISIBLE); - } else { - mLockScreenFp.setVisibility(View.VISIBLE); - } } void animateHint() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index 809e7a70d66c..37a6cfaabb5e 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -33,7 +33,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.systemui.classifier.FalsingDataProvider.SessionListener; import com.android.systemui.classifier.HistoryTracker.BeliefListener; import com.android.systemui.dagger.qualifiers.TestHarness; -import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -66,7 +65,6 @@ public class BrightLineFalsingManager implements FalsingManager { private static final double FALSE_BELIEF_THRESHOLD = 0.9; private final FalsingDataProvider mDataProvider; - private final DockManager mDockManager; private final SingleTapClassifier mSingleTapClassifier; private final DoubleTapClassifier mDoubleTapClassifier; private final HistoryTracker mHistoryTracker; @@ -173,14 +171,13 @@ public class BrightLineFalsingManager implements FalsingManager { @Inject public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider, - DockManager dockManager, MetricsLogger metricsLogger, + MetricsLogger metricsLogger, @Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers, SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier, HistoryTracker historyTracker, KeyguardStateController keyguardStateController, AccessibilityManager accessibilityManager, @TestHarness boolean testHarness) { mDataProvider = falsingDataProvider; - mDockManager = dockManager; mMetricsLogger = metricsLogger; mClassifiers = classifiers; mSingleTapClassifier = singleTapClassifier; @@ -332,7 +329,7 @@ public class BrightLineFalsingManager implements FalsingManager { || !mKeyguardStateController.isShowing() || mTestHarness || mDataProvider.isJustUnlockedWithFace() - || mDockManager.isDocked() + || mDataProvider.isDocked() || mAccessibilityManager.isEnabled(); } @@ -400,7 +397,7 @@ public class BrightLineFalsingManager implements FalsingManager { ipw.print("mJustUnlockedWithFace="); ipw.println(mDataProvider.isJustUnlockedWithFace() ? 1 : 0); ipw.print("isDocked="); - ipw.println(mDockManager.isDocked() ? 1 : 0); + ipw.println(mDataProvider.isDocked() ? 1 : 0); ipw.print("width="); ipw.println(mDataProvider.getWidthPixels()); ipw.print("height="); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 969736910b5e..14e5991f35d2 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -16,6 +16,8 @@ package com.android.systemui.classifier; +import static com.android.systemui.dock.DockManager.DockEventListener; + import android.hardware.SensorManager; import android.hardware.biometrics.BiometricSourceType; import android.util.Log; @@ -25,9 +27,12 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.ProximitySensor; @@ -53,6 +58,8 @@ class FalsingCollectorImpl implements FalsingCollector { private final ProximitySensor mProximitySensor; private final StatusBarStateController mStatusBarStateController; private final KeyguardStateController mKeyguardStateController; + private final BatteryController mBatteryController; + private final DockManager mDockManager; private final DelayableExecutor mMainExecutor; private final SystemClock mSystemClock; @@ -89,12 +96,46 @@ class FalsingCollectorImpl implements FalsingCollector { } }; + + private final BatteryStateChangeCallback mBatteryListener = new BatteryStateChangeCallback() { + @Override + public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + } + + @Override + public void onWirelessChargingChanged(boolean isWirelessCharging) { + if (isWirelessCharging || mDockManager.isDocked()) { + mProximitySensor.pause(); + } else { + mProximitySensor.resume(); + } + } + }; + + private final DockEventListener mDockEventListener = new DockEventListener() { + @Override + public void onEvent(int event) { + if (event == DockManager.STATE_NONE && !mBatteryController.isWirelessCharging()) { + mProximitySensor.resume(); + } else { + mProximitySensor.pause(); + } + } + }; + @Inject - FalsingCollectorImpl(FalsingDataProvider falsingDataProvider, FalsingManager falsingManager, - KeyguardUpdateMonitor keyguardUpdateMonitor, HistoryTracker historyTracker, - ProximitySensor proximitySensor, StatusBarStateController statusBarStateController, + FalsingCollectorImpl( + FalsingDataProvider falsingDataProvider, + FalsingManager falsingManager, + KeyguardUpdateMonitor keyguardUpdateMonitor, + HistoryTracker historyTracker, + ProximitySensor proximitySensor, + StatusBarStateController statusBarStateController, KeyguardStateController keyguardStateController, - @Main DelayableExecutor mainExecutor, SystemClock systemClock) { + BatteryController batteryController, + DockManager dockManager, + @Main DelayableExecutor mainExecutor, + SystemClock systemClock) { mFalsingDataProvider = falsingDataProvider; mFalsingManager = falsingManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; @@ -102,10 +143,11 @@ class FalsingCollectorImpl implements FalsingCollector { mProximitySensor = proximitySensor; mStatusBarStateController = statusBarStateController; mKeyguardStateController = keyguardStateController; + mBatteryController = batteryController; + mDockManager = dockManager; mMainExecutor = mainExecutor; mSystemClock = systemClock; - mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); mProximitySensor.setDelay(SensorManager.SENSOR_DELAY_GAME); @@ -113,6 +155,9 @@ class FalsingCollectorImpl implements FalsingCollector { mState = mStatusBarStateController.getState(); mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); + + mBatteryController.addCallback(mBatteryListener); + mDockManager.addListener(mDockEventListener); } @Override @@ -312,6 +357,8 @@ class FalsingCollectorImpl implements FalsingCollector { unregisterSensors(); mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback); mStatusBarStateController.removeCallback(mStatusBarStateListener); + mBatteryController.removeCallback(mBatteryListener); + mDockManager.removeListener(mDockEventListener); } @Override @@ -351,9 +398,7 @@ class FalsingCollectorImpl implements FalsingCollector { } private void registerSensors() { - if (!mFalsingDataProvider.isWirelessCharging()) { - mProximitySensor.register(mSensorEventListener); - } + mProximitySensor.register(mSensorEventListener); } private void unregisterSensors() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 2f688dd9d247..a3ecb0c0b273 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -22,6 +22,7 @@ import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.policy.BatteryController; import java.util.ArrayList; @@ -40,7 +41,8 @@ public class FalsingDataProvider { private final int mWidthPixels; private final int mHeightPixels; - private final BatteryController mBatteryController; + private BatteryController mBatteryController; + private final DockManager mDockManager; private final float mXdpi; private final float mYdpi; private final List<SessionListener> mSessionListeners = new ArrayList<>(); @@ -59,12 +61,16 @@ public class FalsingDataProvider { private boolean mJustUnlockedWithFace; @Inject - public FalsingDataProvider(DisplayMetrics displayMetrics, BatteryController batteryController) { + public FalsingDataProvider( + DisplayMetrics displayMetrics, + BatteryController batteryController, + DockManager dockManager) { mXdpi = displayMetrics.xdpi; mYdpi = displayMetrics.ydpi; mWidthPixels = displayMetrics.widthPixels; mHeightPixels = displayMetrics.heightPixels; mBatteryController = batteryController; + mDockManager = dockManager; FalsingClassifier.logInfo("xdpi, ydpi: " + getXdpi() + ", " + getYdpi()); FalsingClassifier.logInfo("width, height: " + getWidthPixels() + ", " + getHeightPixels()); @@ -219,11 +225,6 @@ public class FalsingDataProvider { return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY(); } - /** Returns true if phone is being charged without a cable. */ - public boolean isWirelessCharging() { - return mBatteryController.isWirelessCharging(); - } - private void recalculateData() { if (!mDirty) { return; @@ -357,6 +358,11 @@ public class FalsingDataProvider { mJustUnlockedWithFace = justUnlockedWithFace; } + /** Returns true if phone is sitting in a dock or is wirelessly charging. */ + public boolean isDocked() { + return mBatteryController.isWirelessCharging() || mDockManager.isDocked(); + } + /** Implement to be alerted abotu the beginning and ending of falsing tracking. */ public interface SessionListener { /** Called when the lock screen is shown and falsing-tracking begins. */ diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index 5acb3038b91b..06e74821869e 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -669,11 +669,6 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene int userId = user.id; - // No lockdown option if it's not turned on in Settings - if (mSecureSettings.getIntForUser(Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, userId) == 0) { - return false; - } - // Lockdown is meaningless without a place to go. if (!mKeyguardStateController.isMethodSecure()) { return false; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 75f77bffa4a0..c7c25903923a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1506,8 +1506,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, return; } - // if the keyguard is already showing, don't bother - if (mKeyguardViewControllerLazy.get().isShowing()) { + // if the keyguard is already showing, don't bother. check flags in both files + // to account for the hiding animation which results in a delay and discrepancy + // between flags + if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); resetStateLocked(); return; @@ -2309,7 +2311,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, // only play "unlock" noises if not on a call (since the incall UI // disables the keyguard) if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { - Log.i("TEST", "playSounds: false"); playSounds(false); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 902e8c28a85d..15a70831b2f9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -475,6 +475,13 @@ public class MediaControlPanel { @Nullable private ActivityLaunchAnimator.Controller buildLaunchAnimatorController( TransitionLayout player) { + if (!(player.getParent() instanceof ViewGroup)) { + // TODO(b/192194319): Throw instead of just logging. + Log.wtf(TAG, "Skipping player animation as it is not attached to a ViewGroup", + new Exception()); + return null; + } + // TODO(b/174236650): Make sure that the carousel indicator also fades out. // TODO(b/174236650): Instrument the animation to measure jank. return new GhostedViewLaunchAnimatorController(player, diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 4816f1cf8d6a..f5b4c7671dfd 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -18,6 +18,7 @@ package com.android.systemui.navigationbar; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; @@ -342,7 +343,7 @@ public class NavigationBarView extends FrameLayout implements mNavColorSampleMargin = getResources() .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin); - mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.class); + mEdgeBackGestureHandler = Dependency.get(EDGE_BACK_GESTURE_HANDLER_PROVIDER).get(); mEdgeBackGestureHandler.setStateChangeCallback(this::updateStates); mRegionSamplingHelper = new RegionSamplingHelper(this, new RegionSamplingHelper.SamplingCallback() { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index ff5d0b157c80..48d2bb91da05 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -58,7 +58,6 @@ import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.systemui.R; import com.android.systemui.SystemUIFactory; import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationBarView; @@ -92,7 +91,6 @@ import javax.inject.Inject; /** * Utility class to handle edge swipes for back gesture */ -@SysUISingleton public class EdgeBackGestureHandler extends CurrentUserTracker implements PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> { diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 335ebca37bf0..a16b92f494a4 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -47,6 +47,7 @@ import android.content.Intent; import android.graphics.Bitmap; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; +import android.graphics.ImageDecoder; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.graphics.text.LineBreaker; @@ -59,6 +60,7 @@ import android.text.TextUtils; import android.util.IconDrawableFactory; import android.util.Log; import android.util.Pair; +import android.util.Size; import android.util.SizeF; import android.util.TypedValue; import android.view.Gravity; @@ -79,6 +81,7 @@ import com.android.systemui.people.widget.LaunchConversationActivity; import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; import com.android.systemui.people.widget.PeopleTileKey; +import java.io.IOException; import java.text.NumberFormat; import java.time.Duration; import java.util.ArrayList; @@ -178,6 +181,7 @@ public class PeopleTileViewHelper { private int mWidth; private int mHeight; private int mLayoutSize; + private boolean mIsLeftToRight; private Locale mLocale; private NumberFormat mIntegerFormat; @@ -192,6 +196,8 @@ public class PeopleTileViewHelper { mWidth = width; mHeight = height; mLayoutSize = getLayoutSize(); + mIsLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) + == View.LAYOUT_DIRECTION_LTR; } /** @@ -656,7 +662,7 @@ public class PeopleTileViewHelper { private RemoteViews createMissedCallRemoteViews() { RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(), getLayoutForContent())); - views.setViewVisibility(R.id.predefined_icon, View.VISIBLE); + setPredefinedIconVisible(views); views.setViewVisibility(R.id.text_content, View.VISIBLE); views.setViewVisibility(R.id.messages_count, View.GONE); setMaxLines(views, false); @@ -675,19 +681,39 @@ public class PeopleTileViewHelper { return views; } + private void setPredefinedIconVisible(RemoteViews views) { + views.setViewVisibility(R.id.predefined_icon, View.VISIBLE); + if (mLayoutSize == LAYOUT_MEDIUM) { + int endPadding = mContext.getResources().getDimensionPixelSize( + R.dimen.before_predefined_icon_padding); + views.setViewPadding(R.id.name, mIsLeftToRight ? 0 : endPadding, 0, + mIsLeftToRight ? endPadding : 0, + 0); + } + } + private RemoteViews createNotificationRemoteViews() { RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(), getLayoutForNotificationContent())); CharSequence sender = mTile.getNotificationSender(); - Uri image = mTile.getNotificationDataUri(); - if (image != null) { - // TODO: Use NotificationInlineImageCache - views.setImageViewUri(R.id.image, image); + Uri imageUri = mTile.getNotificationDataUri(); + if (imageUri != null) { String newImageDescription = mContext.getString( R.string.new_notification_image_content_description, mTile.getUserName()); views.setContentDescription(R.id.image, newImageDescription); views.setViewVisibility(R.id.image, View.VISIBLE); views.setViewVisibility(R.id.text_content, View.GONE); + try { + Drawable drawable = resolveImage(imageUri, mContext); + Bitmap bitmap = convertDrawableToBitmap(drawable); + views.setImageViewBitmap(R.id.image, bitmap); + } catch (IOException e) { + Log.e(TAG, "Could not decode image: " + e); + // If we couldn't load the image, show text that we have a new image. + views.setTextViewText(R.id.text_content, newImageDescription); + views.setViewVisibility(R.id.text_content, View.VISIBLE); + views.setViewVisibility(R.id.image, View.GONE); + } } else { setMaxLines(views, !TextUtils.isEmpty(sender)); CharSequence content = mTile.getNotificationContent(); @@ -705,6 +731,13 @@ public class PeopleTileViewHelper { views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message); } if (mTile.getMessagesCount() > 1) { + if (mLayoutSize == LAYOUT_MEDIUM) { + int endPadding = mContext.getResources().getDimensionPixelSize( + R.dimen.before_messages_count_padding); + views.setViewPadding(R.id.name, mIsLeftToRight ? 0 : endPadding, 0, + mIsLeftToRight ? endPadding : 0, + 0); + } views.setViewVisibility(R.id.messages_count, View.VISIBLE); views.setTextViewText(R.id.messages_count, getMessagesCountText(mTile.getMessagesCount())); @@ -722,6 +755,40 @@ public class PeopleTileViewHelper { return views; } + private Drawable resolveImage(Uri uri, Context context) throws IOException { + final ImageDecoder.Source source = + ImageDecoder.createSource(context.getContentResolver(), uri); + final Drawable drawable = + ImageDecoder.decodeDrawable(source, (decoder, info, s) -> { + onHeaderDecoded(decoder, info, s); + }); + return drawable; + } + + private static int getPowerOfTwoForSampleRatio(double ratio) { + final int k = Integer.highestOneBit((int) Math.floor(ratio)); + return Math.max(1, k); + } + + private void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info, + ImageDecoder.Source source) { + int widthInPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mWidth, + mContext.getResources().getDisplayMetrics()); + int heightInPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mHeight, + mContext.getResources().getDisplayMetrics()); + int maxIconSizeInPx = Math.max(widthInPx, heightInPx); + int minDimen = (int) (1.5 * Math.min(widthInPx, heightInPx)); + if (minDimen < maxIconSizeInPx) { + maxIconSizeInPx = minDimen; + } + final Size size = info.getSize(); + final int originalSize = Math.max(size.getHeight(), size.getWidth()); + final double ratio = (originalSize > maxIconSizeInPx) + ? originalSize * 1f / maxIconSizeInPx + : 1.0; + decoder.setTargetSampleSize(getPowerOfTwoForSampleRatio(ratio)); + } + private void setContentDescriptionForNotificationTextContent(RemoteViews views, CharSequence content, CharSequence sender) { String newTextDescriptionWithNotificationContent = mContext.getString( @@ -757,7 +824,7 @@ public class PeopleTileViewHelper { if (TextUtils.isEmpty(statusText)) { statusText = getStatusTextByType(status.getActivity()); } - views.setViewVisibility(R.id.predefined_icon, View.VISIBLE); + setPredefinedIconVisible(views); views.setTextViewText(R.id.text_content, statusText); if (status.getActivity() == ACTIVITY_BIRTHDAY @@ -867,13 +934,11 @@ public class PeopleTileViewHelper { * on the status layouts compared to all other layouts. */ private void setAvailabilityDotPadding(RemoteViews views, int resId) { - boolean isLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) - == View.LAYOUT_DIRECTION_LTR; int startPadding = mContext.getResources().getDimensionPixelSize(resId); int bottomPadding = mContext.getResources().getDimensionPixelSize( R.dimen.medium_content_padding_above_name); views.setViewPadding(R.id.medium_content, - isLeftToRight ? startPadding : 0, 0, isLeftToRight ? 0 : startPadding, + mIsLeftToRight ? startPadding : 0, 0, mIsLeftToRight ? 0 : startPadding, bottomPadding); } @@ -1071,6 +1136,7 @@ public class PeopleTileViewHelper { views.setViewPadding(R.id.content, horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); + views.setViewPadding(R.id.name, 0, 0, 0, 0); // Expand the name font on medium if there's space. int heightRequiredForMaxContentText = (int) (mContext.getResources().getDimension( R.dimen.medium_height_for_max_name_text_size) / mDensity); diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java index 3320fbda6fe5..985903435b9a 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java @@ -375,7 +375,7 @@ public class PeopleSpaceWidgetManager { widgetSp.getInt(USER_ID, INVALID_USER_ID), widgetSp.getString(PACKAGE_NAME, EMPTY_STRING)); - return getTileFromPersistentStorage(key, appWidgetId); + return getTileFromPersistentStorage(key, appWidgetId, /* supplementFromStorage= */ true); } /** @@ -383,7 +383,8 @@ public class PeopleSpaceWidgetManager { * If a {@link PeopleTileKey} is not provided, fetch one from {@link SharedPreferences}. */ @Nullable - public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId) throws + public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId, + boolean supplementFromStorage) throws PackageManager.NameNotFoundException { if (!PeopleTileKey.isValid(key)) { Log.e(TAG, "PeopleTileKey invalid: " + key.toString()); @@ -412,7 +413,8 @@ public class PeopleSpaceWidgetManager { // Supplement with our storage. String contactUri = mSharedPrefs.getString(String.valueOf(appWidgetId), null); - if (contactUri != null && storedTile.build().getContactUri() == null) { + if (supplementFromStorage && contactUri != null + && storedTile.build().getContactUri() == null) { if (DEBUG) Log.d(TAG, "Restore contact uri from storage: " + contactUri); storedTile.setContactUri(Uri.parse(contactUri)); } @@ -811,7 +813,8 @@ public class PeopleSpaceWidgetManager { if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId); PeopleSpaceTile tile = null; try { - tile = getTileFromPersistentStorage(key, appWidgetId); + tile = getTileFromPersistentStorage(key, appWidgetId, /* supplementFromStorage= */ + false); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Cannot add widget since app was uninstalled"); return; @@ -850,7 +853,9 @@ public class PeopleSpaceWidgetManager { } catch (Exception e) { Log.w(TAG, "Exception caching shortcut:" + e); } - updateAppWidgetOptionsAndView(appWidgetId, tile); + PeopleSpaceTile finalTile = tile; + mBgExecutor.execute( + () -> updateAppWidgetOptionsAndView(appWidgetId, finalTile)); } /** Registers a conversation listener for {@code appWidgetId} if not already registered. */ @@ -1071,7 +1076,7 @@ public class PeopleSpaceWidgetManager { return; } for (int appWidgetId : appWidgetIds) { - if (DEBUG) Log.d(TAG, "Updating widget from broadcast, widget id: " + appWidgetId); + if (DEBUG) Log.d(TAG, "Updating widget from broadcast, widget id: " + appWidgetId); PeopleSpaceTile existingTile = null; PeopleSpaceTile updatedTile = null; try { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index 1d6c7c94dcc3..929927e5d4e4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -212,6 +212,11 @@ public class QSDetail extends LinearLayout { Dependency.get(CommandQueue.class).animateCollapsePanels(); mTriggeredExpand = false; } + // Always animate on close, even if the last opened detail adapter had shouldAnimate() + // return false. This is necessary to avoid a race condition which could leave the + // keyguard in a bad state where QS remains visible underneath the notifications, clock, + // and status area. + mShouldAnimate = true; } boolean visibleDiff = wasShowingDetail != showingDetail; @@ -245,10 +250,15 @@ public class QSDetail extends LinearLayout { mClosingDetail = true; mDetailAdapter = null; listener = mTeardownDetailWhenDone; - mHeader.setVisibility(View.VISIBLE); - mFooter.setVisibility(View.VISIBLE); - mQsPanelController.setGridContentVisibility(true); - mQsPanelCallback.onScanStateChanged(false); + // Only update visibility if already expanded. Otherwise, a race condition can cause the + // keyguard to enter a bad state where the QS tiles are displayed underneath the + // notifications, clock, and status area. + if (mQsPanelController.isExpanded()) { + mHeader.setVisibility(View.VISIBLE); + mFooter.setVisibility(View.VISIBLE); + mQsPanelController.setGridContentVisibility(true); + mQsPanelCallback.onScanStateChanged(false); + } } sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); animateDetailVisibleDiff(x, y, visibleDiff, listener); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index 1d791f5d632c..d262412d5182 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.broadcast.BroadcastDispatcher; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -204,9 +205,14 @@ public class TileLifecycleManager extends BroadcastReceiver implements if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent + " " + mUser); // Give it another chance next time it needs to be bound, out of kindness. mBindTryCount = 0; - mWrapper = null; + freeWrapper(); if (mIsBound) { - mContext.unbindService(this); + try { + mContext.unbindService(this); + } catch (Exception e) { + Log.e(TAG, "Failed to unbind service " + + mIntent.getComponent().flattenToShortString(), e); + } mIsBound = false; } } @@ -290,7 +296,9 @@ public class TileLifecycleManager extends BroadcastReceiver implements private void handleDeath() { if (mWrapper == null) return; - mWrapper = null; + freeWrapper(); + // Clearly not bound anymore + mIsBound = false; if (!mBound) return; if (DEBUG) Log.d(TAG, "handleDeath"); if (checkComponentState()) { @@ -472,6 +480,18 @@ public class TileLifecycleManager extends BroadcastReceiver implements return mToken; } + private void freeWrapper() { + if (mWrapper != null) { + try { + mWrapper.asBinder().unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + Log.w(TAG, "Trying to unlink not linked recipient for component" + + mIntent.getComponent().flattenToShortString()); + } + mWrapper = null; + } + } + public interface TileChangeListener { void onTileChanged(ComponentName tile); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java index 45c71744e0ec..fa2d4447f26d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; +import static android.os.UserManager.DISALLOW_CAMERA_TOGGLE; import static com.android.systemui.DejankUtils.whitelistIpcs; @@ -86,4 +87,9 @@ public class CameraToggleTile extends SensorPrivacyToggleTile { public @Sensor int getSensorId() { return CAMERA; } + + @Override + public String getRestriction() { + return DISALLOW_CAMERA_TOGGLE; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java index 48a1ad673d76..f4f0b2cdc432 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles; import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; +import static android.os.UserManager.DISALLOW_MICROPHONE_TOGGLE; import static com.android.systemui.DejankUtils.whitelistIpcs; @@ -86,4 +87,9 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile { public @Sensor int getSensorId() { return MICROPHONE; } + + @Override + public String getRestriction() { + return DISALLOW_MICROPHONE_TOGGLE; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java index bf72b7728232..b0a1b18a8cd5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.hardware.SensorPrivacyManager.Sensors.Sensor; import android.os.Handler; import android.os.Looper; +import android.provider.Settings; import android.service.quicksettings.Tile; import android.view.View; import android.widget.Switch; @@ -63,6 +64,11 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS */ public abstract @DrawableRes int getIconRes(boolean isBlocked); + /** + * @return the user restriction name + */ + public abstract String getRestriction(); + protected SensorPrivacyToggleTile(QSHost host, @Background Looper backgroundLooper, @Main Handler mainHandler, @@ -103,6 +109,8 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS boolean isBlocked = arg == null ? mSensorPrivacyController.isSensorBlocked(getSensorId()) : (boolean) arg; + checkIfRestrictionEnforcedByAdminOnly(state, getRestriction()); + state.icon = ResourceIcon.get(getIconRes(isBlocked)); state.state = isBlocked ? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE; state.value = !isBlocked; @@ -112,7 +120,6 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS } else { state.secondaryLabel = mContext.getString(R.string.quick_settings_camera_mic_available); } - state.handlesLongClick = false; state.contentDescription = state.label; state.expandedAccessibilityClassName = Switch.class.getName(); } @@ -124,7 +131,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS @Override public Intent getLongClickIntent() { - return null; + return new Intent(Settings.ACTION_PRIVACY_SETTINGS); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt index ef18df5706ad..f0fb5ebf9e1d 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt @@ -17,6 +17,7 @@ package com.android.systemui.sensorprivacy import android.content.DialogInterface +import android.content.Intent import android.content.Intent.EXTRA_PACKAGE_NAME import android.content.pm.PackageManager import android.content.res.Resources @@ -178,7 +179,7 @@ class SensorUseStartedActivity @Inject constructor( override fun onStart() { super.onStart() - sensorPrivacyController.suppressSensorPrivacyReminders(sensorUsePackageName, true) + setSuppressed(true) unsuppressImmediately = false } @@ -218,12 +219,10 @@ class SensorUseStartedActivity @Inject constructor( super.onStop() if (unsuppressImmediately) { - sensorPrivacyController - .suppressSensorPrivacyReminders(sensorUsePackageName, false) + setSuppressed(false) } else { bgHandler.postDelayed({ - sensorPrivacyController - .suppressSensorPrivacyReminders(sensorUsePackageName, false) + setSuppressed(false) }, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS) } } @@ -237,6 +236,11 @@ class SensorUseStartedActivity @Inject constructor( // do not allow backing out } + override fun onNewIntent(intent: Intent?) { + setIntent(intent) + recreate() + } + private fun disableSensorPrivacy() { if (sensor == ALL_SENSORS) { sensorPrivacyController.setSensorBlocked(DIALOG, MICROPHONE, false) @@ -247,4 +251,16 @@ class SensorUseStartedActivity @Inject constructor( unsuppressImmediately = true setResult(RESULT_OK) } + + private fun setSuppressed(suppressed: Boolean) { + if (sensor == ALL_SENSORS) { + sensorPrivacyController + .suppressSensorPrivacyReminders(MICROPHONE, suppressed) + sensorPrivacyController + .suppressSensorPrivacyReminders(CAMERA, suppressed) + } else { + sensorPrivacyController + .suppressSensorPrivacyReminders(sensor, suppressed) + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java index b6aed23e64ee..180f81c22a9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java @@ -131,7 +131,7 @@ public class RemoteInputController { */ public void removeRemoteInput(NotificationEntry entry, Object token) { Objects.requireNonNull(entry); - if (entry.mRemoteEditImeVisible) return; + if (entry.mRemoteEditImeVisible && entry.mRemoteEditImeAnimatingAway) return; // If the view is being removed, this may be called even though we're not active if (!isRemoteInputActive(entry)) return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index a00d01427ebc..5302188ccb31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -416,10 +416,12 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi return mIcon.icon; } - private Drawable getIcon(StatusBarIcon icon) { - Context notifContext = mNotification != null ? - mNotification.getPackageContext(getContext()) : getContext(); - return getIcon(getContext(), notifContext, icon); + Drawable getIcon(StatusBarIcon icon) { + Context notifContext = getContext(); + if (mNotification != null) { + notifContext = mNotification.getPackageContext(getContext()); + } + return getIcon(getContext(), notifContext != null ? notifContext : getContext(), icon); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 96b0e7819c7a..94ee868ceebc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -183,6 +183,7 @@ public final class NotificationEntry extends ListEntry { private boolean mIsMarkedForUserTriggeredMovement; private boolean mIsAlerting; + public boolean mRemoteEditImeAnimatingAway; public boolean mRemoteEditImeVisible; private boolean mExpandAnimationRunning; 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 e65038b32bf0..f460a132d65c 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 @@ -148,8 +148,22 @@ public class StackScrollAlgorithm { AmbientState ambientState) { NotificationShelf shelf = ambientState.getShelf(); - if (shelf != null) { - shelf.updateState(algorithmState, ambientState); + if (shelf == null) { + return; + } + + shelf.updateState(algorithmState, ambientState); + + // After the shelf has updated its yTranslation, + // explicitly hide views below the shelf to skip rendering them in the hardware layer. + final float shelfTop = shelf.getViewState().yTranslation; + + for (ExpandableView view : algorithmState.visibleChildren) { + final float viewTop = view.getViewState().yTranslation; + + if (viewTop >= shelfTop) { + view.getViewState().hidden = true; + } } } @@ -411,8 +425,7 @@ public class StackScrollAlgorithm { } else { if (view != ambientState.getTrackedHeadsUpRow()) { if (ambientState.isExpansionChanging()) { - // Show all views. Views below the shelf will later be clipped (essentially - // hidden) in NotificationShelf. + // We later update shelf state, then hide views below the shelf. viewState.hidden = false; viewState.inShelf = algorithmState.firstViewInShelf != null && i >= algorithmState.visibleChildren.indexOf( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 16f8319928bb..91d503bac4fe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -74,6 +74,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.settingslib.Utils; import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -459,6 +460,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (tileIcon != null) { mWalletButton.setImageDrawable(tileIcon); } + mWalletButton.getDrawable().setTint( + Utils.getColorAttr( + mContext, + com.android.internal.R.attr.textColorPrimary).getDefaultColor()); mWalletButton.setVisibility(VISIBLE); mWalletButton.setOnClickListener(this::onWalletClick); mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index d6ea4a828395..8c0dfc5f7ab4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -87,7 +87,7 @@ public class KeyguardBouncer { private final Runnable mResetRunnable = ()-> { if (mKeyguardViewController != null) { mKeyguardViewController.resetSecurityContainer(); - for (KeyguardResetCallback callback : mResetCallbacks) { + for (KeyguardResetCallback callback : new ArrayList<>(mResetCallbacks)) { callback.onKeyguardReset(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index f52aad96ce69..3c1892d4b7ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -113,6 +113,7 @@ import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.qs.QSDetailDisplayer; +import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FeatureFlags; @@ -327,6 +328,7 @@ public class NotificationPanelViewController extends PanelViewController { private final int mMaxKeyguardNotifications; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; private final TapAgainViewController mTapAgainViewController; + private final RecordingController mRecordingController; private boolean mShouldUseSplitNotificationShade; // Current max allowed keyguard notifications determined by measuring the panel private int mMaxAllowedKeyguardNotifications; @@ -711,6 +713,7 @@ public class NotificationPanelViewController extends PanelViewController { FragmentService fragmentService, ContentResolver contentResolver, QuickAccessWalletController quickAccessWalletController, + RecordingController recordingController, @Main Executor uiExecutor, SecureSettings secureSettings, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, @@ -755,6 +758,7 @@ public class NotificationPanelViewController extends PanelViewController { mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle()); setPanelAlpha(255, false /* animate */); mCommandQueue = commandQueue; + mRecordingController = recordingController; mDisplayId = displayId; mPulseExpansionHandler = pulseExpansionHandler; mDozeParameters = dozeParameters; @@ -1571,7 +1575,10 @@ public class NotificationPanelViewController extends PanelViewController { public void expandWithQsDetail(DetailAdapter qsDetailAdapter) { traceQsJank(true /* startTracing */, false /* wasCancelled */); flingSettings(0 /* velocity */, FLING_EXPAND); - mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, 0, 0); + // When expanding with a panel, there's no meaningful touch point to correspond to. Set the + // origin to somewhere above the screen. This is used for animations. + int x = mQsFrame.getWidth() / 2; + mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, x, -getHeight()); if (mAccessibilityManager.isEnabled()) { mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle()); } @@ -2359,7 +2366,8 @@ public class NotificationPanelViewController extends PanelViewController { // The padding on this area is large enough that we can use a cheaper clipping strategy mKeyguardStatusAreaClipBounds.set(left, top, right, bottom); clipStatusView = qsVisible; - radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius, + float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius; + radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius, Math.min(top / (float) mScrimCornerRadius, 1f)); statusBarClipTop = top - mKeyguardStatusBar.getTop(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 022faf78b946..5e105bb64350 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -55,16 +55,18 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.google.android.collect.Lists; - import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; +import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.inject.Inject; @@ -100,7 +102,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private ForcePluginOpenListener mForcePluginOpenListener; private Consumer<Integer> mScrimsVisibilityListener; private final ArrayList<WeakReference<StatusBarWindowCallback>> - mCallbacks = Lists.newArrayList(); + mCallbacks = new ArrayList<>(); private final SysuiColorExtractor mColorExtractor; private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @@ -464,13 +466,15 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW @Override public void notifyStateChangedCallbacks() { - for (int i = 0; i < mCallbacks.size(); i++) { - StatusBarWindowCallback cb = mCallbacks.get(i).get(); - if (cb != null) { - cb.onStateChanged(mCurrentState.mKeyguardShowing, - mCurrentState.mKeyguardOccluded, - mCurrentState.mBouncerShowing); - } + // Copy callbacks to separate ArrayList to avoid concurrent modification + List<StatusBarWindowCallback> activeCallbacks = mCallbacks.stream() + .map(Reference::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + for (StatusBarWindowCallback cb : activeCallbacks) { + cb.onStateChanged(mCurrentState.mKeyguardShowing, + mCurrentState.mKeyguardOccluded, + mCurrentState.mBouncerShowing); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index ed7ab6cf9f37..7b110a0ec01f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -107,7 +107,8 @@ public class PhoneStatusBarPolicy private final String mSlotBluetooth; private final String mSlotTty; private final String mSlotZen; - private final String mSlotVolume; + private final String mSlotMute; + private final String mSlotVibrate; private final String mSlotAlarmClock; private final String mSlotManagedProfile; private final String mSlotRotate; @@ -149,7 +150,8 @@ public class PhoneStatusBarPolicy private final PrivacyLogger mPrivacyLogger; private boolean mZenVisible; - private boolean mVolumeVisible; + private boolean mVibrateVisible; + private boolean mMuteVisible; private boolean mCurrentUserSetup; private boolean mManagedProfileIconVisible = false; @@ -207,7 +209,8 @@ public class PhoneStatusBarPolicy mSlotBluetooth = resources.getString(com.android.internal.R.string.status_bar_bluetooth); mSlotTty = resources.getString(com.android.internal.R.string.status_bar_tty); mSlotZen = resources.getString(com.android.internal.R.string.status_bar_zen); - mSlotVolume = resources.getString(com.android.internal.R.string.status_bar_volume); + mSlotMute = resources.getString(com.android.internal.R.string.status_bar_mute); + mSlotVibrate = resources.getString(com.android.internal.R.string.status_bar_volume); mSlotAlarmClock = resources.getString(com.android.internal.R.string.status_bar_alarm_clock); mSlotManagedProfile = resources.getString( com.android.internal.R.string.status_bar_managed_profile); @@ -264,9 +267,14 @@ public class PhoneStatusBarPolicy mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null); mIconController.setIconVisibility(mSlotZen, false); - // volume - mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null); - mIconController.setIconVisibility(mSlotVolume, false); + // vibrate + mIconController.setIcon(mSlotVibrate, R.drawable.stat_sys_ringer_vibrate, + mResources.getString(R.string.accessibility_ringer_vibrate)); + mIconController.setIconVisibility(mSlotVibrate, false); + // mute + mIconController.setIcon(mSlotMute, R.drawable.stat_sys_ringer_silent, + mResources.getString(R.string.accessibility_ringer_silent)); + mIconController.setIconVisibility(mSlotMute, false); updateVolumeZen(); // cast @@ -372,9 +380,8 @@ public class PhoneStatusBarPolicy int zenIconId = 0; String zenDescription = null; - boolean volumeVisible = false; - int volumeIconId = 0; - String volumeDescription = null; + boolean vibrateVisible = false; + boolean muteVisible = false; int zen = mZenController.getZen(); if (DndTile.isVisible(mSharedPreferences) || DndTile.isCombinedIcon(mSharedPreferences)) { @@ -396,13 +403,9 @@ public class PhoneStatusBarPolicy mRingerModeTracker.getRingerModeInternal().getValue(); if (ringerModeInternal != null) { if (ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) { - volumeVisible = true; - volumeIconId = R.drawable.stat_sys_ringer_vibrate; - volumeDescription = mResources.getString(R.string.accessibility_ringer_vibrate); + vibrateVisible = true; } else if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { - volumeVisible = true; - volumeIconId = R.drawable.stat_sys_ringer_silent; - volumeDescription = mResources.getString(R.string.accessibility_ringer_silent); + muteVisible = true; } } } @@ -415,13 +418,16 @@ public class PhoneStatusBarPolicy mZenVisible = zenVisible; } - if (volumeVisible) { - mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription); + if (vibrateVisible != mVibrateVisible) { + mIconController.setIconVisibility(mSlotVibrate, vibrateVisible); + mVibrateVisible = vibrateVisible; } - if (volumeVisible != mVolumeVisible) { - mIconController.setIconVisibility(mSlotVolume, volumeVisible); - mVolumeVisible = volumeVisible; + + if (muteVisible != mMuteVisible) { + mIconController.setIconVisibility(mSlotMute, muteVisible); + mMuteVisible = muteVisible; } + updateAlarm(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 89711fa6b11e..db7ead7c1531 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -55,6 +55,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; +import android.app.TaskInfo; import android.app.UiModeManager; import android.app.WallpaperInfo; import android.app.WallpaperManager; @@ -247,6 +248,8 @@ import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; +import com.android.wm.shell.startingsurface.SplashscreenContentDrawer; +import com.android.wm.shell.startingsurface.StartingSurface; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -268,7 +271,7 @@ public class StatusBar extends SystemUI implements DemoMode, ColorExtractor.OnColorsChangedListener, ConfigurationListener, StatusBarStateController.StateListener, LifecycleOwner, BatteryController.BatteryStateChangeCallback, - ActivityLaunchAnimator.KeyguardHandler { + ActivityLaunchAnimator.Callback { public static final boolean MULTIUSER_DEBUG = false; protected static final int MSG_HIDE_RECENT_APPS = 1020; @@ -685,9 +688,7 @@ public class StatusBar extends SystemUI implements DemoMode, new FalsingManager.FalsingBeliefListener() { @Override public void onFalse() { - // Hides quick settings. - mNotificationPanelViewController.resetViews(true); - // Hides bouncer and quick-quick settings. + // Hides quick settings, bouncer, and quick-quick settings. mStatusBarKeyguardViewManager.reset(true); } }; @@ -705,6 +706,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final Optional<BubblesManager> mBubblesManagerOptional; private final Optional<Bubbles> mBubblesOptional; private final Bubbles.BubbleExpandListener mBubbleExpandListener; + private final Optional<StartingSurface> mStartingSurfaceOptional; private ActivityIntentHelper mActivityIntentHelper; private NotificationStackScrollLayoutController mStackScrollerController; @@ -804,7 +806,8 @@ public class StatusBar extends SystemUI implements DemoMode, LockscreenShadeTransitionController lockscreenShadeTransitionController, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController, - UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, + Optional<StartingSurface> startingSurfaceOptional) { super(context); mNotificationsController = notificationsController; mLightBarController = lightBarController; @@ -891,6 +894,7 @@ public class StatusBar extends SystemUI implements DemoMode, mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mLockscreenShadeTransitionController = lockscreenShadeTransitionController; + mStartingSurfaceOptional = startingSurfaceOptional; lockscreenShadeTransitionController.setStatusbar(this); mExpansionChangedListeners = new ArrayList<>(); @@ -2119,6 +2123,16 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled); } + @Override + public int getBackgroundColor(TaskInfo task) { + if (!mStartingSurfaceOptional.isPresent()) { + Log.w(TAG, "No starting surface, defaulting to SystemBGColor"); + return SplashscreenContentDrawer.getSystemBGColor(); + } + + return mStartingSurfaceOptional.get().getBackgroundColor(task); + } + public boolean isDeviceInVrMode() { return mPresenter.isDeviceInVrMode(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 6f63b1780d68..8a7708aaa8c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -521,7 +521,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void reset(boolean hideBouncerWhenShowing) { if (mShowing) { - mNotificationPanelViewController.closeQs(); + // Hide quick settings. + mNotificationPanelViewController.resetViews(/* animate= */ true); + // Hide bouncer and quick-quick settings. if (mOccluded && !mDozing) { mStatusBar.hideKeyguard(); if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) { 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 98b9cc9bc716..9a6dd38ffca5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -514,7 +514,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON ); ActivityLaunchAnimator.Controller animationController = - new StatusBarLaunchAnimatorController(viewController, mStatusBar, + viewController == null ? null + : new StatusBarLaunchAnimatorController(viewController, mStatusBar, true /* isActivityIntent */); mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index 95712cd303f5..262dc837f22c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -132,7 +132,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, if (!row.isPinned()) { mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); } - mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */); + mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); mPendingRemoteInputView = clicked; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 2611ab5f7016..716d1dbc6462 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -109,6 +109,7 @@ import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; +import com.android.wm.shell.startingsurface.StartingSurface; import java.util.Optional; import java.util.concurrent.Executor; @@ -218,7 +219,8 @@ public interface StatusBarPhoneModule { LockscreenShadeTransitionController transitionController, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController, - UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, + Optional<StartingSurface> startingSurfaceOptional) { return new StatusBar( context, notificationsController, @@ -306,6 +308,7 @@ public interface StatusBarPhoneModule { transitionController, featureFlags, keyguardUnlockAnimationController, - unlockedScreenOffAnimationController); + unlockedScreenOffAnimationController, + startingSurfaceOptional); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 081fe5a47626..a8097c4d74b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -41,6 +41,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashSet; /** @@ -157,7 +158,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { NotificationPeekEvent.NOTIFICATION_PEEK, entry.getSbn().getUid(), entry.getSbn().getPackageName(), entry.getSbn().getInstanceId()); } - for (OnHeadsUpChangedListener listener : mListeners) { + for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) { if (isPinned) { listener.onHeadsUpPinned(entry); } else { @@ -177,7 +178,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { entry.setHeadsUp(true); setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(entry)); EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 1 /* visible */); - for (OnHeadsUpChangedListener listener : mListeners) { + for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) { listener.onHeadsUpStateChanged(entry, true); } } @@ -188,7 +189,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { entry.setHeadsUp(false); setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */); EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */); - for (OnHeadsUpChangedListener listener : mListeners) { + for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) { listener.onHeadsUpStateChanged(entry, false); } } @@ -206,7 +207,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { if (mHasPinnedNotification) { MetricsLogger.count(mContext, "note_peek", 1); } - for (OnHeadsUpChangedListener listener : mListeners) { + for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) { listener.onHeadsUpPinnedModeChanged(hasPinnedNotification); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java index acfdda4cea49..e01b95e81da8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java @@ -29,7 +29,7 @@ public interface IndividualSensorPrivacyController extends void setSensorBlocked(@Source int source, @Sensor int sensor, boolean blocked); - void suppressSensorPrivacyReminders(String packageName, boolean suppress); + void suppressSensorPrivacyReminders(int sensor, boolean suppress); interface Callback { void onSensorBlockedChanged(@Sensor int sensor, boolean blocked); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java index 9807165f69d0..1d71301c7454 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java @@ -68,8 +68,8 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr } @Override - public void suppressSensorPrivacyReminders(String packageName, boolean suppress) { - mSensorPrivacyManager.suppressSensorPrivacyReminders(packageName, suppress); + public void suppressSensorPrivacyReminders(int sensor, boolean suppress) { + mSensorPrivacyManager.suppressSensorPrivacyReminders(sensor, suppress); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index b18dfd2866c4..84d7c05ddc14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -272,6 +272,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene public void onEnd(@NonNull WindowInsetsAnimation animation) { super.onEnd(animation); if (animation.getTypeMask() == WindowInsets.Type.ime()) { + mEntry.mRemoteEditImeAnimatingAway = false; mEntry.mRemoteEditImeVisible = mEditText.getRootWindowInsets().isVisible(WindowInsets.Type.ime()); if (!mEntry.mRemoteEditImeVisible && !mEditText.mShowImeOnInputConnection) { @@ -392,6 +393,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mSendButton.setVisibility(INVISIBLE); mProgressBar.setVisibility(VISIBLE); mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime(); + mEntry.mRemoteEditImeAnimatingAway = true; mController.addSpinning(mEntry.getKey(), mToken); mController.removeRemoteInput(mEntry, mToken); mEditText.mShowImeOnInputConnection = false; @@ -807,7 +809,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } private void onEditTextFocusChanged(RemoteEditText remoteEditText, boolean focused) { - for (View.OnFocusChangeListener listener : mEditTextFocusChangeListeners) { + for (View.OnFocusChangeListener listener : new ArrayList<>(mEditTextFocusChangeListeners)) { listener.onFocusChange(remoteEditText, focused); } } diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 11ddbd045cd4..81999b534046 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -450,19 +450,23 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { OverlayIdentifier systemPalette = categoryToPackage.get(OVERLAY_CATEGORY_SYSTEM_PALETTE); if (mIsMonetEnabled && systemPalette != null && systemPalette.getPackageName() != null) { try { - int color = Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16); + String colorString = systemPalette.getPackageName().toLowerCase(); + if (!colorString.startsWith("#")) { + colorString = "#" + colorString; + } + int color = Color.parseColor(colorString); mNeutralOverlay = getOverlay(color, NEUTRAL); mNeedsOverlayCreation = true; categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE); - } catch (NumberFormatException e) { - Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName()); + } catch (Exception e) { + // Color.parseColor doesn't catch any exceptions from the calls it makes + Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName(), e); } } else if (!mIsMonetEnabled && systemPalette != null) { try { // It's possible that we flipped the flag off and still have a @ColorInt in the // setting. We need to sanitize the input, otherwise the overlay transaction will // fail. - Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16); categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE); } catch (NumberFormatException e) { // This is a package name. All good, let's continue @@ -473,12 +477,17 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { OverlayIdentifier accentPalette = categoryToPackage.get(OVERLAY_CATEGORY_ACCENT_COLOR); if (mIsMonetEnabled && accentPalette != null && accentPalette.getPackageName() != null) { try { - int color = Integer.parseInt(accentPalette.getPackageName().toLowerCase(), 16); + String colorString = accentPalette.getPackageName().toLowerCase(); + if (!colorString.startsWith("#")) { + colorString = "#" + colorString; + } + int color = Color.parseColor(colorString); mSecondaryOverlay = getOverlay(color, ACCENT); mNeedsOverlayCreation = true; categoryToPackage.remove(OVERLAY_CATEGORY_ACCENT_COLOR); - } catch (NumberFormatException e) { - Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName()); + } catch (Exception e) { + // Color.parseColor doesn't catch any exceptions from the calls it makes + Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName(), e); } } else if (!mIsMonetEnabled && accentPalette != null) { try { diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java index 361604c461b4..a40cf4f37cc3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java @@ -101,7 +101,12 @@ abstract public class SafetyWarningDialog extends SystemUIDialog @Override public void onDismiss(DialogInterface unused) { - mContext.unregisterReceiver(mReceiver); + try { + mContext.unregisterReceiver(mReceiver); + } catch (IllegalArgumentException e) { + // Don't crash if the receiver has already been unregistered. + e.printStackTrace(); + } cleanUp(); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 5de7846a820e..3320852ca1f4 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -1743,7 +1743,7 @@ public class VolumeDialogImpl implements VolumeDialog, mContext, android.R.attr.colorBackgroundFloating); final ColorStateList inverseTextTint = Utils.getColorAttr( - mContext, com.android.internal.R.attr.textColorPrimaryInverse); + mContext, com.android.internal.R.attr.textColorOnAccent); row.sliderProgressSolid.setTintList(colorTint); if (row.sliderBgIcon != null) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt index d01cdd45181f..14f112b8b071 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt @@ -10,10 +10,12 @@ import android.graphics.Rect import android.os.Looper import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import android.util.Log import android.view.IRemoteAnimationFinishedCallback import android.view.RemoteAnimationAdapter import android.view.RemoteAnimationTarget import android.view.SurfaceControl +import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import androidx.test.filters.SmallTest @@ -25,6 +27,7 @@ import junit.framework.Assert.assertNotNull import junit.framework.Assert.assertNull import junit.framework.Assert.assertTrue import junit.framework.AssertionFailedError +import kotlin.concurrent.thread import org.junit.Before import org.junit.Rule import org.junit.Test @@ -37,23 +40,23 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Spy import org.mockito.junit.MockitoJUnit -import kotlin.concurrent.thread @SmallTest @RunWith(AndroidTestingRunner::class) @RunWithLooper class ActivityLaunchAnimatorTest : SysuiTestCase() { private val launchContainer = LinearLayout(mContext) - @Mock lateinit var keyguardHandler: ActivityLaunchAnimator.KeyguardHandler + @Mock lateinit var callback: ActivityLaunchAnimator.Callback @Spy private val controller = TestLaunchAnimatorController(launchContainer) @Mock lateinit var iCallback: IRemoteAnimationFinishedCallback + @Mock lateinit var failHandler: Log.TerribleFailureHandler private lateinit var activityLaunchAnimator: ActivityLaunchAnimator @get:Rule val rule = MockitoJUnit.rule() @Before fun setup() { - activityLaunchAnimator = ActivityLaunchAnimator(keyguardHandler, mContext) + activityLaunchAnimator = ActivityLaunchAnimator(callback, mContext) } private fun startIntentWithAnimation( @@ -116,8 +119,8 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { @Test fun animatesIfActivityIsAlreadyOpenAndIsOnKeyguard() { - `when`(keyguardHandler.isOnKeyguard()).thenReturn(true) - val animator = ActivityLaunchAnimator(keyguardHandler, context) + `when`(callback.isOnKeyguard()).thenReturn(true) + val animator = ActivityLaunchAnimator(callback, context) val willAnimateCaptor = ArgumentCaptor.forClass(Boolean::class.java) var animationAdapter: RemoteAnimationAdapter? = null @@ -129,7 +132,7 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { waitForIdleSync() verify(controller).onIntentStarted(willAnimateCaptor.capture()) - verify(keyguardHandler).hideKeyguardWithAnimation(any()) + verify(callback).hideKeyguardWithAnimation(any()) assertTrue(willAnimateCaptor.value) assertNull(animationAdapter) @@ -171,10 +174,17 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { val runner = activityLaunchAnimator.createRunner(controller) runner.onAnimationStart(0, arrayOf(fakeWindow()), emptyArray(), emptyArray(), iCallback) waitForIdleSync() - verify(keyguardHandler).setBlursDisabledForAppLaunch(eq(true)) + verify(callback).setBlursDisabledForAppLaunch(eq(true)) verify(controller).onLaunchAnimationStart(anyBoolean()) } + @Test + fun controllerFromOrphanViewReturnsNullAndIsATerribleFailure() { + Log.setWtfHandler(failHandler) + assertNull(ActivityLaunchAnimator.Controller.fromView(View(mContext))) + verify(failHandler).onTerribleFailure(any(), any(), anyBoolean()) + } + private fun fakeWindow(): RemoteAnimationTarget { val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */) val taskInfo = ActivityManager.RunningTaskInfo() diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt new file mode 100644 index 000000000000..8cba25dc1b92 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.animation + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.widget.LinearLayout +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class GhostedViewLaunchAnimatorControllerTest : SysuiTestCase() { + @Test + fun animatingOrphanViewDoesNotCrash() { + val ghostedView = LinearLayout(mContext) + val controller = GhostedViewLaunchAnimatorController(ghostedView) + val state = ActivityLaunchAnimator.State(top = 0, bottom = 0, left = 0, right = 0) + + controller.onIntentStarted(willAnimate = true) + controller.onLaunchAnimationStart(isExpandingFullyAbove = true) + controller.onLaunchAnimationProgress(state, progress = 0f, linearProgress = 0f) + controller.onLaunchAnimationEnd(isExpandingFullyAbove = true) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index d8d3676d4fa2..397341b197ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -21,7 +21,10 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -58,6 +61,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.Execution; import com.android.systemui.util.concurrency.FakeExecution; import com.android.systemui.util.concurrency.FakeExecutor; @@ -130,6 +134,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private Vibrator mVibrator; @Mock private UdfpsHapticsSimulator mUdfpsHapticsSimulator; + @Mock + private KeyguardStateController mKeyguardStateController; private FakeExecutor mFgExecutor; @@ -137,6 +143,8 @@ public class UdfpsControllerTest extends SysuiTestCase { @Mock private UdfpsView mUdfpsView; @Mock + private UdfpsKeyguardViewController mUdfpsKeyguardViewController; + @Mock private TypedArray mBrightnessValues; @Mock private TypedArray mBrightnessBacklight; @@ -149,6 +157,8 @@ public class UdfpsControllerTest extends SysuiTestCase { @Captor private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor; private ScreenLifecycle.Observer mScreenObserver; + @Captor private ArgumentCaptor<UdfpsAnimationViewController> mAnimViewControllerCaptor; + @Before public void setUp() { setUpResources(); @@ -193,7 +203,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mScreenLifecycle, mVibrator, mUdfpsHapticsSimulator, - Optional.of(mHbmProvider)); + Optional.of(mHbmProvider), + mKeyguardStateController); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -221,6 +232,76 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test + public void onActionDownTouch_whenCanDismissLockScreen_entersDevice() throws RemoteException { + // GIVEN can dismiss lock screen and the current animation is an UdfpsKeyguardViewController + when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); + + // GIVEN that the overlay is showing + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // WHEN ACTION_DOWN is received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + downEvent.recycle(); + + // THEN notify keyguard authenticate to dismiss the keyguard + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean()); + } + + @Test + public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice() throws RemoteException { + // GIVEN can dismiss lock screen and the current animation is an UdfpsKeyguardViewController + when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); + + // GIVEN that the overlay is showing + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // WHEN ACTION_MOVE is received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + moveEvent.recycle(); + + // THEN notify keyguard authenticate to dismiss the keyguard + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean()); + } + + @Test + public void onMultipleTouch_whenCanDismissLockScreen_entersDeviceOnce() throws RemoteException { + // GIVEN can dismiss lock screen and the current animation is an UdfpsKeyguardViewController + when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); + + // GIVEN that the overlay is showing + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // WHEN multiple touches are received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + downEvent.recycle(); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + moveEvent.recycle(); + + // THEN notify keyguard authenticate to dismiss the keyguard + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean()); + } + + @Test public void showUdfpsOverlay_addsViewToWindow() throws RemoteException { mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); @@ -365,7 +446,11 @@ public class UdfpsControllerTest extends SysuiTestCase { moveEvent.recycle(); // THEN click haptic is played - verify(mVibrator).vibrate(mUdfpsController.EFFECT_CLICK, - UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES); + verify(mVibrator).vibrate( + anyInt(), + anyString(), + eq(mUdfpsController.EFFECT_CLICK), + eq("udfps-onStart"), + eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index 546038ec3030..b2a9e8209495 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -39,7 +39,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener; -import com.android.systemui.dock.DockManagerFake; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -62,7 +61,6 @@ public class BrightLineClassifierTest extends SysuiTestCase { private BrightLineFalsingManager mBrightLineFalsingManager; @Mock private FalsingDataProvider mFalsingDataProvider; - private final DockManagerFake mDockManager = new DockManagerFake(); private final MetricsLogger mMetricsLogger = new FakeMetricsLogger(); private final Set<FalsingClassifier> mClassifiers = new HashSet<>(); @Mock @@ -102,7 +100,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { mClassifiers.add(mClassifierB); when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); - mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager, + mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, mAccessibilityManager, false); @@ -168,7 +166,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { // Even when the classifiers report a false, we should allow. when(mClassifierA.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mPassedResult); - mDockManager.setIsDocked(true); + when(mFalsingDataProvider.isDocked()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java index 86243b53804e..c4f480d7e7aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -32,7 +32,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; -import com.android.systemui.dock.DockManagerFake; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; @@ -52,7 +51,6 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { private BrightLineFalsingManager mBrightLineFalsingManager; @Mock private FalsingDataProvider mFalsingDataProvider; - private final DockManagerFake mDockManager = new DockManagerFake(); private final MetricsLogger mMetricsLogger = new FakeMetricsLogger(); private final Set<FalsingClassifier> mClassifiers = new HashSet<>(); @Mock @@ -84,7 +82,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { mClassifiers.add(mClassifierA); when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); - mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager, + mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mMetricsLogger, mClassifiers, mSingleTapClassifier, mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, mAccessibilityManager, false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java index 7d6ff34bb954..5fa7214f07ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java @@ -19,30 +19,35 @@ package com.android.systemui.classifier; import android.util.DisplayMetrics; import android.view.MotionEvent; -import com.android.systemui.utils.leaks.FakeBatteryController; -import com.android.systemui.utils.leaks.LeakCheckedTest; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.statusbar.policy.BatteryController; import org.junit.After; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; -public class ClassifierTest extends LeakCheckedTest { +public class ClassifierTest extends SysuiTestCase { private FalsingDataProvider mDataProvider; - private List<MotionEvent> mMotionEvents = new ArrayList<>(); + private final List<MotionEvent> mMotionEvents = new ArrayList<>(); private float mOffsetX = 0; private float mOffsetY = 0; - private FakeBatteryController mFakeBatteryController; + @Mock + private BatteryController mBatteryController; + private final DockManagerFake mDockManager = new DockManagerFake(); public void setup() { + MockitoAnnotations.initMocks(this); DisplayMetrics displayMetrics = new DisplayMetrics(); displayMetrics.xdpi = 100; displayMetrics.ydpi = 100; displayMetrics.widthPixels = 1000; displayMetrics.heightPixels = 1000; - mFakeBatteryController = new FakeBatteryController(getLeakCheck()); - mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController); + mDataProvider = new FalsingDataProvider(displayMetrics, mBatteryController, mDockManager); } @After @@ -54,10 +59,6 @@ public class ClassifierTest extends LeakCheckedTest { return mDataProvider; } - FakeBatteryController getFakeBatteryController() { - return mFakeBatteryController; - } - protected void setOffsetX(float offsetX) { mOffsetX = offsetX; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java index 3c41216949c2..d99a5531d353 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java @@ -32,9 +32,12 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dock.DockManager; +import com.android.systemui.dock.DockManagerFake; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.sensors.ProximitySensor; @@ -67,6 +70,9 @@ public class FalsingCollectorImplTest extends SysuiTestCase { private SysuiStatusBarStateController mStatusBarStateController; @Mock private KeyguardStateController mKeyguardStateController; + @Mock + private BatteryController mBatteryController; + private final DockManagerFake mDockManager = new DockManagerFake(); private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock); @@ -79,8 +85,8 @@ public class FalsingCollectorImplTest extends SysuiTestCase { mFalsingCollector = new FalsingCollectorImpl(mFalsingDataProvider, mFalsingManager, mKeyguardUpdateMonitor, mHistoryTracker, mProximitySensor, - mStatusBarStateController, mKeyguardStateController, mFakeExecutor, - mFakeSystemClock); + mStatusBarStateController, mKeyguardStateController, mBatteryController, + mDockManager, mFakeExecutor, mFakeSystemClock); } @Test @@ -91,9 +97,32 @@ public class FalsingCollectorImplTest extends SysuiTestCase { @Test public void testNoProximityWhenWirelessCharging() { - when(mFalsingDataProvider.isWirelessCharging()).thenReturn(true); - mFalsingCollector.onScreenTurningOn(); - verify(mProximitySensor, never()).register(any(ThresholdSensor.Listener.class)); + ArgumentCaptor<BatteryController.BatteryStateChangeCallback> batteryCallbackCaptor = + ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class); + verify(mBatteryController).addCallback(batteryCallbackCaptor.capture()); + batteryCallbackCaptor.getValue().onWirelessChargingChanged(true); + verify(mProximitySensor).pause(); + } + + @Test + public void testProximityWhenOffWirelessCharging() { + ArgumentCaptor<BatteryController.BatteryStateChangeCallback> batteryCallbackCaptor = + ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class); + verify(mBatteryController).addCallback(batteryCallbackCaptor.capture()); + batteryCallbackCaptor.getValue().onWirelessChargingChanged(false); + verify(mProximitySensor).resume(); + } + + @Test + public void testNoProximityWhenDocked() { + mDockManager.setDockEvent(DockManager.STATE_DOCKED); + verify(mProximitySensor).pause(); + } + + @Test + public void testProximityWhenUndocked() { + mDockManager.setDockEvent(DockManager.STATE_NONE); + verify(mProximitySensor).resume(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java index 1fe694e97bcf..5dc607fd342b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyLong; 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.testing.AndroidTestingRunner; import android.util.DisplayMetrics; @@ -30,12 +31,15 @@ import android.view.MotionEvent; import androidx.test.filters.SmallTest; import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener; -import com.android.systemui.utils.leaks.FakeBatteryController; +import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.statusbar.policy.BatteryController; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.util.List; @@ -43,19 +47,21 @@ import java.util.List; @RunWith(AndroidTestingRunner.class) public class FalsingDataProviderTest extends ClassifierTest { - private FakeBatteryController mFakeBatteryController; private FalsingDataProvider mDataProvider; + @Mock + private BatteryController mBatteryController; + private final DockManagerFake mDockManager = new DockManagerFake(); @Before public void setup() { super.setup(); - mFakeBatteryController = new FakeBatteryController(getLeakCheck()); + MockitoAnnotations.initMocks(this); DisplayMetrics displayMetrics = new DisplayMetrics(); displayMetrics.xdpi = 100; displayMetrics.ydpi = 100; displayMetrics.widthPixels = 1000; displayMetrics.heightPixels = 1000; - mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController); + mDataProvider = new FalsingDataProvider(displayMetrics, mBatteryController, mDockManager); } @After @@ -250,10 +256,17 @@ public class FalsingDataProviderTest extends ClassifierTest { @Test public void test_isWirelessCharging() { - assertThat(mDataProvider.isWirelessCharging()).isFalse(); + assertThat(mDataProvider.isDocked()).isFalse(); - mFakeBatteryController.setWirelessCharging(true); - assertThat(mDataProvider.isWirelessCharging()).isTrue(); + when(mBatteryController.isWirelessCharging()).thenReturn(true); + assertThat(mDataProvider.isDocked()).isTrue(); + } + + @Test + public void test_isDocked() { + assertThat(mDataProvider.isDocked()).isFalse(); + mDockManager.setIsDocked(true); + assertThat(mDataProvider.isDocked()).isTrue(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java index 0eeb955e6b42..d25b3e3279f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java @@ -16,8 +16,11 @@ package com.android.systemui.navigationbar; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; + import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; @@ -68,7 +71,8 @@ public class NavigationBarButtonTest extends SysuiTestCase { mDependency.injectMockDependency(OverviewProxyService.class); mDependency.injectMockDependency(KeyguardStateController.class); mDependency.injectMockDependency(NavigationBarController.class); - mDependency.injectMockDependency(EdgeBackGestureHandler.class); + mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER, + () -> mock(EdgeBackGestureHandler.class)); mNavBar = new NavigationBarView(context, null); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index a570675b442e..a76afd43cbbd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -24,6 +24,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS; import static org.junit.Assert.assertEquals; @@ -135,7 +136,8 @@ public class NavigationBarTest extends SysuiTestCase { mDependency.injectMockDependency(StatusBarStateController.class); mDependency.injectMockDependency(NavigationBarController.class); mOverviewProxyService = mDependency.injectMockDependency(OverviewProxyService.class); - mDependency.injectMockDependency(EdgeBackGestureHandler.class); + mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER, + () -> mock(EdgeBackGestureHandler.class)); TestableLooper.get(this).runWithLooper(() -> { mNavigationBar = createNavBar(mContext); mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java index e4d32f4db709..62871dc6101e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java @@ -16,6 +16,8 @@ package com.android.systemui.navigationbar; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; @@ -58,7 +60,8 @@ public class NavigationBarTransitionsTest extends SysuiTestCase { mDependency.injectMockDependency(StatusBarStateController.class); mDependency.injectMockDependency(KeyguardStateController.class); mDependency.injectMockDependency(NavigationBarController.class); - mDependency.injectMockDependency(EdgeBackGestureHandler.class); + mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER, + () -> mock(EdgeBackGestureHandler.class)); doReturn(mContext) .when(mDependency.injectMockDependency(NavigationModeController.class)) .getCurrentUserContext(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java index d56aa777706b..671b1bea849f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java @@ -16,6 +16,8 @@ package com.android.systemui.navigationbar.buttons; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -38,6 +40,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.navigationbar.buttons.ContextualButton; import com.android.systemui.navigationbar.buttons.ContextualButtonGroup; import com.android.systemui.navigationbar.buttons.KeyButtonDrawable; +import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import org.junit.Before; import org.junit.Ignore; @@ -65,6 +68,8 @@ public class NavigationBarContextTest extends SysuiTestCase { @Before public void setup() { mDependency.injectMockDependency(AssistManager.class); + mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER, + () -> mock(EdgeBackGestureHandler.class)); mGroup = new ContextualButtonGroup(GROUP_ID); mBtn0 = new ContextualButton(BUTTON_0_ID, mContext, ICON_RES_ID); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java index c8f223bdd72f..2ab2c941e9df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java @@ -16,10 +16,13 @@ package com.android.systemui.navigationbar.buttons; +import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -36,6 +39,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.navigationbar.buttons.NearestTouchFrame; +import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import org.junit.Before; import org.junit.Test; @@ -52,6 +56,8 @@ public class NearestTouchFrameTest extends SysuiTestCase { @Before public void setup() { + mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER, + () -> mock(EdgeBackGestureHandler.class)); Configuration c = new Configuration(mContext.getResources().getConfiguration()); c.smallestScreenWidthDp = 500; mNearestTouchFrame = new NearestTouchFrame(mContext, null, c); diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java index 05bef4c2aeb7..24c189a85327 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java @@ -1125,7 +1125,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A)); when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel); PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); - PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT); + PeopleSpaceTile tile = mManager + .getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT, true); assertThat(tile.getId()).isEqualTo(key.getShortcutId()); } @@ -1133,7 +1134,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { public void testGetPeopleTileFromPersistentStorageNoConversation() throws Exception { when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null); PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); - PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT); + PeopleSpaceTile tile = mManager + .getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT, false); assertThat(tile).isNull(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java index c2bd024f0375..84776c7eb18f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java @@ -148,8 +148,10 @@ public class QSDetailTest extends SysuiTestCase { eq(true) /* in */, any()); clearInvocations(mQsDetail.mClipper); + // Detail adapters should always animate on close. shouldAnimate() should only affect the + // open transition mQsDetail.handleShowingDetail(null, 0, 0, false); - verify(mQsDetail.mClipper).updateCircularClip(eq(false) /* animate */, anyInt(), anyInt(), + verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(), eq(false) /* in */, any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java index 42fd288d94ee..0a428654f14a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java @@ -77,10 +77,10 @@ public class TileLifecycleManagerTest extends SysuiTestCase { // Stub.asInterface will just return itself. when(mMockTileService.queryLocalInterface(anyString())).thenReturn(mMockTileService); + when(mMockTileService.asBinder()).thenReturn(mMockTileService); mContext.addMockService(mTileServiceComponentName, mMockTileService); - mTileServiceIntent = new Intent().setComponent(mTileServiceComponentName); mUser = new UserHandle(UserHandle.myUserId()); mThread = new HandlerThread("TestThread"); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java index 7c819f5c5ba4..85ea52b6af6a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java @@ -39,6 +39,7 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Icon; import android.os.UserHandle; +import android.service.notification.StatusBarNotification; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -131,4 +132,19 @@ public class StatusBarIconViewTest extends SysuiTestCase { icon, 0, 0, ""); assertFalse(mIconView.set(largeIcon)); } + + @Test + public void testNullNotifInfo() { + Bitmap bitmap = Bitmap.createBitmap(60, 60, Bitmap.Config.ARGB_8888); + Icon icon = Icon.createWithBitmap(bitmap); + StatusBarIcon largeIcon = new StatusBarIcon(UserHandle.ALL, "mockPackage", + icon, 0, 0, ""); + mIconView.setNotification(mock(StatusBarNotification.class)); + mIconView.getIcon(largeIcon); + // no crash? good + + mIconView.setNotification(null); + mIconView.getIcon(largeIcon); + // no crash? good + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index a6fc02d7dafc..f8fc22495d8d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -94,6 +94,7 @@ import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.QSDetailDisplayer; +import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.KeyguardAffordanceView; @@ -295,6 +296,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { private NotificationRemoteInputManager mNotificationRemoteInputManager; @Mock private RemoteInputController mRemoteInputController; + @Mock + private RecordingController mRecordingController; private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; @@ -433,6 +436,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mFragmentService, mContentResolver, mQuickAccessWalletController, + mRecordingController, new FakeExecutor(new FakeSystemClock()), mSecureSettings, mUnlockedScreenOffAnimationController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java index 9a5e948b762d..1fc1473adf19 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java @@ -26,6 +26,7 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; import android.content.Intent; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.View; import androidx.test.filters.SmallTest; @@ -37,6 +38,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; @@ -94,4 +96,11 @@ public class StatusBarRemoteInputCallbackTest extends SysuiTestCase { verify(mRemoteInputCallback, times(1)).onWorkChallengeChanged(); } + @Test + public void testShowGenericBouncer_onLockedRemoteInput() { + mRemoteInputCallback.onLockedRemoteInput( + mock(ExpandableNotificationRow.class), mock(View.class)); + + verify(mStatusBarKeyguardViewManager).showGenericBouncer(true); + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index cbc7c6dd0447..f126ed0c7555 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -152,6 +152,7 @@ import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; +import com.android.wm.shell.startingsurface.StartingSurface; import org.junit.Before; import org.junit.Test; @@ -273,6 +274,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private IWallpaperManager mWallpaperManager; @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Mock private StartingSurface mStartingSurface; private ShadeController mShadeController; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); private InitController mInitController = new InitController(); @@ -443,7 +445,8 @@ public class StatusBarTest extends SysuiTestCase { mLockscreenTransitionController, mFeatureFlags, mKeyguardUnlockAnimationController, - mUnlockedScreenOffAnimationController); + mUnlockedScreenOffAnimationController, + Optional.of(mStartingSurface)); when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class), any(NotificationPanelViewController.class), any(BiometricUnlockController.class), any(ViewGroup.class), any(KeyguardBypassController.class))) diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java index 1a24c113a0df..07d3fc20983f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -466,6 +466,44 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { } @Test + public void catchException_whenPackageNameIsOverlayName() { + mDeviceProvisionedController = mock(DeviceProvisionedController.class); + mThemeOverlayApplier = mock(ThemeOverlayApplier.class); + mWallpaperManager = mock(WallpaperManager.class); + + // Assume we have some wallpaper colors at boot. + when(mWallpaperManager.getWallpaperColors(anyInt())) + .thenReturn(new WallpaperColors(Color.valueOf(Color.GRAY), null, null)); + + Executor executor = MoreExecutors.directExecutor(); + + mThemeOverlayController = new ThemeOverlayController(null /* context */, + mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, + mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, + mUserTracker, mDumpManager, mFeatureFlags, mWakefulnessLifecycle) { + @Nullable + @Override + protected FabricatedOverlay getOverlay(int color, int type) { + FabricatedOverlay overlay = mock(FabricatedOverlay.class); + when(overlay.getIdentifier()) + .thenReturn(new OverlayIdentifier("com.thebest.livewallpaperapp.ever")); + + return overlay; + } + + }; + mThemeOverlayController.start(); + + verify(mWallpaperManager).addOnColorsChangedListener(mColorsListener.capture(), eq(null), + eq(UserHandle.USER_ALL)); + verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture()); + + // Colors were applied during controller initialization. + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + clearInvocations(mThemeOverlayApplier); + } + + @Test public void onWallpaperColorsChanged_defersUntilSetupIsCompleted_ifHasColors() { mDeviceProvisionedController = mock(DeviceProvisionedController.class); mThemeOverlayApplier = mock(ThemeOverlayApplier.class); 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 3cea17567173..dd4830e893af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -99,6 +99,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { Prefs.putInt(mContext, Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT, VolumePrefs.SHOW_RINGER_TOAST_COUNT + 1); + + Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false); } private State createShellState() { diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index a48f76ea1ca3..3047c9042848 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -268,6 +268,14 @@ message SystemMessage { // Package: android NOTE_NAS_UPGRADE = 64; + // Notify the user to unblock the microphone global toggle + // Package: android + NOTE_UNBLOCK_MIC_TOGGLE = 65; + + // Notify the user to unblock the camera global toggle + // Package: android + NOTE_UNBLOCK_CAM_TOGGLE = 66; + // ADD_NEW_IDS_ABOVE_THIS_LINE // Legacy IDs with arbitrary values appear below // Legacy IDs existed as stable non-conflicting constants prior to the O release 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 e1af2c48789f..d7bc04091181 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -258,7 +258,12 @@ public class TouchExplorer extends BaseEventStreamTransformation super.onMotionEvent(event, rawEvent, policyFlags); return; } - + try { + checkForMalformedEvent(event); + } catch (IllegalArgumentException e) { + Slog.e(LOG_TAG, "Ignoring malformed event: " + event.toString(), e); + return; + } if (DEBUG) { Slog.d(LOG_TAG, "Received event: " + event + ", policyFlags=0x" + Integer.toHexString(policyFlags)); @@ -1223,6 +1228,32 @@ public class TouchExplorer extends BaseEventStreamTransformation } /** + * Checks to see whether an event is consistent with itself. + * + * @throws IllegalArgumentException in the case of a malformed event. + */ + private static void checkForMalformedEvent(MotionEvent event) { + if (event.getPointerCount() < 0) { + throw new IllegalArgumentException("Invalid pointer count: " + event.getPointerCount()); + } + for (int i = 0; i < event.getPointerCount(); ++i) { + try { + int pointerId = event.getPointerId(i); + float x = event.getX(i); + float y = event.getY(i); + if (Float.isNaN(x) || Float.isNaN(y) || x < 0.0f || y < 0.0f) { + throw new IllegalArgumentException( + "Invalid coordinates: (" + x + ", " + y + ")"); + } + } catch (Exception e) { + throw new IllegalArgumentException( + "Encountered exception getting details of pointer " + i + " / " + + event.getPointerCount(), e); + } + } + } + + /** * Class for delayed sending of hover enter and move events. */ class SendHoverEnterAndMoveDelayed implements Runnable { diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 53ff8ff768de..ac43fbd4f976 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -122,6 +122,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.internal.util.FunctionalUtils; @@ -260,7 +261,7 @@ public final class SensorPrivacyService extends SystemService { * <Package, User> -> list of suppressor tokens */ @GuardedBy("mLock") - private ArrayMap<Pair<String, UserHandle>, ArrayList<IBinder>> mSuppressReminders = + private ArrayMap<Pair<Integer, UserHandle>, ArrayList<IBinder>> mSuppressReminders = new ArrayMap<>(); private final ArrayMap<SensorUseReminderDialogInfo, ArraySet<Integer>> @@ -423,7 +424,7 @@ public final class SensorPrivacyService extends SystemService { } synchronized (mLock) { - if (mSuppressReminders.containsKey(new Pair<>(packageName, user))) { + if (mSuppressReminders.containsKey(new Pair<>(sensor, user))) { Log.d(TAG, "Suppressed sensor privacy reminder for " + packageName + "/" + user); return; @@ -450,14 +451,22 @@ public final class SensorPrivacyService extends SystemService { for (int taskNum = 0; taskNum < numTasks; taskNum++) { RunningTaskInfo task = tasks.get(taskNum); - if (task.isVisible && task.topActivity.getPackageName().equals(packageName)) { - if (task.isFocused) { - // There is the one focused activity - enqueueSensorUseReminderDialogAsync(task.taskId, user, packageName, sensor); - return; - } + if (task.isVisible) { + if (task.topActivity.getPackageName().equals(packageName)) { + if (task.isFocused) { + // There is the one focused activity + enqueueSensorUseReminderDialogAsync(task.taskId, user, packageName, + sensor); + return; + } - tasksOfPackageUsingSensor.add(task); + tasksOfPackageUsingSensor.add(task); + } else if (task.topActivity.flattenToString().equals(mContext.getResources() + .getString(R.string.config_sensorUseStartedActivity)) + && task.isFocused) { + enqueueSensorUseReminderDialogAsync(task.taskId, user, packageName, + sensor); + } } } @@ -550,8 +559,15 @@ public final class SensorPrivacyService extends SystemService { SensorUseReminderDialogInfo info = new SensorUseReminderDialogInfo(taskId, user, packageName); if (!mQueuedSensorUseReminderDialogs.containsKey(info)) { - ArraySet<Integer> sensors = new ArraySet<Integer>(); - sensors.add(sensor); + ArraySet<Integer> sensors = new ArraySet<>(); + if (sensor == MICROPHONE && mSuppressReminders.containsKey(new Pair<>(CAMERA, user)) + || sensor == CAMERA && mSuppressReminders + .containsKey(new Pair<>(MICROPHONE, user))) { + sensors.add(MICROPHONE); + sensors.add(CAMERA); + } else { + sensors.add(sensor); + } mQueuedSensorUseReminderDialogs.put(info, sensors); mHandler.sendMessageDelayed( PooledLambda.obtainMessage(this::showSensorUserReminderDialog, info), @@ -608,6 +624,7 @@ public final class SensorPrivacyService extends SystemService { @NonNull String packageName, int sensor) { int iconRes; int messageRes; + int notificationId; CharSequence packageLabel; try { @@ -622,9 +639,11 @@ public final class SensorPrivacyService extends SystemService { if (sensor == MICROPHONE) { iconRes = R.drawable.ic_mic_blocked; messageRes = R.string.sensor_privacy_start_use_mic_notification_content_title; + notificationId = SystemMessage.NOTE_UNBLOCK_MIC_TOGGLE; } else { iconRes = R.drawable.ic_camera_blocked; messageRes = R.string.sensor_privacy_start_use_camera_notification_content_title; + notificationId = SystemMessage.NOTE_UNBLOCK_CAM_TOGGLE; } NotificationManager notificationManager = @@ -641,7 +660,7 @@ public final class SensorPrivacyService extends SystemService { notificationManager.createNotificationChannel(channel); Icon icon = Icon.createWithResource(getUiContext().getResources(), iconRes); - notificationManager.notify(sensor, + notificationManager.notify(notificationId, new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID) .setContentTitle(getUiContext().getString(messageRes)) .setContentText(Html.fromHtml(getUiContext().getString( @@ -1161,13 +1180,12 @@ public final class SensorPrivacyService extends SystemService { } @Override - public void suppressIndividualSensorPrivacyReminders(int userId, String packageName, + public void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress) { enforceManageSensorPrivacyPermission(); - Objects.requireNonNull(packageName); Objects.requireNonNull(token); - Pair<String, UserHandle> key = new Pair<>(packageName, UserHandle.of(userId)); + Pair<Integer, UserHandle> key = new Pair<>(sensor, UserHandle.of(userId)); synchronized (mLock) { if (suppress) { @@ -1197,7 +1215,7 @@ public final class SensorPrivacyService extends SystemService { * @param key Key the token is in * @param token The token to remove */ - private void removeSuppressPackageReminderToken(@NonNull Pair<String, UserHandle> key, + private void removeSuppressPackageReminderToken(@NonNull Pair<Integer, UserHandle> key, @NonNull IBinder token) { synchronized (mLock) { ArrayList<IBinder> suppressPackageReminderTokens = @@ -1229,7 +1247,7 @@ public final class SensorPrivacyService extends SystemService { @Override public void binderDied(@NonNull IBinder token) { synchronized (mLock) { - for (Pair<String, UserHandle> key : mSuppressReminders.keySet()) { + for (Pair<Integer, UserHandle> key : mSuppressReminders.keySet()) { removeSuppressPackageReminderToken(key, token); } } @@ -1557,7 +1575,7 @@ public final class SensorPrivacyService extends SystemService { listeners.finishBroadcast(); } - public void removeSuppressPackageReminderToken(Pair<String, UserHandle> key, + public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key, IBinder token) { sendMessage(PooledLambda.obtainMessage( SensorPrivacyServiceImpl::removeSuppressPackageReminderToken, diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index f9fd10817627..207a5e3db06e 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -24,6 +24,7 @@ import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; +import static android.telephony.SubscriptionManager.isValidSubscriptionId; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; @@ -435,6 +436,15 @@ public class VcnManagementService extends IVcnManagementService.Stub { } } + private boolean isActiveSubGroup( + @NonNull ParcelUuid subGrp, @NonNull TelephonySubscriptionSnapshot snapshot) { + if (subGrp == null || snapshot == null) { + return false; + } + + return Objects.equals(subGrp, snapshot.getActiveDataSubscriptionGroup()); + } + private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback { /** * Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker} @@ -452,28 +462,49 @@ public class VcnManagementService extends IVcnManagementService.Stub { // Start any VCN instances as necessary for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) { + final ParcelUuid subGrp = entry.getKey(); + + // TODO(b/193687515): Support multiple VCNs active at the same time if (snapshot.packageHasPermissionsForSubscriptionGroup( - entry.getKey(), entry.getValue().getProvisioningPackageName())) { - if (!mVcns.containsKey(entry.getKey())) { - startVcnLocked(entry.getKey(), entry.getValue()); + subGrp, entry.getValue().getProvisioningPackageName()) + && isActiveSubGroup(subGrp, snapshot)) { + if (!mVcns.containsKey(subGrp)) { + startVcnLocked(subGrp, entry.getValue()); } // Cancel any scheduled teardowns for active subscriptions - mHandler.removeCallbacksAndMessages(mVcns.get(entry.getKey())); + mHandler.removeCallbacksAndMessages(mVcns.get(subGrp)); } } // Schedule teardown of any VCN instances that have lost carrier privileges (after a // delay) for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) { - final VcnConfig config = mConfigs.get(entry.getKey()); + final ParcelUuid subGrp = entry.getKey(); + final VcnConfig config = mConfigs.get(subGrp); + + final boolean isActiveSubGrp = isActiveSubGroup(subGrp, snapshot); + final boolean isValidActiveDataSubIdNotInVcnSubGrp = + isValidSubscriptionId(snapshot.getActiveDataSubscriptionId()) + && !isActiveSubGroup(subGrp, snapshot); + // TODO(b/193687515): Support multiple VCNs active at the same time if (config == null || !snapshot.packageHasPermissionsForSubscriptionGroup( - entry.getKey(), config.getProvisioningPackageName())) { - final ParcelUuid uuidToTeardown = entry.getKey(); + subGrp, config.getProvisioningPackageName()) + || !isActiveSubGrp) { + final ParcelUuid uuidToTeardown = subGrp; final Vcn instanceToTeardown = entry.getValue(); + // TODO(b/193687515): Support multiple VCNs active at the same time + // If directly switching to a subscription not in the current group, + // teardown immediately to prevent other subscription's network from being + // outscored by the VCN. Otherwise, teardown after a delay to ensure that + // SIM profile switches do not trigger the VCN to cycle. + final long teardownDelayMs = + isValidActiveDataSubIdNotInVcnSubGrp + ? 0 + : CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS; mHandler.postDelayed(() -> { synchronized (mLock) { // Guard against case where this is run after a old instance was @@ -489,7 +520,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { uuidToTeardown, VCN_STATUS_CODE_INACTIVE); } } - }, instanceToTeardown, CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); + }, instanceToTeardown, teardownDelayMs); } else { // If this VCN's status has not changed, update it with the new snapshot entry.getValue().updateSubscriptionSnapshot(mLastSnapshot); @@ -553,8 +584,13 @@ public class VcnManagementService extends IVcnManagementService.Stub { private void startVcnLocked(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) { logDbg("Starting VCN config for subGrp: " + subscriptionGroup); - // TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active - // VCN. + // TODO(b/193687515): Support multiple VCNs active at the same time + if (!mVcns.isEmpty()) { + // Only one VCN supported at a time; teardown all others before starting new one + for (ParcelUuid uuidToTeardown : mVcns.keySet()) { + stopVcnLocked(uuidToTeardown); + } + } final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup); @@ -582,7 +618,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { final Vcn vcn = mVcns.get(subscriptionGroup); vcn.updateConfig(config); } else { - startVcnLocked(subscriptionGroup, config); + // TODO(b/193687515): Support multiple VCNs active at the same time + if (isActiveSubGroup(subscriptionGroup, mLastSnapshot)) { + startVcnLocked(subscriptionGroup, config); + } } } @@ -1007,6 +1046,11 @@ public class VcnManagementService extends IVcnManagementService.Stub { } } + @VisibleForTesting(visibility = Visibility.PRIVATE) + void setLastSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) { + mLastSnapshot = Objects.requireNonNull(snapshot); + } + private void logVdbg(String msg) { if (VDBG) { Slog.v(TAG, msg); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index b5ead200cea5..795d3d6c3461 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3334,7 +3334,13 @@ public final class ActiveServices { } } - private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) { + /** + * Bump the given service record into executing state. + * @param oomAdjReason The caller requests it to perform the oomAdjUpdate if it's not null. + * @return {@code true} if it performed oomAdjUpdate. + */ + private boolean bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why, + @Nullable String oomAdjReason) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING " + why + " of " + r + " in app " + r.app); else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING " @@ -3383,9 +3389,19 @@ public final class ActiveServices { } } } + boolean oomAdjusted = false; + if (oomAdjReason != null && r.app != null + && r.app.mState.getCurProcState() > ActivityManager.PROCESS_STATE_SERVICE) { + // Force an immediate oomAdjUpdate, so the client app could be in the correct process + // state before doing any service related transactions + mAm.enqueueOomAdjTargetLocked(r.app); + mAm.updateOomAdjPendingTargetsLocked(oomAdjReason); + oomAdjusted = true; + } r.executeFg |= fg; r.executeNesting++; r.executingStart = now; + return oomAdjusted; } private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, @@ -3398,8 +3414,8 @@ public final class ActiveServices { + " rebind=" + rebind); if ((!i.requested || rebind) && i.apps.size() > 0) { try { - bumpServiceExecutingLocked(r, execInFg, "bind"); - r.app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); + bumpServiceExecutingLocked(r, execInFg, "bind", + OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE); r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind, r.app.mState.getReportedProcState()); if (!rebind) { @@ -3867,14 +3883,13 @@ public final class ActiveServices { final ProcessServiceRecord psr = app.mServices; final boolean newService = psr.startService(r); - bumpServiceExecutingLocked(r, execInFg, "create"); + bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */); mAm.updateLruProcessLocked(app, false, null); updateServiceForegroundLocked(psr, /* oomAdj= */ false); - if (enqueueOomAdj) { - mAm.enqueueOomAdjTargetLocked(app); - } else { - mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); - } + // Force an immediate oomAdjUpdate, so the client app could be in the correct process state + // before doing any service related transactions + mAm.enqueueOomAdjTargetLocked(app); + mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); boolean created = false; try { @@ -3895,7 +3910,6 @@ public final class ActiveServices { mAm.mBatteryStatsService.noteServiceStartLaunch(uid, packageName, serviceName); mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); - app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.mState.getReportedProcState()); @@ -3995,11 +4009,7 @@ public final class ActiveServices { mAm.grantImplicitAccess(r.userId, si.intent, si.callingId, UserHandle.getAppId(r.appInfo.uid) ); - bumpServiceExecutingLocked(r, execInFg, "start"); - if (!oomAdjusted) { - oomAdjusted = true; - mAm.updateOomAdjLocked(r.app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); - } + bumpServiceExecutingLocked(r, execInFg, "start", null /* oomAdjReason */); if (r.fgRequired && !r.fgWaiting) { if (!r.isForeground) { if (DEBUG_BACKGROUND_CHECK) { @@ -4023,6 +4033,10 @@ public final class ActiveServices { args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent)); } + if (!oomAdjusted) { + mAm.enqueueOomAdjTargetLocked(r.app); + mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE); + } ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args); slice.setInlineCountLimit(4); Exception caughtException = null; @@ -4117,7 +4131,7 @@ public final class ActiveServices { } } - boolean needOomAdj = false; + boolean oomAdjusted = false; // Tell the service that it has been unbound. if (r.app != null && r.app.getThread() != null) { for (int i = r.bindings.size() - 1; i >= 0; i--) { @@ -4126,8 +4140,8 @@ public final class ActiveServices { + ": hasBound=" + ibr.hasBound); if (ibr.hasBound) { try { - bumpServiceExecutingLocked(r, false, "bring down unbind"); - needOomAdj = true; + oomAdjusted |= bumpServiceExecutingLocked(r, false, "bring down unbind", + OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); ibr.hasBound = false; ibr.requested = false; r.app.getThread().scheduleUnbindService(r, @@ -4135,7 +4149,6 @@ public final class ActiveServices { } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + r.shortInstanceName, e); - needOomAdj = false; serviceProcessGoneLocked(r, enqueueOomAdj); break; } @@ -4247,10 +4260,10 @@ public final class ActiveServices { mAm.updateLruProcessLocked(r.app, false, null); updateServiceForegroundLocked(r.app.mServices, false); try { - bumpServiceExecutingLocked(r, false, "destroy"); + oomAdjusted |= bumpServiceExecutingLocked(r, false, "destroy", + oomAdjusted ? null : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); mDestroyingServices.add(r); r.destroying = true; - needOomAdj = true; r.app.getThread().scheduleStopService(r); } catch (Exception e) { Slog.w(TAG, "Exception when destroying service " @@ -4266,11 +4279,10 @@ public final class ActiveServices { TAG_SERVICE, "Removed service that is not running: " + r); } - if (needOomAdj) { - if (enqueueOomAdj) { - mAm.enqueueOomAdjTargetLocked(r.app); - } else { - mAm.updateOomAdjLocked(r.app, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); + if (!oomAdjusted) { + mAm.enqueueOomAdjTargetLocked(r.app); + if (!enqueueOomAdj) { + mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); } } if (r.bindings.size() > 0) { @@ -4387,7 +4399,8 @@ public final class ActiveServices { if (s.app != null && s.app.getThread() != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { - bumpServiceExecutingLocked(s, false, "unbind"); + bumpServiceExecutingLocked(s, false, "unbind", + OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.mState.getSetProcState() <= PROCESS_STATE_HEAVY_WEIGHT) { // If this service's process is not already in the cached list, @@ -4395,11 +4408,6 @@ public final class ActiveServices { // it to go down there and we want it to start out near the top. mAm.updateLruProcessLocked(s.app, false, null); } - if (enqueueOomAdj) { - mAm.enqueueOomAdjTargetLocked(s.app); - } else { - mAm.updateOomAdjLocked(s.app, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); - } b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; // we will deal with that later if it asks for one. diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java index 9d1c83894d46..9079ba84c8f3 100644 --- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java +++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java @@ -50,7 +50,7 @@ class ActivityManagerDebugConfig { static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false; static final boolean DEBUG_BROADCAST_DEFERRAL = DEBUG_BROADCAST || false; static final boolean DEBUG_COMPACTION = DEBUG_ALL || false; - static final boolean DEBUG_FREEZER = DEBUG_ALL || true; + static final boolean DEBUG_FREEZER = DEBUG_ALL || false; static final boolean DEBUG_LRU = DEBUG_ALL || false; static final boolean DEBUG_MU = DEBUG_ALL || false; static final boolean DEBUG_NETWORK = DEBUG_ALL || false; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4ec5559a061d..99ae52c00995 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5003,7 +5003,7 @@ public class ActivityManagerService extends IActivityManager.Stub (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0, res.key.type); } else { - throw new IllegalArgumentException(); + return new PendingIntentInfo(null, -1, false, ActivityManager.INTENT_SENDER_UNKNOWN); } } @@ -11048,9 +11048,9 @@ public class ActivityManagerService extends IActivityManager.Stub } final long gpuUsage = Debug.getGpuTotalUsageKb(); if (gpuUsage >= 0) { - final long gpuDmaBufUsage = Debug.getGpuDmaBufUsageKb(); - if (gpuDmaBufUsage >= 0) { - final long gpuPrivateUsage = gpuUsage - gpuDmaBufUsage; + final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb(); + if (gpuPrivateUsage >= 0) { + final long gpuDmaBufUsage = gpuUsage - gpuPrivateUsage; pw.print(" GPU: "); pw.print(stringifyKBSize(gpuUsage)); pw.print(" ("); @@ -12425,6 +12425,15 @@ public class ActivityManagerService extends IActivityManager.Stub return sticky; } + // SafetyNet logging for b/177931370. If any process other than system_server tries to + // listen to this broadcast action, then log it. + if (callingPid != Process.myPid()) { + if (filter.hasAction("com.android.server.net.action.SNOOZE_WARNING") + || filter.hasAction("com.android.server.net.action.SNOOZE_RAPID")) { + EventLog.writeEvent(0x534e4554, "177931370", callingUid, ""); + } + } + synchronized (this) { IApplicationThread thread; if (callerApp != null && ((thread = callerApp.getThread()) == null diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index 74094e500de7..36c0de919279 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -1561,9 +1561,9 @@ public class AppProfiler { final long gpuUsage = Debug.getGpuTotalUsageKb(); if (gpuUsage >= 0) { - final long gpuDmaBufUsage = Debug.getGpuDmaBufUsageKb(); - if (gpuDmaBufUsage >= 0) { - final long gpuPrivateUsage = gpuUsage - gpuDmaBufUsage; + final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb(); + if (gpuPrivateUsage >= 0) { + final long gpuDmaBufUsage = gpuUsage - gpuPrivateUsage; memInfoBuilder.append(" GPU: "); memInfoBuilder.append(stringifyKBSize(gpuUsage)); memInfoBuilder.append(" ("); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 67dfb8051f93..0c633cacda92 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -579,8 +579,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } } - // Collect the latest low power stats without holding the mStats lock. - mStats.fillLowPowerStats(); + if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RPM) != 0) { + // Collect the latest low power stats without holding the mStats lock. + mStats.fillLowPowerStats(); + } final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver); final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver); diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 8db7eeaaa89a..9dbb70757cf7 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -992,9 +992,7 @@ public final class CachedAppOptimizer { } if (!opt.isFrozen()) { - if (DEBUG_FREEZER) { - Slog.d(TAG_AM, "sync unfroze " + pid + " " + app.processName); - } + Slog.d(TAG_AM, "sync unfroze " + pid + " " + app.processName); mFreezeHandler.sendMessage( mFreezeHandler.obtainMessage(REPORT_UNFREEZE_MSG, @@ -1386,9 +1384,7 @@ public final class CachedAppOptimizer { return; } - if (DEBUG_FREEZER) { - Slog.d(TAG_AM, "froze " + pid + " " + name); - } + Slog.d(TAG_AM, "froze " + pid + " " + name); EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name); diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 33bc212fb9c0..24edc01c24df 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -202,6 +202,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Scanner; import java.util.Set; @@ -775,7 +776,11 @@ public class AppOpsService extends IAppOpsService.Stub { /** Clean up event */ public void finish() { - mClientId.unlinkToDeath(this, 0); + try { + mClientId.unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + // Either not linked, or already unlinked. Either way, nothing to do. + } } @Override @@ -5099,13 +5104,15 @@ public class AppOpsService extends IAppOpsService.Stub { String lastPkg = null; for (int i=0; i<allOps.size(); i++) { AppOpsManager.PackageOps pkg = allOps.get(i); - if (!pkg.getPackageName().equals(lastPkg)) { + if (!Objects.equals(pkg.getPackageName(), lastPkg)) { if (lastPkg != null) { out.endTag(null, "pkg"); } lastPkg = pkg.getPackageName(); - out.startTag(null, "pkg"); - out.attribute(null, "n", lastPkg); + if (lastPkg != null) { + out.startTag(null, "pkg"); + out.attribute(null, "n", lastPkg); + } } out.startTag(null, "uid"); out.attributeInt(null, "n", pkg.getUid()); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 91283b9c6ccc..f7d091498456 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1930,6 +1930,32 @@ public class AudioService extends IAudioService.Stub } } + /** @see AudioManager#getSurroundFormats() */ + @Override + public Map<Integer, Boolean> getSurroundFormats() { + Map<Integer, Boolean> surroundFormats = new HashMap<>(); + int status = AudioSystem.getSurroundFormats(surroundFormats); + if (status != AudioManager.SUCCESS) { + // fail and bail! + Log.e(TAG, "getSurroundFormats failed:" + status); + return new HashMap<>(); // Always return a map. + } + return surroundFormats; + } + + /** @see AudioManager#getReportedSurroundFormats() */ + @Override + public List<Integer> getReportedSurroundFormats() { + ArrayList<Integer> reportedSurroundFormats = new ArrayList<>(); + int status = AudioSystem.getReportedSurroundFormats(reportedSurroundFormats); + if (status != AudioManager.SUCCESS) { + // fail and bail! + Log.e(TAG, "getReportedSurroundFormats failed:" + status); + return new ArrayList<>(); // Always return a list. + } + return reportedSurroundFormats; + } + /** @see AudioManager#isSurroundFormatEnabled(int) */ @Override public boolean isSurroundFormatEnabled(int audioFormat) { diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index ca357b4c2cec..c2eb06262edd 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -22,6 +22,7 @@ import android.hardware.biometrics.BiometricConstants; import android.media.AudioAttributes; import android.os.IBinder; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.VibrationEffect; @@ -49,6 +50,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); private final PowerManager mPowerManager; + // If haptics should occur when auth result (success/reject) is known + protected final boolean mShouldVibrate; private boolean mShouldSendErrorToClient = true; private boolean mAlreadyCancelled; @@ -59,11 +62,12 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement public AcquisitionClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, - @NonNull String owner, int cookie, int sensorId, int statsModality, - int statsAction, int statsClient) { + @NonNull String owner, int cookie, int sensorId, boolean shouldVibrate, + int statsModality, int statsAction, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId, statsModality, statsAction, statsClient); mPowerManager = context.getSystemService(PowerManager.class); + mShouldVibrate = shouldVibrate; } @Override @@ -188,31 +192,25 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); } - protected boolean successHapticsEnabled() { - return true; - } - - protected boolean errorHapticsEnabled() { - return true; - } - protected final void vibrateSuccess() { - if (!successHapticsEnabled()) { - return; - } Vibrator vibrator = getContext().getSystemService(Vibrator.class); if (vibrator != null) { - vibrator.vibrate(SUCCESS_VIBRATION_EFFECT, VIBRATION_SONIFICATION_ATTRIBUTES); + vibrator.vibrate(Process.myUid(), + getContext().getOpPackageName(), + SUCCESS_VIBRATION_EFFECT, + getClass().getSimpleName() + "::success", + VIBRATION_SONIFICATION_ATTRIBUTES); } } protected final void vibrateError() { - if (!errorHapticsEnabled()) { - return; - } Vibrator vibrator = getContext().getSystemService(Vibrator.class); if (vibrator != null) { - vibrator.vibrate(ERROR_VIBRATION_EFFECT, VIBRATION_SONIFICATION_ATTRIBUTES); + vibrator.vibrate(Process.myUid(), + getContext().getOpPackageName(), + ERROR_VIBRATION_EFFECT, + getClass().getSimpleName() + "::error", + VIBRATION_SONIFICATION_ATTRIBUTES); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 80e60e67f05a..3e6602e3175a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -68,9 +68,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener, - @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication) { + @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication, + boolean shouldVibrate) { super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId, - statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); + shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, + statsClient); mIsStrongBiometric = isStrongBiometric; mOperationId = operationId; mRequireConfirmation = requireConfirmation; @@ -204,7 +206,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> mAlreadyDone = true; - if (listener != null) { + if (listener != null && mShouldVibrate) { vibrateSuccess(); } @@ -250,7 +252,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> Slog.w(TAG, "Client not listening"); } } else { - if (listener != null) { + if (listener != null && mShouldVibrate) { vibrateError(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java index e1320d8e1a4f..a15e14b79e30 100644 --- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java @@ -38,7 +38,6 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> { protected final byte[] mHardwareAuthToken; protected final int mTimeoutSec; protected final BiometricUtils mBiometricUtils; - private final boolean mShouldVibrate; private long mEnrollmentStartTimeMs; @@ -50,15 +49,13 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> { public EnrollClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils, - int timeoutSec, int statsModality, int sensorId, - boolean shouldVibrate) { + int timeoutSec, int statsModality, int sensorId, boolean shouldVibrate) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, - statsModality, BiometricsProtoEnums.ACTION_ENROLL, + shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricUtils = utils; mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length); mTimeoutSec = timeoutSec; - mShouldVibrate = shouldVibrate; } public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) { diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index db927b227d9a..0525d2da6988 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -19,7 +19,6 @@ package com.android.server.biometrics.sensors.face.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.NotificationManager; -import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.hardware.biometrics.BiometricAuthenticator; @@ -33,7 +32,6 @@ import android.hardware.face.FaceAuthenticationFrame; import android.hardware.face.FaceManager; import android.os.IBinder; import android.os.RemoteException; -import android.provider.Settings; import android.util.Slog; import com.android.internal.R; @@ -59,9 +57,6 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements @Nullable private final NotificationManager mNotificationManager; @Nullable private ICancellationSignal mCancellationSignal; - @NonNull private final ContentResolver mContentResolver; - private final boolean mCustomHaptics; - private final int[] mBiometricPromptIgnoreList; private final int[] mBiometricPromptIgnoreListVendor; private final int[] mKeyguardIgnoreList; @@ -78,7 +73,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */, - lockoutCache, allowBackgroundAuthentication); + lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */); mUsageStats = usageStats; mLockoutCache = lockoutCache; mNotificationManager = context.getSystemService(NotificationManager.class); @@ -92,10 +87,6 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements R.array.config_face_acquire_keyguard_ignorelist); mKeyguardIgnoreListVendor = resources.getIntArray( R.array.config_face_acquire_vendor_keyguard_ignorelist); - - mContentResolver = context.getContentResolver(); - mCustomHaptics = Settings.Global.getInt(mContentResolver, - "face_custom_success_error", 0) == 1; } @NonNull @@ -261,18 +252,4 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements Slog.e(TAG, "Remote exception", e); } } - - @Override - protected boolean successHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "face_success_enabled", 1) == 0 - : super.successHapticsEnabled(); - } - - @Override - protected boolean errorHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "face_error_enabled", 1) == 0 - : super.errorHapticsEnabled(); - } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java index cb966e7b47a9..1e73ac528f08 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java @@ -46,8 +46,8 @@ public class FaceDetectClient extends AcquisitionClient<ISession> implements Det @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, - BiometricsProtoEnums.MODALITY_FACE, BiometricsProtoEnums.ACTION_AUTHENTICATE, - statsClient); + true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FACE, + BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); mIsStrongBiometric = isStrongBiometric; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 6c0adafcf2ee..5731d73dfd49 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -17,7 +17,6 @@ package com.android.server.biometrics.sensors.face.hidl; import android.annotation.NonNull; -import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.hardware.biometrics.BiometricAuthenticator; @@ -28,7 +27,6 @@ import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.face.FaceManager; import android.os.IBinder; import android.os.RemoteException; -import android.provider.Settings; import android.util.Slog; import com.android.internal.R; @@ -49,8 +47,6 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { private static final String TAG = "FaceAuthenticationClient"; - @NonNull private final ContentResolver mContentResolver; - private final boolean mCustomHaptics; private final UsageStats mUsageStats; private final int[] mBiometricPromptIgnoreList; @@ -69,7 +65,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */, - lockoutTracker, allowBackgroundAuthentication); + lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */); mUsageStats = usageStats; final Resources resources = getContext().getResources(); @@ -81,10 +77,6 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { R.array.config_face_acquire_keyguard_ignorelist); mKeyguardIgnoreListVendor = resources.getIntArray( R.array.config_face_acquire_vendor_keyguard_ignorelist); - - mContentResolver = context.getContentResolver(); - mCustomHaptics = Settings.Global.getInt(mContentResolver, - "face_custom_success_error", 0) == 1; } @NonNull @@ -200,18 +192,4 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { final boolean shouldSend = shouldSend(acquireInfo, vendorCode); onAcquiredInternal(acquireInfo, vendorCode, shouldSend); } - - @Override - protected boolean successHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "face_success_enabled", 1) == 0 - : super.successHapticsEnabled(); - } - - @Override - protected boolean errorHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "face_error_enabled", 1) == 0 - : super.errorHapticsEnabled(); - } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 012e47e425f6..183fabdc2a7b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -215,9 +215,9 @@ public class FingerprintService extends SystemService { } @Override // Binder call - public void enroll(final IBinder token, final byte[] hardwareAuthToken, final int userId, - final IFingerprintServiceReceiver receiver, final String opPackageName, - @FingerprintManager.EnrollReason int enrollReason) { + public void enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, + final int userId, final IFingerprintServiceReceiver receiver, + final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); final Pair<Integer, ServiceProvider> provider = getSingleProvider(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 3a214f44c0a8..706ac1013746 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -85,9 +85,12 @@ public interface ServiceProvider { void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token, @NonNull String opPackageName, long challenge); - void scheduleEnroll(int sensorId, @NonNull IBinder token, byte[] hardwareAuthToken, int userId, - @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, - @FingerprintManager.EnrollReason int enrollReason, + /** + * Schedules fingerprint enrollment. + */ + void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, + int userId, @NonNull IFingerprintServiceReceiver receiver, + @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason, @NonNull FingerprintStateCallback fingerprintStateCallback); void cancelEnrollment(int sensorId, @NonNull IBinder token); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 6a05ed470123..8681ad75b7c6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -19,7 +19,6 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; -import android.content.ContentResolver; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; @@ -27,10 +26,10 @@ import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcqu import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; import android.os.RemoteException; -import android.provider.Settings; import android.util.Slog; import com.android.server.biometrics.Utils; @@ -57,9 +56,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ICancellationSignal mCancellationSignal; - @NonNull private final ContentResolver mContentResolver; - private final boolean mCustomHaptics; - FingerprintAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, @@ -67,17 +63,14 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp int sensorId, boolean isStrongBiometric, int statsClient, @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache, @Nullable IUdfpsOverlayController udfpsOverlayController, - boolean allowBackgroundAuthentication) { + boolean allowBackgroundAuthentication, + @NonNull FingerprintSensorPropertiesInternal sensorProps) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, - lockoutCache, allowBackgroundAuthentication); + lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */); mLockoutCache = lockoutCache; mUdfpsOverlayController = udfpsOverlayController; - - mContentResolver = context.getContentResolver(); - mCustomHaptics = Settings.Global.getInt(mContentResolver, - "fp_custom_success_error", 0) == 1; } @NonNull @@ -213,18 +206,4 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); mCallback.onClientFinished(this, false /* success */); } - - @Override - protected boolean successHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "fp_success_enabled", 1) == 0 - : super.successHapticsEnabled(); - } - - @Override - protected boolean errorHapticsEnabled() { - return mCustomHaptics - ? Settings.Global.getInt(mContentResolver, "fp_error_enabled", 1) == 0 - : super.errorHapticsEnabled(); - } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java index 5e1a245554a6..c5dc44988612 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java @@ -52,8 +52,8 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> implements Det @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, - BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE, - statsClient); + true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT, + BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); mIsStrongBiometric = isStrongBiometric; mUdfpsOverlayController = udfpsOverlayController; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index 646b988545be..a211bb5e14e3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -65,7 +65,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps { @Nullable IUdfpsOverlayController udfpsOvelayController, @Nullable ISidefpsController sidefpsController, int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) { - // UDFPS enroll vibrations are handled in SystemUI + // UDFPS haptics occur when an image is acquired (instead of when the result is known) super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, 0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, !sensorProps.isAnyUdfpsType() /* shouldVibrate */); @@ -104,6 +104,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps { // See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD && mSensorProps.isAnyUdfpsType()) { + vibrateSuccess(); UdfpsHelper.onAcquiredGood(getSensorId(), mUdfpsOverlayController); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 096c3111d35c..102b07493134 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -329,9 +329,10 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void scheduleEnroll(int sensorId, @NonNull IBinder token, byte[] hardwareAuthToken, - int userId, @NonNull IFingerprintServiceReceiver receiver, - @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason, + public void scheduleEnroll(int sensorId, @NonNull IBinder token, + @NonNull byte[] hardwareAuthToken, int userId, + @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, + @FingerprintManager.EnrollReason int enrollReason, @NonNull FingerprintStateCallback fingerprintStateCallback) { mHandler.post(() -> { final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() @@ -395,7 +396,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), - mUdfpsOverlayController, allowBackgroundAuthentication); + mUdfpsOverlayController, allowBackgroundAuthentication, + mSensors.get(sensorId).getSensorProperties()); scheduleForSensor(sensorId, client, fingerprintStateCallback); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index bf7775730a2c..40e3bc3a4698 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -65,7 +65,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, - lockoutTracker, allowBackgroundAuthentication); + lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */); mLockoutFrameworkImpl = lockoutTracker; mUdfpsOverlayController = udfpsOverlayController; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java index 8d777e1c2787..af1e49d250c6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java @@ -56,8 +56,8 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint> int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, - BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE, - statsClient); + true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT, + BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); mUdfpsOverlayController = udfpsOverlayController; mIsStrongBiometric = isStrongBiometric; } diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java index e0b4d47de0ee..645131c1eee8 100644 --- a/services/core/java/com/android/server/display/HighBrightnessModeController.java +++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java @@ -72,7 +72,7 @@ class HighBrightnessModeController { private final Injector mInjector; private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged; - private SurfaceControlHdrLayerInfoListener mHdrListener; + private HdrListener mHdrListener; private HighBrightnessModeData mHbmData; private IBinder mRegisteredDisplayToken; @@ -251,6 +251,11 @@ class HighBrightnessModeController { mHandler.runWithScissors(() -> dumpLocal(pw), 1000); } + @VisibleForTesting + HdrListener getHdrListener() { + return mHdrListener; + } + private void dumpLocal(PrintWriter pw) { pw.println("HighBrightnessModeController:"); pw.println(" mBrightness=" + mBrightness); @@ -487,7 +492,8 @@ class HighBrightnessModeController { } } - private class HdrListener extends SurfaceControlHdrLayerInfoListener { + @VisibleForTesting + class HdrListener extends SurfaceControlHdrLayerInfoListener { @Override public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers, int maxW, int maxH, int flags) { diff --git a/services/core/java/com/android/server/location/injector/AlarmHelper.java b/services/core/java/com/android/server/location/injector/AlarmHelper.java index f3fb9c84273b..91a1042d9625 100644 --- a/services/core/java/com/android/server/location/injector/AlarmHelper.java +++ b/services/core/java/com/android/server/location/injector/AlarmHelper.java @@ -33,7 +33,6 @@ public abstract class AlarmHelper { WorkSource workSource) { // helps ensure that we're not wasting system resources by setting alarms in the past/now Preconditions.checkArgument(delayMs > 0); - Preconditions.checkArgument(workSource != null); setDelayedAlarmInternal(delayMs, listener, workSource); } 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 8c9068daed9b..8955c288391f 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -735,8 +735,12 @@ public class LocationProviderManager extends if (mExpirationRealtimeMs <= registerTimeMs) { onAlarm(); } else if (mExpirationRealtimeMs < Long.MAX_VALUE) { + // Set WorkSource to null in order to ensure the alarm wakes up the device even when + // it is idle. Do this when the cost of waking up the device is less than the power + // cost of not performing the actions set off by the alarm, such as unregistering a + // location request. mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this, - getRequest().getWorkSource()); + null); } // start listening for provider enabled/disabled events @@ -1122,8 +1126,12 @@ public class LocationProviderManager extends if (mExpirationRealtimeMs <= registerTimeMs) { onAlarm(); } else if (mExpirationRealtimeMs < Long.MAX_VALUE) { + // Set WorkSource to null in order to ensure the alarm wakes up the device even when + // it is idle. Do this when the cost of waking up the device is less than the power + // cost of not performing the actions set off by the alarm, such as unregistering a + // location request. mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this, - getRequest().getWorkSource()); + null); } } @@ -1995,7 +2003,11 @@ public class LocationProviderManager extends } } }; - mAlarmHelper.setDelayedAlarm(delayMs, mDelayedRegister, newRequest.getWorkSource()); + // Set WorkSource to null in order to ensure the alarm wakes up the device even when it + // is idle. Do this when the cost of waking up the device is less than the power cost of + // not performing the actions set off by the alarm, such as unregistering a location + // request. + mAlarmHelper.setDelayedAlarm(delayMs, mDelayedRegister, null); } return true; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 0bec09cd003f..c0b8648b5328 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -2174,6 +2174,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId) { + checkPasswordReadPermission(); final VerifyCredentialResponse response; @@ -2185,6 +2186,7 @@ public class LockSettingsService extends ILockSettings.Stub { synchronized (mSpManager) { if (gatekeeperPassword == null) { + Slog.d(TAG, "No gatekeeper password for handle"); response = VerifyCredentialResponse.ERROR; } else { response = mSpManager.verifyChallengeInternal(getGateKeeperService(), diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index b144ff27c993..16a0b7e39a07 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -372,7 +372,7 @@ public class ZenModeHelper { } } if (rule.enabled != automaticZenRule.isEnabled()) { - dispatchOnAutomaticRuleStatusChanged(mConfig.user, rule.pkg, ruleId, + dispatchOnAutomaticRuleStatusChanged(mConfig.user, rule.getPkg(), ruleId, automaticZenRule.isEnabled() ? AUTOMATIC_RULE_STATUS_ENABLED : AUTOMATIC_RULE_STATUS_DISABLED); } @@ -391,13 +391,14 @@ public class ZenModeHelper { if (ruleToRemove == null) return false; if (canManageAutomaticZenRule(ruleToRemove)) { newConfig.automaticRules.remove(id); - if (ruleToRemove.pkg != null && !"android".equals(ruleToRemove.pkg)) { + if (ruleToRemove.getPkg() != null && !"android".equals(ruleToRemove.getPkg())) { for (ZenRule currRule : newConfig.automaticRules.values()) { - if (currRule.pkg != null && currRule.pkg.equals(ruleToRemove.pkg)) { + if (currRule.getPkg() != null + && currRule.getPkg().equals(ruleToRemove.getPkg())) { break; // no need to remove from cache } } - mRulesUidCache.remove(getPackageUserKey(ruleToRemove.pkg, newConfig.user)); + mRulesUidCache.remove(getPackageUserKey(ruleToRemove.getPkg(), newConfig.user)); } if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason); } else { @@ -405,7 +406,7 @@ public class ZenModeHelper { "Cannot delete rules not owned by your condition provider"); } dispatchOnAutomaticRuleStatusChanged( - mConfig.user, ruleToRemove.pkg, id, AUTOMATIC_RULE_STATUS_REMOVED); + mConfig.user, ruleToRemove.getPkg(), id, AUTOMATIC_RULE_STATUS_REMOVED); return setConfigLocked(newConfig, reason, null, true); } } @@ -417,14 +418,7 @@ public class ZenModeHelper { newConfig = mConfig.copy(); for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); - String pkg = rule.pkg != null - ? rule.pkg - : (rule.component != null) - ? rule.component.getPackageName() - : (rule.configurationActivity != null) - ? rule.configurationActivity.getPackageName() - : null; - if (Objects.equals(pkg, packageName) && canManageAutomaticZenRule(rule)) { + if (Objects.equals(rule.getPkg(), packageName) && canManageAutomaticZenRule(rule)) { newConfig.automaticRules.removeAt(i); } } @@ -524,7 +518,7 @@ public class ZenModeHelper { if (packages != null) { final int packageCount = packages.length; for (int i = 0; i < packageCount; i++) { - if (packages[i].equals(rule.pkg)) { + if (packages[i].equals(rule.getPkg())) { return true; } } @@ -834,8 +828,8 @@ public class ZenModeHelper { ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) { try { - if (rule.pkg != null) { - mPm.getPackageInfo(rule.pkg, PackageManager.MATCH_ANY_USER); + if (rule.getPkg() != null) { + mPm.getPackageInfo(rule.getPkg(), PackageManager.MATCH_ANY_USER); } } catch (PackageManager.NameNotFoundException e) { newConfig.automaticRules.removeAt(i); @@ -1246,7 +1240,7 @@ public class ZenModeHelper { } // Look for packages and enablers, enablers get priority. - String pkg = rule.pkg == null ? "" : rule.pkg; + String pkg = rule.getPkg() == null ? "" : rule.getPkg(); if (rule.enabler != null) { pkg = rule.enabler; id = ZenModeConfig.MANUAL_RULE_ID; diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6adde9ad25fd..00ef97d7a17a 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -1265,12 +1265,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mProgressLock") private void computeProgressLocked(boolean forcePublish) { - if (!mCommitted) { + if (!isIncrementalInstallation() || !mCommitted) { mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f) + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f); } else { - // For incremental install, continue to publish incremental progress during committing. - if (isIncrementalInstallation() && (mIncrementalProgress - mProgress) >= 0.01) { + // For incremental, publish regular install progress before the session is committed, + // but publish incremental progress afterwards. + if (mIncrementalProgress - mProgress >= 0.01) { // It takes some time for data loader to write to incremental file system, so at the // beginning of the commit, the incremental progress might be very small. // Wait till the incremental progress is larger than what's already displayed. @@ -1279,7 +1280,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - // Only publish when meaningful change + // Only publish meaningful progress changes. if (forcePublish || (mProgress - mReportedProgress) >= 0.01) { mReportedProgress = mProgress; mCallback.onSessionProgressChanged(this, mProgress); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index af3cb5bbe0cb..ee44c10edbf3 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -112,8 +112,6 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT; import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; -import static com.android.internal.util.ArrayUtils.emptyIfNull; -import static com.android.internal.util.ArrayUtils.filter; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME; @@ -7957,12 +7955,9 @@ public class PackageManagerService extends IPackageManager.Stub } catch (PackageManagerException e) { Slog.w(TAG, "updateAllSharedLibrariesLPw failed: ", e); } - final int[] userIds = mUserManager.getUserIds(); - for (final int userId : userIds) { - mPermissionManager.onPackageInstalled(pkg, - PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, - userId); - } + mPermissionManager.onPackageInstalled(pkg, + PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, + UserHandle.USER_ALL); writeSettingsLPrTEMP(); } } catch (PackageManagerException e) { @@ -19215,12 +19210,7 @@ public class PackageManagerService extends IPackageManager.Stub } final int autoRevokePermissionsMode = installArgs.autoRevokePermissionsMode; permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode); - for (int currentUserId : allUsersList) { - if (ps.getInstalled(currentUserId)) { - mPermissionManager.onPackageInstalled(pkg, permissionParamsBuilder.build(), - currentUserId); - } - } + mPermissionManager.onPackageInstalled(pkg, permissionParamsBuilder.build(), userId); } res.name = pkgName; res.uid = pkg.getUid(); @@ -21864,10 +21854,8 @@ public class PackageManagerService extends IPackageManager.Stub if (sharedUserPkgs == null) { sharedUserPkgs = Collections.emptyList(); } - for (final int userId : allUserHandles) { - mPermissionManager.onPackageUninstalled(packageName, deletedPs.appId, - deletedPs.pkg, sharedUserPkgs, userId); - } + mPermissionManager.onPackageUninstalled(packageName, deletedPs.appId, + deletedPs.pkg, sharedUserPkgs, UserHandle.USER_ALL); } clearPackagePreferredActivitiesLPw( deletedPs.name, changedUsers, UserHandle.USER_ALL); @@ -22084,11 +22072,12 @@ public class PackageManagerService extends IPackageManager.Stub } } + // The method below will take care of removing obsolete permissions and granting + // install permissions. + mPermissionManager.onPackageInstalled(pkg, + PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, + UserHandle.USER_ALL); for (final int userId : allUserHandles) { - // The method below will take care of removing obsolete permissions and granting - // install permissions. - mPermissionManager.onPackageInstalled(pkg, - PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, userId); if (applyUserRestrictions) { mSettings.writePermissionStateForUserLPr(userId, false); } @@ -22411,10 +22400,9 @@ public class PackageManagerService extends IPackageManager.Stub } removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), nextUserId, ps.appId); clearPackagePreferredActivities(ps.name, nextUserId); - mPermissionManager.onPackageUninstalled(ps.name, ps.appId, pkg, sharedUserPkgs, - nextUserId); mDomainVerificationManager.clearPackageForUser(ps.name, nextUserId); } + mPermissionManager.onPackageUninstalled(ps.name, ps.appId, pkg, sharedUserPkgs, userId); if (outInfo != null) { if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { @@ -23636,18 +23624,6 @@ public class PackageManagerService extends IPackageManager.Stub getPackageFromComponentString(R.string.config_defaultAppPredictionService)); } - private @NonNull String[] dropNonSystemPackages(@NonNull String[] pkgNames) { - return emptyIfNull(filter(pkgNames, String[]::new, mIsSystemPackage), String.class); - } - - private Predicate<String> mIsSystemPackage = (pkgName) -> { - if ("android".equals(pkgName)) { - return true; - } - AndroidPackage pkg = mPackages.get(pkgName); - return pkg != null && pkg.isSystem(); - }; - @Override public String getSystemCaptionsServicePackageName() { return ensureSystemPackageName( @@ -27271,7 +27247,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) { - return dropNonSystemPackages(getKnownPackageNamesInternal(knownPackage, userId)); + return getKnownPackageNamesInternal(knownPackage, userId); } private String[] getKnownPackageNamesInternal(int knownPackage, int userId) { diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 81ea46514d3d..376326264d9c 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -31,6 +31,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.permission.LegacyPermissionDataProvider; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.pkg.PackageStateUnserialized; +import com.android.server.utils.SnapshotCache; import java.io.File; import java.util.ArrayList; @@ -81,6 +82,7 @@ public class PackageSetting extends PackageSettingBase { * object equality to check whether shared user settings are the same. */ SharedUserSetting sharedUser; + /** * Temporary holding space for the shared user ID. While parsing package settings, the * shared users tag may come after the packages. In this case, we must delay linking the @@ -103,6 +105,19 @@ public class PackageSetting extends PackageSettingBase { @NonNull private UUID mDomainSetId; + /** + * Snapshot support. + */ + private final SnapshotCache<PackageSetting> mSnapshot; + + private SnapshotCache<PackageSetting> makeCache() { + return new SnapshotCache<PackageSetting>(this, this) { + @Override + public PackageSetting createSnapshot() { + return new PackageSetting(mSource, true); + }}; + } + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public PackageSetting(String name, String realName, @NonNull File codePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, @@ -118,6 +133,7 @@ public class PackageSetting extends PackageSettingBase { this.sharedUserId = sharedUserId; mDomainSetId = domainSetId; copyMimeGroups(mimeGroups); + mSnapshot = makeCache(); } /** @@ -127,6 +143,7 @@ public class PackageSetting extends PackageSettingBase { PackageSetting(PackageSetting orig) { super(orig, orig.realName); doCopy(orig); + mSnapshot = makeCache(); } /** @@ -137,6 +154,33 @@ public class PackageSetting extends PackageSettingBase { PackageSetting(PackageSetting orig, String realPkgName) { super(orig, realPkgName); doCopy(orig); + mSnapshot = makeCache(); + } + + /** + * Create a snapshot. The copy constructor is already in use and cannot be modified + * for this purpose. + */ + PackageSetting(PackageSetting orig, boolean snapshot) { + super(orig, snapshot); + // The existing doCopy() method cannot be used in here because sharedUser must be + // a snapshot, and not a reference. Also, the pkgState must be copied. However, + // this code should otherwise be kept in sync with doCopy(). + appId = orig.appId; + pkg = orig.pkg; + sharedUser = orig.sharedUser == null ? null : orig.sharedUser.snapshot(); + sharedUserId = orig.sharedUserId; + copyMimeGroups(orig.mimeGroups); + pkgState = orig.pkgState; + mDomainSetId = orig.getDomainSetId(); + mSnapshot = new SnapshotCache.Sealed(); + } + + /** + * Return the package snapshot. + */ + public PackageSetting snapshot() { + return mSnapshot.snapshot(); } /** @see #pkg **/ diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 731d41c38f79..bf82bd8b09d5 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -169,6 +169,15 @@ public abstract class PackageSettingBase extends SettingBase { doCopy(base); } + // A copy constructor used to create snapshots. The boolean is present only to + // match up with the constructor in PackageSetting. + PackageSettingBase(PackageSettingBase orig, boolean snapshot) { + super(orig); + name = orig.name; + realName = orig.realName; + doCopy(orig); + } + public void setInstallerPackageName(String packageName) { installSource = installSource.setInstallerPackage(packageName); onChanged(); diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index 0e8a278f3b6b..7b5c7e3a0c84 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -22,12 +22,13 @@ import android.content.pm.ApplicationInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.permission.LegacyPermissionState; +import com.android.server.utils.Snappable; import com.android.server.utils.Watchable; import com.android.server.utils.WatchableImpl; import com.android.server.utils.Watcher; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) -public abstract class SettingBase implements Watchable { +public abstract class SettingBase implements Watchable, Snappable { // TODO: make this variable protected, or even private with a getter and setter. // Simply making it protected or private requires that the name be changed to conformm // to the Android naming convention, and that touches quite a few files. diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java index 9b1c08d9c321..8ddbe08e2572 100644 --- a/services/core/java/com/android/server/pm/SharedUserSetting.java +++ b/services/core/java/com/android/server/pm/SharedUserSetting.java @@ -26,6 +26,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.util.ArrayUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.utils.SnapshotCache; import libcore.util.EmptyArray; @@ -49,12 +50,25 @@ public final class SharedUserSetting extends SettingBase { // that all apps within the sharedUser run in the same selinux context. int seInfoTargetSdkVersion; - final ArraySet<PackageSetting> packages = new ArraySet<>(); + final ArraySet<PackageSetting> packages; final PackageSignatures signatures = new PackageSignatures(); Boolean signaturesChanged; - ArrayMap<String, ParsedProcess> processes; + final ArrayMap<String, ParsedProcess> processes; + + /** + * Snapshot support. + */ + private final SnapshotCache<SharedUserSetting> mSnapshot; + + private SnapshotCache<SharedUserSetting> makeCache() { + return new SnapshotCache<SharedUserSetting>(this, this) { + @Override + public SharedUserSetting createSnapshot() { + return new SharedUserSetting(mSource); + }}; + } SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) { super(_pkgFlags, _pkgPrivateFlags); @@ -62,6 +76,31 @@ public final class SharedUserSetting extends SettingBase { uidPrivateFlags = _pkgPrivateFlags; name = _name; seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; + packages = new ArraySet<>(); + processes = new ArrayMap<>(); + mSnapshot = makeCache(); + } + + // The copy constructor is used to create a snapshot + private SharedUserSetting(SharedUserSetting orig) { + super(orig); + name = orig.name; + uidFlags = orig.uidFlags; + uidPrivateFlags = orig.uidPrivateFlags; + packages = new ArraySet(orig.packages); + // A PackageParser.SigningDetails seems to consist solely of final attributes, so + // it is safe to copy the reference. + signatures.mSigningDetails = orig.signatures.mSigningDetails; + signaturesChanged = orig.signaturesChanged; + processes = new ArrayMap(orig.processes); + mSnapshot = new SnapshotCache.Sealed(); + } + + /** + * Return a read-only snapshot of this object. + */ + public SharedUserSetting snapshot() { + return mSnapshot.snapshot(); } @Override @@ -80,9 +119,6 @@ public final class SharedUserSetting extends SettingBase { void addProcesses(Map<String, ParsedProcess> newProcs) { if (newProcs != null) { final int numProcs = newProcs.size(); - if (processes == null) { - processes = new ArrayMap<>(numProcs); - } for (String key : newProcs.keySet()) { ParsedProcess newProc = newProcs.get(key); ParsedProcess proc = processes.get(newProc.getName()); @@ -191,7 +227,7 @@ public final class SharedUserSetting extends SettingBase { * Update tracked data about processes based on all known packages in the shared user ID. */ public void updateProcesses() { - processes = null; + processes.clear(); for (int i = packages.size() - 1; i >= 0; i--) { final AndroidPackage pkg = packages.valueAt(i).pkg; if (pkg != null) { @@ -230,14 +266,15 @@ public final class SharedUserSetting extends SettingBase { this.signaturesChanged = sharedUser.signaturesChanged; if (sharedUser.processes != null) { final int numProcs = sharedUser.processes.size(); - this.processes = new ArrayMap<>(numProcs); + this.processes.clear(); + this.processes.ensureCapacity(numProcs); for (int i = 0; i < numProcs; i++) { ParsedProcess proc = new ParsedProcess(sharedUser.processes.valueAt(i)); this.processes.put(proc.getName(), proc); } } else { - this.processes = null; + this.processes.clear(); } onChanged(); return this; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 30ddbb60080f..dfc14bd733df 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2920,7 +2920,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { wasChanged = true; } - if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) { + if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0 + && !isPermissionSplitFromNonRuntime(permName, + pkg.getTargetSdkVersion())) { flags &= ~FLAG_PERMISSION_REVOKED_COMPAT; wasChanged = true; // Hard restricted permissions cannot be held. @@ -4038,17 +4040,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { * * @param packageName The package that is updated * @param pkg The package that is updated, or {@code null} if package is deleted - * @param filterUserId If not {@link UserHandle.USER_ALL}, only restore the permission state for - * this particular user */ - private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg, - @UserIdInt int filterUserId) { + private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) { // If the package is being deleted, update the permissions of all the apps final int flags = (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : UPDATE_PERMISSIONS_REPLACE_PKG); - updatePermissions(packageName, pkg, getVolumeUuidForPackage(pkg), flags, - mDefaultPermissionCallback, filterUserId); + updatePermissions( + packageName, pkg, getVolumeUuidForPackage(pkg), flags, mDefaultPermissionCallback); } /** @@ -4070,8 +4069,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { (fingerprintChanged ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL : 0); - updatePermissions(null, null, volumeUuid, flags, mDefaultPermissionCallback, - UserHandle.USER_ALL); + updatePermissions(null, null, volumeUuid, flags, mDefaultPermissionCallback); } finally { PackageManager.uncorkPackageInfoCache(); } @@ -4120,14 +4118,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { * all volumes * @param flags Control permission for which apps should be updated * @param callback Callback to call after permission changes - * @param filterUserId If not {@link UserHandle.USER_ALL}, only restore the permission state for - * this particular user */ private void updatePermissions(final @Nullable String changingPkgName, final @Nullable AndroidPackage changingPkg, final @Nullable String replaceVolumeUuid, @UpdatePermissionFlags int flags, - final @Nullable PermissionCallback callback, @UserIdInt int filterUserId) { + final @Nullable PermissionCallback callback) { // TODO: Most of the methods exposing BasePermission internals [source package name, // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't // have package settings, we should make note of it elsewhere [map between @@ -4163,7 +4159,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Only replace for packages on requested volume final String volumeUuid = getVolumeUuidForPackage(pkg); final boolean replace = replaceAll && Objects.equals(replaceVolumeUuid, volumeUuid); - restorePermissionState(pkg, replace, changingPkgName, callback, filterUserId); + restorePermissionState(pkg, replace, changingPkgName, callback, + UserHandle.USER_ALL); }); } @@ -4172,7 +4169,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { final String volumeUuid = getVolumeUuidForPackage(changingPkg); final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0) && Objects.equals(replaceVolumeUuid, volumeUuid); - restorePermissionState(changingPkg, replace, changingPkgName, callback, filterUserId); + restorePermissionState(changingPkg, replace, changingPkgName, callback, + UserHandle.USER_ALL); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -4839,18 +4837,20 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void onPackageInstalledInternal(@NonNull AndroidPackage pkg, @NonNull PermissionManagerServiceInternal.PackageInstalledParams params, - @UserIdInt int userId) { - updatePermissions(pkg.getPackageName(), pkg, userId); - addAllowlistedRestrictedPermissionsInternal(pkg, - params.getAllowlistedRestrictedPermissions(), - FLAG_PERMISSION_WHITELIST_INSTALLER, userId); - final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode(); - if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED - || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) { - setAutoRevokeExemptedInternal(pkg, - autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId); + @UserIdInt int[] userIds) { + updatePermissions(pkg.getPackageName(), pkg); + for (final int userId : userIds) { + addAllowlistedRestrictedPermissionsInternal(pkg, + params.getAllowlistedRestrictedPermissions(), + FLAG_PERMISSION_WHITELIST_INSTALLER, userId); + final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode(); + if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED + || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) { + setAutoRevokeExemptedInternal(pkg, + autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId); + } + grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId); } - grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId); } private void addAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg, @@ -4873,7 +4873,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void onPackageUninstalledInternal(@NonNull String packageName, int appId, @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs, - @UserIdInt int userId) { + @UserIdInt int[] userIds) { // TODO: Move these checks to check PackageState to be more reliable. // System packages should always have an available APK. if (pkg != null && pkg.isSystem() @@ -4884,27 +4884,31 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If we are only marking a system package as uninstalled, we need to keep its // pregranted permission state so that it still works once it gets reinstalled, thus // only reset the user modifications to its permission state. - resetRuntimePermissionsInternal(pkg, userId); + for (final int userId : userIds) { + resetRuntimePermissionsInternal(pkg, userId); + } return; } - updatePermissions(packageName, null, userId); - if (sharedUserPkgs.isEmpty()) { - removeUidStateAndResetPackageInstallPermissionsFixed(appId, packageName, userId); - } else { - // Remove permissions associated with package. Since runtime - // permissions are per user we have to kill the removed package - // or packages running under the shared user of the removed - // package if revoking the permissions requested only by the removed - // package is successful and this causes a change in gids. - final int userIdToKill = revokeSharedUserPermissionsForDeletedPackageInternal(pkg, - sharedUserPkgs, userId); - final boolean shouldKill = userIdToKill != UserHandle.USER_NULL; - // If gids changed, kill all affected packages. - if (shouldKill) { - mHandler.post(() -> { - // This has to happen with no lock held. - killUid(appId, UserHandle.USER_ALL, KILL_APP_REASON_GIDS_CHANGED); - }); + updatePermissions(packageName, null); + for (final int userId : userIds) { + if (sharedUserPkgs.isEmpty()) { + removeUidStateAndResetPackageInstallPermissionsFixed(appId, packageName, userId); + } else { + // Remove permissions associated with package. Since runtime + // permissions are per user we have to kill the removed package + // or packages running under the shared user of the removed + // package if revoking the permissions requested only by the removed + // package is successful and this causes a change in gids. + final int userIdToKill = revokeSharedUserPermissionsForDeletedPackageInternal(pkg, + sharedUserPkgs, userId); + final boolean shouldKill = userIdToKill != UserHandle.USER_NULL; + // If gids changed, kill all affected packages. + if (shouldKill) { + mHandler.post(() -> { + // This has to happen with no lock held. + killUid(appId, UserHandle.USER_ALL, KILL_APP_REASON_GIDS_CHANGED); + }); + } } } } @@ -5179,8 +5183,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { @NonNull PackageInstalledParams params, @UserIdInt int userId) { Objects.requireNonNull(pkg, "pkg"); Objects.requireNonNull(params, "params"); - Preconditions.checkArgumentNonNegative(userId, "userId"); - onPackageInstalledInternal(pkg, params, userId); + Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM + || userId == UserHandle.USER_ALL, "userId"); + final int[] userIds = userId == UserHandle.USER_ALL ? getAllUserIds() + : new int[] { userId }; + onPackageInstalledInternal(pkg, params, userIds); } @Override @@ -5195,8 +5202,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { @UserIdInt int userId) { Objects.requireNonNull(packageName, "packageName"); Objects.requireNonNull(sharedUserPkgs, "sharedUserPkgs"); - Preconditions.checkArgumentNonNegative(userId, "userId"); - onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userId); + Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM + || userId == UserHandle.USER_ALL, "userId"); + final int[] userIds = userId == UserHandle.USER_ALL ? getAllUserIds() + : new int[] { userId }; + onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userIds); } @NonNull diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index 9026262db897..ab7135526746 100644 --- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java +++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java @@ -189,12 +189,16 @@ public abstract class SoftRestrictedPermissionPolicy { return false; } - // 3. The app has WRITE_MEDIA_STORAGE, OR - // the app already has legacy external storage or requested it, - // and is < R. - return hasWriteMediaStorageGrantedForUid - || ((hasLegacyExternalStorage || hasRequestedLegacyExternalStorage) - && targetSDK < Build.VERSION_CODES.R); + // 3. The app targetSDK should be less than R + if (targetSDK >= Build.VERSION_CODES.R) { + return false; + } + + // 4. The app has WRITE_MEDIA_STORAGE, + // OR the app already has legacy external storage + // OR the app requested legacy external storage + return hasWriteMediaStorageGrantedForUid || hasLegacyExternalStorage + || hasRequestedLegacyExternalStorage; } @Override public boolean mayDenyExtraAppOpIfGranted() { @@ -216,10 +220,8 @@ public abstract class SoftRestrictedPermissionPolicy { return true; } - // The package doesn't have WRITE_MEDIA_STORAGE, - // AND didn't request legacy storage to be preserved - if (!hasWriteMediaStorageGrantedForUid - && !hasRequestedPreserveLegacyExternalStorage) { + // The package doesn't request legacy storage to be preserved + if (!hasRequestedPreserveLegacyExternalStorage) { return true; } diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java index 9c8ff685d14d..068626588745 100644 --- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java +++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java @@ -125,10 +125,12 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn } }); + // Eager local evaluation to avoid reading a different or null value at closure-run-time + final DelegatingListener listenerToStart = this.mDelegatingListener; run(service -> service.startListening( recognizerIntent, - mDelegatingListener, + listenerToStart, attributionSource)); } } @@ -162,7 +164,9 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn } mRecordingInProgress = false; - run(service -> service.stopListening(mDelegatingListener)); + // Eager local evaluation to avoid reading a different or null value at closure-run-time + final DelegatingListener listenerToStop = this.mDelegatingListener; + run(service -> service.stopListening(listenerToStop)); } } diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java index f7950aacedc3..5442e5b0413f 100644 --- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java +++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java @@ -141,7 +141,8 @@ final class SpeechRecognitionManagerServiceImpl extends throws RemoteException { attributionSource.enforceCallingUid(); if (!attributionSource.isTrusted(mMaster.getContext())) { - mMaster.getContext().getSystemService(PermissionManager.class) + attributionSource = mMaster.getContext() + .getSystemService(PermissionManager.class) .registerAttributionSource(attributionSource); } service.startListening(recognizerIntent, listener, attributionSource); @@ -255,8 +256,8 @@ final class SpeechRecognitionManagerServiceImpl extends private boolean componentMapsToRecognitionService(@NonNull ComponentName serviceComponent) { List<ResolveInfo> resolveInfos = - getContext().getPackageManager().queryIntentServices( - new Intent(RecognitionService.SERVICE_INTERFACE), 0); + getContext().getPackageManager().queryIntentServicesAsUser( + new Intent(RecognitionService.SERVICE_INTERFACE), 0, getUserId()); if (resolveInfos == null) { return false; } diff --git a/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java b/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java index 9f8b27f5f1bf..30b6e688bab6 100644 --- a/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java +++ b/services/core/java/com/android/server/stats/pull/SystemMemoryUtil.java @@ -28,7 +28,7 @@ final class SystemMemoryUtil { static Metrics getMetrics() { int totalIonKb = (int) Debug.getDmabufHeapTotalExportedKb(); int gpuTotalUsageKb = (int) Debug.getGpuTotalUsageKb(); - int gpuDmaBufUsageKb = (int) Debug.getGpuDmaBufUsageKb(); + int gpuPrivateAllocationsKb = (int) Debug.getGpuPrivateMemoryKb(); int dmaBufTotalExportedKb = (int) Debug.getDmabufTotalExportedKb(); long[] mInfos = new long[Debug.MEMINFO_COUNT]; @@ -58,10 +58,6 @@ final class SystemMemoryUtil { accountedKb += mInfos[Debug.MEMINFO_KERNEL_STACK]; } - int gpuPrivateAllocationsKb = -1; - if (gpuTotalUsageKb >= 0 && gpuDmaBufUsageKb >= 0) { - gpuPrivateAllocationsKb = gpuTotalUsageKb - gpuDmaBufUsageKb; - } // If we can distinguish gpu private allocs it means the dmabuf metrics // are supported already. if (dmaBufTotalExportedKb >= 0 && gpuPrivateAllocationsKb >= 0) { diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java index fca706b707fa..a31c56a3b737 100644 --- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java @@ -36,6 +36,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; @@ -85,6 +86,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @NonNull private final SubscriptionManager mSubscriptionManager; @NonNull private final CarrierConfigManager mCarrierConfigManager; + @NonNull private final ActiveDataSubscriptionIdListener mActiveDataSubIdListener; + // TODO (Android T+): Add ability to handle multiple subIds per slot. @NonNull private final Map<Integer, Integer> mReadySubIdsBySlotId = new HashMap<>(); @NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener; @@ -112,6 +115,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { mTelephonyManager = mContext.getSystemService(TelephonyManager.class); mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); + mActiveDataSubIdListener = new ActiveDataSubscriptionIdListener(); mSubscriptionChangedListener = new OnSubscriptionsChangedListener() { @@ -124,16 +128,20 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { /** Registers the receivers, and starts tracking subscriptions. */ public void register() { + final HandlerExecutor executor = new HandlerExecutor(mHandler); + mContext.registerReceiver( this, new IntentFilter(ACTION_CARRIER_CONFIG_CHANGED), null, mHandler); mSubscriptionManager.addOnSubscriptionsChangedListener( - new HandlerExecutor(mHandler), mSubscriptionChangedListener); + executor, mSubscriptionChangedListener); + mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener); } /** Unregisters the receivers, and stops tracking subscriptions. */ public void unregister() { mContext.unregisterReceiver(this); mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener); + mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener); } /** @@ -185,7 +193,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } final TelephonySubscriptionSnapshot newSnapshot = - new TelephonySubscriptionSnapshot(newSubIdToInfoMap, privilegedPackages); + new TelephonySubscriptionSnapshot( + mDeps.getActiveDataSubscriptionId(), newSubIdToInfoMap, privilegedPackages); // If snapshot was meaningfully updated, fire the callback if (!newSnapshot.equals(mCurrentSnapshot)) { @@ -242,16 +251,20 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { /** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */ public static class TelephonySubscriptionSnapshot { + private final int mActiveDataSubId; private final Map<Integer, SubscriptionInfo> mSubIdToInfoMap; private final Map<ParcelUuid, Set<String>> mPrivilegedPackages; public static final TelephonySubscriptionSnapshot EMPTY_SNAPSHOT = - new TelephonySubscriptionSnapshot(Collections.emptyMap(), Collections.emptyMap()); + new TelephonySubscriptionSnapshot( + INVALID_SUBSCRIPTION_ID, Collections.emptyMap(), Collections.emptyMap()); @VisibleForTesting(visibility = Visibility.PRIVATE) TelephonySubscriptionSnapshot( + int activeDataSubId, @NonNull Map<Integer, SubscriptionInfo> subIdToInfoMap, @NonNull Map<ParcelUuid, Set<String>> privilegedPackages) { + mActiveDataSubId = activeDataSubId; Objects.requireNonNull(subIdToInfoMap, "subIdToInfoMap was null"); Objects.requireNonNull(privilegedPackages, "privilegedPackages was null"); @@ -265,6 +278,22 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { mPrivilegedPackages = Collections.unmodifiableMap(unmodifiableInnerSets); } + /** Returns the active subscription ID. May be INVALID_SUBSCRIPTION_ID */ + public int getActiveDataSubscriptionId() { + return mActiveDataSubId; + } + + /** Returns the active subscription group */ + @Nullable + public ParcelUuid getActiveDataSubscriptionGroup() { + final SubscriptionInfo info = mSubIdToInfoMap.get(getActiveDataSubscriptionId()); + if (info == null) { + return null; + } + + return info.getGroupUuid(); + } + /** Returns the active subscription groups */ @NonNull public Set<ParcelUuid> getActiveSubscriptionGroups() { @@ -313,7 +342,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public int hashCode() { - return Objects.hash(mSubIdToInfoMap, mPrivilegedPackages); + return Objects.hash(mActiveDataSubId, mSubIdToInfoMap, mPrivilegedPackages); } @Override @@ -324,7 +353,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj; - return mSubIdToInfoMap.equals(other.mSubIdToInfoMap) + return mActiveDataSubId == other.mActiveDataSubId + && mSubIdToInfoMap.equals(other.mSubIdToInfoMap) && mPrivilegedPackages.equals(other.mPrivilegedPackages); } @@ -333,6 +363,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { pw.println("TelephonySubscriptionSnapshot:"); pw.increaseIndent(); + pw.println("mActiveDataSubId: " + mActiveDataSubId); pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap); pw.println("mPrivilegedPackages: " + mPrivilegedPackages); @@ -342,7 +373,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public String toString() { return "TelephonySubscriptionSnapshot{ " - + "mSubIdToInfoMap=" + mSubIdToInfoMap + + "mActiveDataSubId=" + mActiveDataSubId + + ", mSubIdToInfoMap=" + mSubIdToInfoMap + ", mPrivilegedPackages=" + mPrivilegedPackages + " }"; } @@ -362,6 +394,14 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { void onNewSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot); } + private class ActiveDataSubscriptionIdListener extends TelephonyCallback + implements TelephonyCallback.ActiveDataSubscriptionIdListener { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + handleSubscriptionsChanged(); + } + } + /** External static dependencies for test injection */ @VisibleForTesting(visibility = Visibility.PRIVATE) public static class Dependencies { @@ -369,5 +409,10 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { public boolean isConfigForIdentifiedCarrier(PersistableBundle bundle) { return CarrierConfigManager.isConfigForIdentifiedCarrier(bundle); } + + /** Gets the active Subscription ID */ + public int getActiveDataSubscriptionId() { + return SubscriptionManager.getActiveDataSubscriptionId(); + } } } diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java index 03863723a5e9..dd4e260c6d91 100644 --- a/services/core/java/com/android/server/vibrator/VibrationThread.java +++ b/services/core/java/com/android/server/vibrator/VibrationThread.java @@ -1294,21 +1294,32 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { @Override public boolean shouldPlayWhenVibratorComplete(int vibratorId) { if (controller.getVibratorInfo().getId() == vibratorId) { + mVibratorCallbackReceived = true; mNextOffTime = SystemClock.uptimeMillis(); } - // Timings are tightly controlled here, so never anticipate when vibrator is complete. - return false; + // Timings are tightly controlled here, so only anticipate if the vibrator was supposed + // to be ON but has completed prematurely, to turn it back on as soon as possible. + return mNextOffTime < startTime && controller.getCurrentAmplitude() > 0; } @Override public List<Step> play() { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "AmplitudeStep"); try { + long now = SystemClock.uptimeMillis(); + long latency = now - startTime; if (DEBUG) { - long latency = SystemClock.uptimeMillis() - startTime; Slog.d(TAG, "Running amplitude step with " + latency + "ms latency."); } + if (mVibratorCallbackReceived && latency < 0) { + // This step was anticipated because the vibrator turned off prematurely. + // Turn it back on and return this same step to run at the exact right time. + mNextOffTime = turnVibratorBackOn(/* remainingDuration= */ -latency); + return Arrays.asList(new AmplitudeStep(startTime, controller, effect, + segmentIndex, mNextOffTime)); + } + VibrationEffectSegment segment = effect.getSegments().get(segmentIndex); if (!(segment instanceof StepSegment)) { Slog.w(TAG, "Ignoring wrong segment for a AmplitudeStep: " + segment); @@ -1321,17 +1332,16 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { return skipToNextSteps(/* segmentsSkipped= */ 1); } - long now = SystemClock.uptimeMillis(); float amplitude = stepSegment.getAmplitude(); if (amplitude == 0) { - if (mNextOffTime > now) { + if (vibratorOffTimeout > now) { // Amplitude cannot be set to zero, so stop the vibrator. stopVibrating(); mNextOffTime = now; } } else { if (startTime >= mNextOffTime) { - // Vibrator has stopped. Turn vibrator back on for the duration of another + // Vibrator is OFF. Turn vibrator back on for the duration of another // cycle before setting the amplitude. long onDuration = getVibratorOnDuration(effect, segmentIndex); if (onDuration > 0) { @@ -1350,6 +1360,22 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { } } + private long turnVibratorBackOn(long remainingDuration) { + long onDuration = getVibratorOnDuration(effect, segmentIndex); + if (onDuration <= 0) { + // Vibrator is supposed to go back off when this step starts, so just leave it off. + return vibratorOffTimeout; + } + onDuration += remainingDuration; + float expectedAmplitude = controller.getCurrentAmplitude(); + mVibratorOnResult = startVibrating(onDuration); + if (mVibratorOnResult > 0) { + // Set the amplitude back to the value it was supposed to be playing at. + changeAmplitude(expectedAmplitude); + } + return SystemClock.uptimeMillis() + onDuration + CALLBACKS_EXTRA_TIMEOUT; + } + private long startVibrating(long duration) { if (DEBUG) { Slog.d(TAG, "Turning on vibrator " + controller.getVibratorInfo().getId() + " for " @@ -1383,7 +1409,10 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { repeatIndex = -1; } if (i == startIndex) { - return 1000; + // The repeating waveform keeps the vibrator ON all the time. Use a minimum + // of 1s duration to prevent short patterns from turning the vibrator ON too + // frequently. + return Math.max(timing, 1000); } } if (i == segmentCount && effect.getRepeatIndex() < 0) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index f3dbed574b06..4c1992ef18b2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -801,6 +801,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Tracking cookie for the launch of this activity and it's task. IBinder mLaunchCookie; + // Entering PiP is usually done in two phases, we put the task into pinned mode first and + // SystemUi sets the pinned mode on activity after transition is done. + boolean mWaitForEnteringPinnedMode; + private final Runnable mPauseTimeoutRunnable = new Runnable() { @Override public void run() { @@ -4721,7 +4725,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private void postApplyAnimation(boolean visible) { final boolean delayed = isAnimating(PARENTS | CHILDREN, - ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION); + ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION + | ANIMATION_TYPE_RECENTS); if (!delayed) { // We aren't delayed anything, but exiting windows rely on the animation finished // callback being called in case the ActivityRecord was pretending to be delayed, @@ -4741,7 +4746,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // updated. // If we're becoming invisible, update the client visibility if we are not running an // animation. Otherwise, we'll update client visibility in onAnimationFinished. - if (visible || !isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { + if (visible || !isAnimating(PARENTS, + ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) { setClientVisible(visible); } @@ -7705,6 +7711,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // mode (see RootWindowContainer#moveActivityToPinnedRootTask). So once the windowing mode // of activity is changed, it is the signal of the last step to update the PiP states. if (!wasInPictureInPicture && inPinnedWindowingMode() && task != null) { + mWaitForEnteringPinnedMode = false; mTaskSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, task.getBounds()); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 090a01aa6f1b..f3ba56a03aef 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -5604,7 +5604,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public ActivityTokens getTopActivityForTask(int taskId) { synchronized (mGlobalLock) { - final Task task = mRootWindowContainer.anyTaskForId(taskId); + final Task task = mRootWindowContainer.anyTaskForId(taskId, + MATCH_ATTACHED_TASK_ONLY); if (task == null) { Slog.w(TAG, "getApplicationThreadForTopActivity failed:" + " Requested task not found"); @@ -6471,12 +6472,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.w(TAG, "Override application configuration: cannot find pid " + mPid); return; } - if (wpc.getNightMode() == mNightMode) { - return; - } - if (!wpc.setOverrideNightMode(mNightMode)) { - return; - } + wpc.setOverrideNightMode(mNightMode); wpc.updateNightModeForAllActivities(mNightMode); mPackageConfigPersister.updateFromImpl(wpc.mName, wpc.mUserId, this); } finally { diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 8fbe1775fd19..d52e9b608cdb 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -545,8 +545,8 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @return true if the nightMode has been changed. */ public boolean setOverrideNightMode(int nightMode) { - final int currentUiMode = mFullConfiguration.uiMode; - final int currentNightMode = getNightMode(); + final int currentUiMode = mRequestedOverrideConfiguration.uiMode; + final int currentNightMode = currentUiMode & Configuration.UI_MODE_NIGHT_MASK; final int validNightMode = nightMode & Configuration.UI_MODE_NIGHT_MASK; if (currentNightMode == validNightMode) { return false; @@ -558,10 +558,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { return true; } - int getNightMode() { - return mFullConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK; - } - public boolean isActivityTypeDream() { return getActivityType() == ACTIVITY_TYPE_DREAM; } diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java index 35add129309f..75abd171bb9b 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java +++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java @@ -26,6 +26,7 @@ import android.content.pm.ParceledListSlice; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.util.Slog; import android.view.SurfaceControl; import android.window.DisplayAreaAppearedInfo; import android.window.IDisplayAreaOrganizer; @@ -49,7 +50,8 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl final ActivityTaskManagerService mService; private final WindowManagerGlobalLock mGlobalLock; - private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap(); + private final HashMap<Integer, DisplayAreaOrganizerState> mOrganizersByFeatureIds = + new HashMap(); private class DeathRecipient implements IBinder.DeathRecipient { int mFeature; @@ -63,12 +65,41 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl @Override public void binderDied() { synchronized (mGlobalLock) { - mOrganizersByFeatureIds.remove(mFeature); - removeOrganizer(mOrganizer); + mOrganizersByFeatureIds.remove(mFeature).destroy(); } } } + private class DisplayAreaOrganizerState { + private final IDisplayAreaOrganizer mOrganizer; + private final DeathRecipient mDeathRecipient; + + DisplayAreaOrganizerState(IDisplayAreaOrganizer organizer, int feature) { + mOrganizer = organizer; + mDeathRecipient = new DeathRecipient(organizer, feature); + try { + organizer.asBinder().linkToDeath(mDeathRecipient, 0); + } catch (RemoteException e) { + // Oh well... + } + } + + void destroy() { + IBinder organizerBinder = mOrganizer.asBinder(); + mService.mRootWindowContainer.forAllDisplayAreas((da) -> { + if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) { + if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) { + // Delete the organizer created TDA when unregister. + deleteTaskDisplayArea(da.asTaskDisplayArea()); + } else { + da.setOrganizer(null); + } + } + }); + organizerBinder.unlinkToDeath(mDeathRecipient, 0); + } + } + DisplayAreaOrganizerController(ActivityTaskManagerService atm) { mService = atm; mGlobalLock = atm.mGlobalLock; @@ -80,7 +111,8 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl @Nullable IDisplayAreaOrganizer getOrganizerByFeature(int featureId) { - return mOrganizersByFeatureIds.get(featureId); + final DisplayAreaOrganizerState state = mOrganizersByFeatureIds.get(featureId); + return state != null ? state.mOrganizer : null; } @Override @@ -94,17 +126,18 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register display organizer=%s uid=%d", organizer.asBinder(), uid); if (mOrganizersByFeatureIds.get(feature) != null) { - throw new IllegalStateException( - "Replacing existing organizer currently unsupported"); - } + if (mOrganizersByFeatureIds.get(feature).mOrganizer.asBinder() + .isBinderAlive()) { + throw new IllegalStateException( + "Replacing existing organizer currently unsupported"); + } - final DeathRecipient dr = new DeathRecipient(organizer, feature); - try { - organizer.asBinder().linkToDeath(dr, 0); - } catch (RemoteException e) { - // Oh well... + mOrganizersByFeatureIds.remove(feature).destroy(); + Slog.d(TAG, "Replacing dead organizer for feature=" + feature); } + final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer, + feature); final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>(); mService.mRootWindowContainer.forAllDisplays(dc -> { if (!dc.isTrusted()) { @@ -120,7 +153,7 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl }); }); - mOrganizersByFeatureIds.put(feature, organizer); + mOrganizersByFeatureIds.put(feature, state); return new ParceledListSlice<>(displayAreaInfos); } } finally { @@ -137,9 +170,11 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl synchronized (mGlobalLock) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister display organizer=%s uid=%d", organizer.asBinder(), uid); - mOrganizersByFeatureIds.entrySet().removeIf( - entry -> entry.getValue().asBinder() == organizer.asBinder()); - removeOrganizer(organizer); + mOrganizersByFeatureIds.values().forEach((state) -> { + if (state.mOrganizer.asBinder() == organizer.asBinder()) { + state.destroy(); + } + }); } } finally { Binder.restoreCallingIdentity(origId); @@ -190,19 +225,15 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl } final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++; - final DeathRecipient dr = new DeathRecipient(organizer, taskDisplayAreaFeatureId); - try { - organizer.asBinder().linkToDeath(dr, 0); - } catch (RemoteException e) { - // Oh well... - } + final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer, + taskDisplayAreaFeatureId); final TaskDisplayArea tda = parentRoot != null ? createTaskDisplayArea(parentRoot, name, taskDisplayAreaFeatureId) : createTaskDisplayArea(parentTda, name, taskDisplayAreaFeatureId); final DisplayAreaAppearedInfo tdaInfo = organizeDisplayArea(organizer, tda, "DisplayAreaOrganizerController.createTaskDisplayArea"); - mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, organizer); + mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, state); return tdaInfo; } } finally { @@ -230,8 +261,7 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl + "TaskDisplayArea=" + taskDisplayArea); } - mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId); - deleteTaskDisplayArea(taskDisplayArea); + mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId).destroy(); } } finally { Binder.restoreCallingIdentity(origId); @@ -251,6 +281,10 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl void onDisplayAreaVanished(IDisplayAreaOrganizer organizer, DisplayArea da) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "DisplayArea vanished name=%s", da.getName()); + if (!organizer.asBinder().isBinderAlive()) { + Slog.d(TAG, "Organizer died before sending onDisplayAreaVanished"); + return; + } try { organizer.onDisplayAreaVanished(da.getDisplayAreaInfo()); } catch (RemoteException e) { @@ -267,20 +301,6 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl } } - private void removeOrganizer(IDisplayAreaOrganizer organizer) { - IBinder organizerBinder = organizer.asBinder(); - mService.mRootWindowContainer.forAllDisplayAreas((da) -> { - if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) { - if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) { - // Delete the organizer created TDA when unregister. - deleteTaskDisplayArea(da.asTaskDisplayArea()); - } else { - da.setOrganizer(null); - } - } - }); - } - private DisplayAreaAppearedInfo organizeDisplayArea(IDisplayAreaOrganizer organizer, DisplayArea displayArea, String callsite) { displayArea.setOrganizer(organizer, true /* skipDisplayAreaAppeared */); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 97c19ab72918..73d31bf7e0c8 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1568,6 +1568,10 @@ public class DisplayPolicy { layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR)); return; } + if (win.mActivityRecord != null && win.mActivityRecord.mWaitForEnteringPinnedMode) { + // Skip layout of the window when in transition to pip mode. + return; + } final WindowManager.LayoutParams attrs = win.getAttrs(); final int type = attrs.type; diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index a10b5d6e8177..b1bdc11ecee4 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -239,8 +239,10 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan // Fetch all the surface controls and pass them to the client to get the animation // started. Cancel any existing recents animation running synchronously (do not hold the // WM lock) - mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, - "startRecentsActivity"); + if (mWindowManager.getRecentsAnimationController() != null) { + mWindowManager.getRecentsAnimationController().forceCancelAnimation( + REORDER_MOVE_TO_ORIGINAL_POSITION, "startRecentsActivity"); + } mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner, this, mDefaultTaskDisplayArea.getDisplayId(), mTaskSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 9e147b132682..e346e3ec7db9 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -122,9 +122,7 @@ public class RecentsAnimationController implements DeathRecipient { new ArrayList<>(); private final int mDisplayId; private boolean mWillFinishToHome = false; - private final Runnable mFailsafeRunnable = () -> cancelAnimation( - mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, - "failSafeRunnable"); + private final Runnable mFailsafeRunnable = this::onFailsafe; // The recents component app token that is shown behind the visibile tasks private ActivityRecord mTargetActivityRecord; @@ -262,9 +260,6 @@ public class RecentsAnimationController implements DeathRecipient { final long token = Binder.clearCallingIdentity(); try { synchronized (mService.getWindowManagerLock()) { - if (mCanceled) { - return; - } // Remove all new task targets. for (int i = mPendingNewTaskTargets.size() - 1; i >= 0; i--) { removeTaskInternal(mPendingNewTaskTargets.get(i)); @@ -807,6 +802,14 @@ public class RecentsAnimationController implements DeathRecipient { }, mPendingWallpaperAnimations); } + void forceCancelAnimation(@ReorderMode int reorderMode, String reason) { + if (!mCanceled) { + cancelAnimation(reorderMode, reason); + } else { + continueDeferredCancelAnimation(); + } + } + void cancelAnimation(@ReorderMode int reorderMode, String reason) { cancelAnimation(reorderMode, false /*screenshot */, reason); } @@ -821,9 +824,6 @@ public class RecentsAnimationController implements DeathRecipient { * finish the animation. */ public void cancelAnimationForHomeStart() { - if (mCanceled) { - return; - } final int reorderMode = mTargetActivityType == ACTIVITY_TYPE_HOME && mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_KEEP_IN_PLACE; @@ -836,9 +836,6 @@ public class RecentsAnimationController implements DeathRecipient { * how to finish the animation. */ public void cancelAnimationForDisplayChange() { - if (mCanceled) { - return; - } cancelAnimation(mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, true /* screenshot */, "cancelAnimationForDisplayChange"); } @@ -868,6 +865,8 @@ public class RecentsAnimationController implements DeathRecipient { if (taskSnapshot != null) { // Defer until the runner calls back to cleanupScreenshot() adapter.setSnapshotOverlay(taskSnapshot); + // Schedule a new failsafe for if the runner doesn't clean up the screenshot + scheduleFailsafe(); } else { // Do a normal cancel since we couldn't screenshot mCallbacks.onAnimationFinished(reorderMode, false /* sendUserLeaveHint */); @@ -1014,6 +1013,12 @@ public class RecentsAnimationController implements DeathRecipient { mService.mH.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY); } + void onFailsafe() { + forceCancelAnimation( + mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, + "onFailsafe"); + } + private void linkToDeathOfRunner() throws RemoteException { if (!mLinkedToDeathOfRunner) { mRunner.asBinder().linkToDeath(this, 0); @@ -1030,13 +1035,7 @@ public class RecentsAnimationController implements DeathRecipient { @Override public void binderDied() { - if (!mCanceled) { - cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); - } else { - // If we are already canceled but with a screenshot, and are waiting for the - // cleanupScreenshot() callback, then force-finish the animation now - continueDeferredCancelAnimation(); - } + forceCancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); synchronized (mService.getWindowManagerLock()) { // Clear associated input consumers on runner death @@ -1358,5 +1357,7 @@ public class RecentsAnimationController implements DeathRecipient { + mCancelOnNextTransitionStart); pw.print(innerPrefix); pw.println("mCancelDeferredWithScreenshot=" + mCancelDeferredWithScreenshot); + pw.print(innerPrefix); pw.println("mPendingCancelWithScreenshotReorderMode=" + + mPendingCancelWithScreenshotReorderMode); } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 9a6a51848317..32147215834f 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2191,6 +2191,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // from doing work and changing the activity visuals while animating // TODO(task-org): Figure-out more structured way to do this long term. r.setWindowingMode(intermediateWindowingMode); + r.mWaitForEnteringPinnedMode = true; rootTask.setWindowingMode(WINDOWING_MODE_PINNED); rootTask.setDeferTaskAppear(false); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 777306aa13c5..936b2efa00ad 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -61,6 +61,8 @@ import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.SurfaceControl.METADATA_TASK_ID; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; @@ -4105,6 +4107,7 @@ class Task extends WindowContainer<WindowContainer> { info.positionInParent = getRelativePosition(); info.pictureInPictureParams = getPictureInPictureParams(top); + info.displayCutoutInsets = getDisplayCutoutInsets(top); info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info : null; @@ -4139,6 +4142,18 @@ class Task extends WindowContainer<WindowContainer> { ? null : new PictureInPictureParams(topVisibleActivity.pictureInPictureArgs); } + private Rect getDisplayCutoutInsets(Task top) { + if (top == null || top.mDisplayContent == null + || top.getDisplayInfo().displayCutout == null) return null; + final WindowState w = top.getTopVisibleAppMainWindow(); + final int displayCutoutMode = w == null + ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + : w.getAttrs().layoutInDisplayCutoutMode; + return (displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS + || displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) + ? null : top.getDisplayInfo().displayCutout.getSafeInsets(); + } + /** * Returns a {@link TaskInfo} with information from this task. */ diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index fd71d1bc1c38..193d92a3b2ff 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -14991,9 +14991,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void setNetworkLoggingActiveInternal(boolean active) { - final boolean[] shouldSendNotification = new boolean[] {false}; - synchronized (getLockObject()) { - mInjector.binderWithCleanCallingIdentity(() -> { + mInjector.binderWithCleanCallingIdentity(() -> { + boolean shouldSendNotification = false; + synchronized (getLockObject()) { if (active) { if (mNetworkLogger == null) { final int affectedUserId = getNetworkLoggingAffectedUser(); @@ -15008,7 +15008,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " service not being available yet."); } maybePauseDeviceWideLoggingLocked(); - shouldSendNotification[0] = shouldSendNetworkLoggingNotificationLocked(); + shouldSendNotification = shouldSendNetworkLoggingNotificationLocked(); } else { if (mNetworkLogger != null && !mNetworkLogger.stopNetworkLogging()) { Slogf.wtf(LOG_TAG, "Network logging could not be stopped due to the logging" @@ -15016,15 +15016,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } mNetworkLogger = null; } - }); - } - if (active) { - if (shouldSendNotification[0]) { - sendNetworkLoggingNotification(); } - } else { - mInjector.getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_LOGGING); - } + if (active) { + if (shouldSendNotification) { + mHandler.post(() -> sendNetworkLoggingNotification()); + } + } else { + mHandler.post(() -> mInjector.getNotificationManager().cancel( + SystemMessage.NOTE_NETWORK_LOGGING)); + } + }); } private @UserIdInt int getNetworkLoggingAffectedUser() { 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 583797e69995..a254f68e8bed 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -514,8 +514,16 @@ public class AlarmManagerServiceTest { } private void setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi, - boolean unrestricted) { - final int flags = unrestricted ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED : FLAG_ALLOW_WHILE_IDLE; + boolean unrestricted, boolean compat) { + assertFalse("Alarm cannot be compat and unrestricted", unrestricted && compat); + final int flags; + if (unrestricted) { + flags = FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; + } else if (compat) { + flags = FLAG_ALLOW_WHILE_IDLE_COMPAT; + } else { + flags = FLAG_ALLOW_WHILE_IDLE; + } setTestAlarm(type, triggerTime, pi, 0, flags, TEST_CALLING_UID); } @@ -1600,13 +1608,13 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < quota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, - getNewMockPendingIntent(), false); + getNewMockPendingIntent(), false, false); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, - getNewMockPendingIntent(), false); + getNewMockPendingIntent(), false, false); final long expectedNextTrigger = firstTrigger + mAllowWhileIdleWindow; assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, mTestTimer.getElapsed()); @@ -1619,6 +1627,108 @@ public class AlarmManagerServiceTest { } @Test + public void allowWhileIdleCompatAlarmsWhileDeviceIdle() throws Exception { + setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); + + final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + window + 1000, + getNewMockPendingIntent()); + assertNotNull(mService.mPendingIdleUntil); + + final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; + final long firstTrigger = mNowElapsedTest + 10; + for (int i = 0; i < quota; i++) { + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, + getNewMockPendingIntent(), false, true); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + } + // This one should get deferred on set. + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, + getNewMockPendingIntent(), false, true); + final long expectedNextTrigger = firstTrigger + window; + assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, + mTestTimer.getElapsed()); + + // Bring the idle until alarm back. + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50, + getNewMockPendingIntent()); + assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed()); + assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); + } + + @Test + public void allowWhileIdleCompatHistorySeparate() throws Exception { + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); + when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); + + final int fullQuota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; + final int compatQuota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; + + final long fullWindow = mAllowWhileIdleWindow; + final long compatWindow = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; + + final long firstFullTrigger = mNowElapsedTest + 10; + for (int i = 0; i < fullQuota; i++) { + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + i, + getNewMockPendingIntent(), false, false); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + } + // This one should get deferred on set, as full quota is not available. + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + fullQuota, + getNewMockPendingIntent(), false, false); + final long expectedNextFullTrigger = firstFullTrigger + fullWindow; + assertEquals("Incorrect trigger when no quota left", expectedNextFullTrigger, + mTestTimer.getElapsed()); + mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); + + // The following should be allowed, as compat quota should be free. + for (int i = 0; i < compatQuota; i++) { + final long trigger = mNowElapsedTest + 1; + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), + false, true); + assertEquals(trigger, mTestTimer.getElapsed()); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + } + + // Refresh the state + mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); + mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); + mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, + TEST_CALLING_USER); + + // Now test with flipped order + + final long firstCompatTrigger = mNowElapsedTest + 10; + for (int i = 0; i < compatQuota; i++) { + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + i, + getNewMockPendingIntent(), false, true); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + } + // This one should get deferred on set, as full quota is not available. + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + compatQuota, + getNewMockPendingIntent(), false, true); + final long expectedNextCompatTrigger = firstCompatTrigger + compatWindow; + assertEquals("Incorrect trigger when no quota left", expectedNextCompatTrigger, + mTestTimer.getElapsed()); + mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); + + // The following should be allowed, as full quota should be free. + for (int i = 0; i < fullQuota; i++) { + final long trigger = mNowElapsedTest + 1; + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), + false, false); + assertEquals(trigger, mTestTimer.getElapsed()); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + } + } + + @Test public void allowWhileIdleUnrestricted() throws Exception { setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); @@ -1634,7 +1744,7 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < numAlarms; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, - getNewMockPendingIntent(), true); + getNewMockPendingIntent(), true, false); } // All of them should fire as expected. for (int i = 0; i < numAlarms; i++) { @@ -1736,7 +1846,7 @@ public class AlarmManagerServiceTest { final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, - getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); + getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, @@ -1744,7 +1854,7 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, - trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); + trigger, getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, @@ -1752,7 +1862,36 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, - getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); + getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); + } + + @Test + public void allowWhileIdleCompatAlarmsInBatterySaver() throws Exception { + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); + when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); + + final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; + final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; + + testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, + getNewMockPendingIntent(), false, true), quota, window); + + // Refresh the state + mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); + mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, + TEST_CALLING_USER); + + testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, + trigger, getNewMockPendingIntent(), false, true), quota, window); + + // Refresh the state + mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); + mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, + TEST_CALLING_USER); + + testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, + getNewMockPendingIntent(), false, true), quota, window); } @Test @@ -2123,7 +2262,7 @@ public class AlarmManagerServiceTest { final PendingIntent alarmPi = getNewMockPendingIntent(); final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, - alarmPi, null, null, null, alarmClock); + alarmPi, null, null, null, alarmClock); // Correct permission checks are invoked. verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index 91f49224fde8..5b067bc58da3 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -869,6 +869,446 @@ public class AppSearchImplTest { } @Test + public void testGetNextPageToken_query() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.query("package1", "database1", "", searchSpec, /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test + public void testGetNextPageWithDifferentPackage_query() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.query("package1", "database1", "", searchSpec, /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Try getting next page with the wrong package, package2 + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.getNextPage("package2", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package2\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + + // Can continue getting next page for package1 + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test + public void testGetNextPageToken_globalQuery() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.globalQuery( + /*queryExpression=*/ "", + searchSpec, + "package1", + /*visibilityStore=*/ null, + Process.myUid(), + /*callerHasSystemAccess=*/ false, + /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test + public void testGetNextPageWithDifferentPackage_globalQuery() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.globalQuery( + /*queryExpression=*/ "", + searchSpec, + "package1", + /*visibilityStore=*/ null, + Process.myUid(), + /*callerHasSystemAccess=*/ false, + /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Try getting next page with the wrong package, package2 + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.getNextPage("package2", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package2\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + + // Can continue getting next page for package1 + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test + public void testInvalidateNextPageToken_query() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.query("package1", "database1", "", searchSpec, /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Invalidate the token + mAppSearchImpl.invalidateNextPageToken("package1", nextPageToken); + + // Can't get next page because we invalidated the token. + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.getNextPage("package1", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package1\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + } + + @Test + public void testInvalidateNextPageTokenWithDifferentPackage_query() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.query("package1", "database1", "", searchSpec, /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Try getting next page with the wrong package, package2 + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.invalidateNextPageToken("package2", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package2\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + + // Can continue getting next page for package1 + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test + public void testInvalidateNextPageToken_globalQuery() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.globalQuery( + /*queryExpression=*/ "", + searchSpec, + "package1", + /*visibilityStore=*/ null, + Process.myUid(), + /*callerHasSystemAccess=*/ false, + /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Invalidate the token + mAppSearchImpl.invalidateNextPageToken("package1", nextPageToken); + + // Can't get next page because we invalidated the token. + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.getNextPage("package1", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package1\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + } + + @Test + public void testInvalidateNextPageTokenWithDifferentPackage_globalQuery() throws Exception { + // Insert package1 schema + List<AppSearchSchema> schema1 = + ImmutableList.of(new AppSearchSchema.Builder("schema1").build()); + mAppSearchImpl.setSchema( + "package1", + "database1", + schema1, + /*visibilityStore=*/ null, + /*schemasNotDisplayedBySystem=*/ Collections.emptyList(), + /*schemasVisibleToPackages=*/ Collections.emptyMap(), + /*forceOverride=*/ false, + /*version=*/ 0); + + // Insert two package1 documents + GenericDocument document1 = + new GenericDocument.Builder<>("namespace", "id1", "schema1").build(); + GenericDocument document2 = + new GenericDocument.Builder<>("namespace", "id2", "schema1").build(); + mAppSearchImpl.putDocument("package1", "database1", document1, /*logger=*/ null); + mAppSearchImpl.putDocument("package1", "database1", document2, /*logger=*/ null); + + // Query for only 1 result per page + SearchSpec searchSpec = + new SearchSpec.Builder() + .setTermMatch(TermMatchType.Code.PREFIX_VALUE) + .setResultCountPerPage(1) + .build(); + SearchResultPage searchResultPage = + mAppSearchImpl.globalQuery( + /*queryExpression=*/ "", + searchSpec, + "package1", + /*visibilityStore=*/ null, + Process.myUid(), + /*callerHasSystemAccess=*/ false, + /*logger=*/ null); + + // Document2 will come first because it was inserted last and default return order is + // most recent. + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2); + + long nextPageToken = searchResultPage.getNextPageToken(); + + // Try getting next page with the wrong package, package2 + AppSearchException e = + assertThrows( + AppSearchException.class, + () -> mAppSearchImpl.invalidateNextPageToken("package2", nextPageToken)); + assertThat(e) + .hasMessageThat() + .contains("Package \"package2\" cannot use nextPageToken: " + nextPageToken); + assertThat(e.getResultCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR); + + // Can continue getting next page for package1 + searchResultPage = mAppSearchImpl.getNextPage("package1", nextPageToken); + assertThat(searchResultPage.getResults()).hasSize(1); + assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1); + } + + @Test public void testRemoveEmptyDatabase_noExceptionThrown() throws Exception { SearchSpec searchSpec = new SearchSpec.Builder() @@ -1777,11 +2217,11 @@ public class AppSearchImplTest { assertThrows( IllegalStateException.class, - () -> appSearchImpl.getNextPage(/*nextPageToken=*/ 1L)); + () -> appSearchImpl.getNextPage("package", /*nextPageToken=*/ 1L)); assertThrows( IllegalStateException.class, - () -> appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L)); + () -> appSearchImpl.invalidateNextPageToken("package", /*nextPageToken=*/ 1L)); assertThrows( IllegalStateException.class, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java index 46f96364ff9e..a06a78288535 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java @@ -90,7 +90,8 @@ public class AcquisitionClientTest { @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter callback) { super(context, lazyDaemon, token, callback, 0 /* userId */, "Test", 0 /* cookie */, - TEST_SENSOR_ID /* sensorId */, 0 /* statsModality */, 0 /* statsAction */, + TEST_SENSOR_ID /* sensorId */, true /* shouldVibrate */, 0 /* statsModality */, + 0 /* statsAction */, 0 /* statsClient */); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index 4d1f241787a7..109fb22520c8 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -359,7 +359,7 @@ public class BiometricSchedulerTest { false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */, TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */, 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class), - false /* isKeyguard */); + false /* isKeyguard */, true /* shouldVibrate */); } @Override @@ -382,7 +382,7 @@ public class BiometricSchedulerTest { false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */, TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */, 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class), - false /* isKeyguard */); + false /* isKeyguard */, true /* shouldVibrate */); } @Override diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java index 7243947db944..1ad8850a1921 100644 --- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java @@ -16,6 +16,7 @@ package com.android.server.display; +import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT; @@ -38,6 +39,7 @@ import android.os.Temperature.ThrottlingStatus; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import android.test.mock.MockContentResolver; +import android.util.MathUtils; import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; @@ -90,11 +92,10 @@ public class HighBrightnessModeControllerTest { @Mock IThermalService mThermalServiceMock; @Mock Injector mInjectorMock; + @Mock BrightnessSetting mBrightnessSetting; @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor; - @Mock private BrightnessSetting mBrightnessSetting; - private static final HighBrightnessModeData DEFAULT_HBM_DATA = new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS, TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS, @@ -348,6 +349,105 @@ public class HighBrightnessModeControllerTest { assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode()); } + @Test + public void testHdrRequires50PercentOfScreen() { + final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock()); + + final int layerWidth = DISPLAY_WIDTH; + final int smallLayerHeight = DISPLAY_HEIGHT / 2 - 1; // height to use for <50% + final int largeLayerHeight = DISPLAY_HEIGHT / 2 + 1; // height to use for >50% + + // ensure hdr doesn't turn on if layer is too small + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/, + layerWidth, smallLayerHeight, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode()); + + // Now check with layer larger than 50% + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/, + layerWidth, largeLayerHeight, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode()); + } + + @Test + public void testHdrTrumpsSunlight() { + final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock()); + + // Turn on sunlight + hbmc.setAutoBrightnessEnabled(true); + hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode()); + assertEquals(DEFAULT_MAX, hbmc.getCurrentBrightnessMax(), EPSILON); + + // turn on hdr + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/, + DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode()); + assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON); + } + + @Test + public void testHdrBrightnessLimitSameAsNormalLimit() { + final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock()); + + // Check limit when HBM is off + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/, + DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode()); + assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON); + + // Check limit with HBM is set to HDR + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 0 /*numberOfHdrLayers*/, + DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode()); + assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON); + } + + @Test + public void testHdrBrightnessScaledNormalBrightness() { + final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock()); + + hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/, + DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/); + advanceTime(0); + assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode()); + + // verify things are scaled for 0.5f + float brightness = 0.5f; + float expectedHdrBrightness = MathUtils.map(DEFAULT_MIN, TRANSITION_POINT, + DEFAULT_MIN, DEFAULT_MAX, brightness); // map value from normal range to hdr range + hbmc.onBrightnessChanged(brightness); + advanceTime(0); + assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON); + + // Try another value + brightness = 0.33f; + expectedHdrBrightness = MathUtils.map(DEFAULT_MIN, TRANSITION_POINT, + DEFAULT_MIN, DEFAULT_MAX, brightness); // map value from normal range to hdr range + hbmc.onBrightnessChanged(brightness); + advanceTime(0); + assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON); + + // Try the min value + brightness = DEFAULT_MIN; + expectedHdrBrightness = DEFAULT_MIN; + hbmc.onBrightnessChanged(brightness); + advanceTime(0); + assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON); + + // Try the max value + brightness = TRANSITION_POINT; + expectedHdrBrightness = DEFAULT_MAX; + hbmc.onBrightnessChanged(brightness); + advanceTime(0); + assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON); + } + private void assertState(HighBrightnessModeController hbmc, float brightnessMin, float brightnessMax, int hbmMode) { assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 29f4aa976ef6..22fb76b1fbe5 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -198,6 +198,7 @@ public class PackageManagerSettingsTests { new WatchableTester(settingsUnderTest, "noSuspendingPackage"); watcher.register(); settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1)); + settingsUnderTest.readPackageRestrictionsLPr(0); watcher.verifyChangeReported("put package 1"); // Collect a snapshot at the midway point (package 2 has not been added) final Settings snapshot = settingsUnderTest.snapshot(); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java index 1596483cdbe1..2e5c24c1a95c 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java @@ -246,6 +246,81 @@ public class VibrationThreadTest { } @Test + public void vibrate_singleVibratorRepeatingShortAlwaysOnWaveform_turnsVibratorOnForASecond() + throws Exception { + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + + long vibrationId = 1; + int[] amplitudes = new int[]{1, 2, 3}; + VibrationEffect effect = VibrationEffect.createWaveform( + new long[]{1, 10, 100}, amplitudes, 0); + VibrationThread thread = startThreadAndDispatcher(vibrationId, effect); + + assertTrue(waitUntil(t -> !fakeVibrator.getAmplitudes().isEmpty(), thread, + TEST_TIMEOUT_MILLIS)); + thread.cancel(); + waitForCompletion(thread); + + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating()); + assertEquals(Arrays.asList(expectedOneShot(1000)), fakeVibrator.getEffectSegments()); + } + + @Test + public void vibrate_singleVibratorRepeatingLongAlwaysOnWaveform_turnsVibratorOnForACycle() + throws Exception { + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + + long vibrationId = 1; + int[] amplitudes = new int[]{1, 2, 3}; + VibrationEffect effect = VibrationEffect.createWaveform( + new long[]{5000, 500, 50}, amplitudes, 0); + VibrationThread thread = startThreadAndDispatcher(vibrationId, effect); + + assertTrue(waitUntil(t -> !fakeVibrator.getAmplitudes().isEmpty(), thread, + TEST_TIMEOUT_MILLIS)); + thread.cancel(); + waitForCompletion(thread); + + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating()); + assertEquals(Arrays.asList(expectedOneShot(5550)), fakeVibrator.getEffectSegments()); + } + + + @Test + public void vibrate_singleVibratorRepeatingAlwaysOnWaveform_turnsVibratorBackOn() + throws Exception { + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + + long vibrationId = 1; + int[] amplitudes = new int[]{1, 2}; + VibrationEffect effect = VibrationEffect.createWaveform( + new long[]{900, 50}, amplitudes, 0); + VibrationThread thread = startThreadAndDispatcher(vibrationId, effect); + + assertTrue(waitUntil(t -> fakeVibrator.getAmplitudes().size() > 2 * amplitudes.length, + thread, 1000 + TEST_TIMEOUT_MILLIS)); + thread.cancel(); + waitForCompletion(thread); + + verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED); + assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating()); + assertEquals(2, fakeVibrator.getEffectSegments().size()); + // First time turn vibrator ON for minimum of 1s. + assertEquals(1000L, fakeVibrator.getEffectSegments().get(0).getDuration()); + // Vibrator turns off in the middle of the second execution of first step, turn it back ON + // for another 1s + remaining of 850ms. + assertEquals(1850, fakeVibrator.getEffectSegments().get(1).getDuration(), /* delta= */ 20); + // Set amplitudes for a cycle {1, 2}, start second loop then turn it back on to same value. + assertEquals(expectedAmplitudes(1, 2, 1, 1), + mVibratorProviders.get(VIBRATOR_ID).getAmplitudes().subList(0, 4)); + } + + @Test public void vibrate_singleVibratorPredefinedCancel_cancelsVibrationImmediately() throws Exception { mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index d0bf63a1680f..733d3f0f66ef 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -281,6 +281,34 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertNull(fromXml.pkg); } + @Test + public void testRuleXml_getPkg_nullPkg() throws Exception { + String tag = "tag"; + + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.enabled = true; + rule.configurationActivity = new ComponentName("a", "a"); + + TypedXmlSerializer out = Xml.newFastSerializer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + out.setOutput(new BufferedOutputStream(baos), "utf-8"); + out.startDocument(null, true); + out.startTag(null, tag); + ZenModeConfig.writeRuleXml(rule, out); + out.endTag(null, tag); + out.endDocument(); + + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser); + assertEquals("a", fromXml.getPkg()); + + fromXml.condition = new Condition(Uri.EMPTY, "", Condition.STATE_TRUE); + assertTrue(fromXml.isAutomaticActive()); + } + private ZenModeConfig getMutedRingerConfig() { ZenModeConfig config = new ZenModeConfig(); // Allow alarms, media 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 00dbaf649ca2..4410404b0cd7 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -33,6 +33,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCRE import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +import static android.service.notification.Condition.STATE_TRUE; import static android.util.StatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE; @@ -49,6 +50,7 @@ import static junit.framework.TestCase.assertTrue; import static junit.framework.TestCase.fail; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -64,6 +66,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AutomaticZenRule; @@ -72,7 +76,9 @@ import android.app.NotificationManager.Policy; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.media.AudioAttributes; @@ -81,6 +87,7 @@ import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.VolumePolicy; import android.net.Uri; +import android.os.Binder; import android.os.Process; import android.os.UserHandle; import android.provider.Settings; @@ -105,6 +112,8 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.server.UiServiceTestCase; import com.android.server.notification.ManagedServices.UserProfiles; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -172,8 +181,14 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(), mConditionProviders, mStatsEventBuilderFactory)); + ResolveInfo ri = new ResolveInfo(); + ri.activityInfo = new ActivityInfo(); + when(mPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn( + ImmutableList.of(ri)); when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt())) .thenReturn(CUSTOM_PKG_UID); + when(mPackageManager.getPackagesForUid(anyInt())).thenReturn( + new String[] {getContext().getPackageName()}); mZenModeHelperSpy.mPm = mPackageManager; } @@ -1486,7 +1501,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("android", CountdownConditionProvider.class.getName()); mZenModeHelperSpy.mConfig.manualRule.condition = new Condition(conditionId, "", "", "", 0, - Condition.STATE_TRUE, Condition.FLAG_RELEVANT_NOW); + STATE_TRUE, Condition.FLAG_RELEVANT_NOW); mZenModeHelperSpy.mConfig.manualRule.enabled = true; ZenModeConfig originalConfig = mZenModeHelperSpy.mConfig.copy(); @@ -1592,10 +1607,12 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void testAddAutomaticZenRule() { + public void testAddAutomaticZenRule_CA() { AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, new ComponentName("android", "ScheduleConditionProvider"), ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); @@ -1608,6 +1625,107 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(NotificationManager.zenModeFromInterruptionFilter( zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode); assertEquals(zenRule.getName(), ruleInConfig.name); + assertEquals("android", ruleInConfig.pkg); + } + + @Test + public void testAddAutomaticZenRule_CPS() { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); + + assertTrue(id != null); + ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id); + assertTrue(ruleInConfig != null); + assertEquals(zenRule.isEnabled(), ruleInConfig.enabled); + assertEquals(zenRule.isModified(), ruleInConfig.modified); + assertEquals(zenRule.getConditionId(), ruleInConfig.conditionId); + assertEquals(NotificationManager.zenModeFromInterruptionFilter( + zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode); + assertEquals(zenRule.getName(), ruleInConfig.name); + assertEquals("android", ruleInConfig.pkg); + } + + @Test + public void testSetAutomaticZenRuleState_nullPkg() { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + + String id = mZenModeHelperSpy.addAutomaticZenRule(null, zenRule, "test"); + mZenModeHelperSpy.setAutomaticZenRuleState(zenRule.getConditionId(), + new Condition(zenRule.getConditionId(), "", STATE_TRUE)); + + ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id); + assertEquals(STATE_TRUE, ruleInConfig.condition.state); + } + + @Test + public void testUpdateAutomaticZenRule_nullPkg() { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + + String id = mZenModeHelperSpy.addAutomaticZenRule(null, zenRule, "test"); + + AutomaticZenRule zenRule2 = new AutomaticZenRule("NEW", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + + mZenModeHelperSpy.updateAutomaticZenRule(id, zenRule2, ""); + + ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id); + assertEquals("NEW", ruleInConfig.name); + } + + @Test + public void testRemoveAutomaticZenRule_nullPkg() { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + + String id = mZenModeHelperSpy.addAutomaticZenRule(null, zenRule, "test"); + + assertTrue(id != null); + ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id); + assertTrue(ruleInConfig != null); + assertEquals(zenRule.getName(), ruleInConfig.name); + + mZenModeHelperSpy.removeAutomaticZenRule(id, "test"); + assertNull(mZenModeHelperSpy.mConfig.automaticRules.get(id)); + } + + @Test + public void testRemoveAutomaticZenRules_nullPkg() { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule(null, zenRule, "test"); + + assertTrue(id != null); + ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id); + assertTrue(ruleInConfig != null); + assertEquals(zenRule.getName(), ruleInConfig.name); + + mZenModeHelperSpy.removeAutomaticZenRules(mContext.getPackageName(), "test"); + assertNull(mZenModeHelperSpy.mConfig.automaticRules.get(id)); } @Test @@ -1624,17 +1742,17 @@ public class ZenModeHelperTest extends UiServiceTestCase { NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String id2 = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule2, "test"); - Condition condition = new Condition(sharedUri, "", Condition.STATE_TRUE); + Condition condition = new Condition(sharedUri, "", STATE_TRUE); mZenModeHelperSpy.setAutomaticZenRuleState(sharedUri, condition); for (ZenModeConfig.ZenRule rule : mZenModeHelperSpy.mConfig.automaticRules.values()) { if (rule.id.equals(id)) { assertNotNull(rule.condition); - assertTrue(rule.condition.state == Condition.STATE_TRUE); + assertTrue(rule.condition.state == STATE_TRUE); } if (rule.id.equals(id2)) { assertNotNull(rule.condition); - assertTrue(rule.condition.state == Condition.STATE_TRUE); + assertTrue(rule.condition.state == STATE_TRUE); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index d5628fc9de48..724342b90a53 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -57,6 +57,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl; import android.view.View; @@ -555,6 +556,7 @@ public class DisplayAreaTest extends WindowTestsBase { final DisplayArea<WindowContainer> displayArea = new DisplayArea<>( mWm, BELOW_TASKS, "NewArea", FEATURE_VENDOR_FIRST); final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class); + doReturn(mock(IBinder.class)).when(mockDisplayAreaOrganizer).asBinder(); displayArea.mOrganizer = mockDisplayAreaOrganizer; spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController); mDisplayContent.addChild(displayArea, 0); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 9954de2da67e..f01519f934f3 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -286,6 +286,21 @@ public class CarrierConfigManager { "call_barring_default_service_class_int"; /** + * This carrier supports dialing USSD codes to enable/disable supplementary services such as + * call forwarding and call waiting over CDMA. + * <p> + * The supplementary service menu will still need to be set as visible, see + * {@link #KEY_CALL_FORWARDING_VISIBILITY_BOOL} and + * {@link #KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL}. + * <p> + * If this is set as false and the supplementary service menu is visible, the associated setting + * will be enabled and disabled based on the availability of supplementary services over UT. See + * {@link #KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL}. + * @hide + */ + public static final String KEY_SUPPORT_SS_OVER_CDMA_BOOL = "support_ss_over_cdma_bool"; + + /** * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED * events from the Sim. * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and @@ -5120,6 +5135,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true); sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true); sDefaults.putInt(KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT, SERVICE_CLASS_VOICE); + sDefaults.putBoolean(KEY_SUPPORT_SS_OVER_CDMA_BOOL, false); sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL, true); sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNANSWERED_SUPPORTED_BOOL, true); diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index b7a6d0ff7607..7c7dc4d79e9a 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -23,6 +23,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; @@ -50,6 +51,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; 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 android.annotation.NonNull; @@ -99,6 +101,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import java.io.FileNotFoundException; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -227,6 +230,7 @@ public class VcnManagementServiceTest { setupMockedCarrierPrivilege(true); mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps); + setupActiveSubscription(TEST_UUID_1); doReturn(mMockIBinder).when(mMockPolicyListener).asBinder(); doReturn(mMockIBinder).when(mMockStatusCallback).asBinder(); @@ -300,23 +304,65 @@ public class VcnManagementServiceTest { } private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( - Set<ParcelUuid> activeSubscriptionGroups) { + ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups) { return triggerSubscriptionTrackerCbAndGetSnapshot( - activeSubscriptionGroups, Collections.emptyMap()); + activeDataSubGrp, activeSubscriptionGroups, Collections.emptyMap()); } private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( - Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap) { + ParcelUuid activeDataSubGrp, + Set<ParcelUuid> activeSubscriptionGroups, + Map<Integer, ParcelUuid> subIdToGroupMap) { + return triggerSubscriptionTrackerCbAndGetSnapshot( + activeDataSubGrp, + activeSubscriptionGroups, + subIdToGroupMap, + true /* hasCarrierPrivileges */); + } + + private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( + ParcelUuid activeDataSubGrp, + Set<ParcelUuid> activeSubscriptionGroups, + Map<Integer, ParcelUuid> subIdToGroupMap, + boolean hasCarrierPrivileges) { return triggerSubscriptionTrackerCbAndGetSnapshot( - activeSubscriptionGroups, subIdToGroupMap, true /* hasCarrierPrivileges */); + TEST_SUBSCRIPTION_ID, + activeDataSubGrp, + activeSubscriptionGroups, + subIdToGroupMap, + hasCarrierPrivileges); } private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( + int activeDataSubId, + ParcelUuid activeDataSubGrp, + Set<ParcelUuid> activeSubscriptionGroups, + Map<Integer, ParcelUuid> subIdToGroupMap, + boolean hasCarrierPrivileges) { + final TelephonySubscriptionSnapshot snapshot = + buildSubscriptionSnapshot( + activeDataSubId, + activeDataSubGrp, + activeSubscriptionGroups, + subIdToGroupMap, + hasCarrierPrivileges); + + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); + cb.onNewSnapshot(snapshot); + + return snapshot; + } + + private TelephonySubscriptionSnapshot buildSubscriptionSnapshot( + int activeDataSubId, + ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap, boolean hasCarrierPrivileges) { final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class); doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups(); + doReturn(activeDataSubGrp).when(snapshot).getActiveDataSubscriptionGroup(); + doReturn(activeDataSubId).when(snapshot).getActiveDataSubscriptionId(); final Set<String> privilegedPackages = (activeSubscriptionGroups == null || activeSubscriptionGroups.isEmpty()) @@ -343,12 +389,19 @@ public class VcnManagementServiceTest { return subIds; }).when(snapshot).getAllSubIdsInGroup(any()); - final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); - cb.onNewSnapshot(snapshot); - return snapshot; } + private void setupActiveSubscription(ParcelUuid activeDataSubGrp) { + mVcnMgmtSvc.setLastSnapshot( + buildSubscriptionSnapshot( + TEST_SUBSCRIPTION_ID, + activeDataSubGrp, + Collections.emptySet(), + Collections.emptyMap(), + true /* hasCarrierPrivileges */)); + } + private TelephonySubscriptionTrackerCallback getTelephonySubscriptionTrackerCallback() { final ArgumentCaptor<TelephonySubscriptionTrackerCallback> captor = ArgumentCaptor.forClass(TelephonySubscriptionTrackerCallback.class); @@ -372,25 +425,56 @@ public class VcnManagementServiceTest { @Test public void testTelephonyNetworkTrackerCallbackStartsInstances() throws Exception { + // Add a record for a non-active SIM + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + TelephonySubscriptionSnapshot snapshot = - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_1, new ArraySet<>(Arrays.asList(TEST_UUID_1, TEST_UUID_2))); verify(mMockDeps) .newVcnContext( eq(mMockContext), eq(mTestLooper.getLooper()), any(VcnNetworkProvider.class), anyBoolean()); + + // Verify that only the VCN for the active data SIM was started. verify(mMockDeps) .newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any()); + verify(mMockDeps, never()) + .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), eq(snapshot), any()); + } + + @Test + public void testTelephonyNetworkTrackerCallbackSwitchingActiveDataStartsAndStopsInstances() + throws Exception { + // Add a record for a non-active SIM + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + final Vcn vcn = startAndGetVcnInstance(TEST_UUID_1); + + TelephonySubscriptionSnapshot snapshot = + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_2, new ArraySet<>(Arrays.asList(TEST_UUID_1, TEST_UUID_2))); + + // Verify that a new VCN for UUID_2 was started, and the old instance was torn down + // immediately + verify(mMockDeps) + .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), eq(snapshot), any()); + verify(vcn).teardownAsynchronously(); + assertEquals(1, mVcnMgmtSvc.getAllVcns().size()); + assertFalse(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_1)); + assertTrue(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_2)); } @Test public void testTelephonyNetworkTrackerCallbackStopsInstances() throws Exception { + setupActiveSubscription(TEST_UUID_2); + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet()); + triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); // Verify teardown after delay mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); @@ -400,19 +484,76 @@ public class VcnManagementServiceTest { } @Test + public void testTelephonyNetworkTrackerCallbackSwitchToNewSubscriptionImmediatelyTearsDown() + throws Exception { + setupActiveSubscription(TEST_UUID_2); + + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); + final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); + + // Simulate switch to different default data subscription that does not have a VCN. + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_SUBSCRIPTION_ID, + null /* activeDataSubscriptionGroup */, + Collections.emptySet(), + Collections.emptyMap(), + false /* hasCarrierPrivileges */); + mTestLooper.dispatchAll(); + + verify(vcn).teardownAsynchronously(); + assertEquals(0, mVcnMgmtSvc.getAllVcns().size()); + } + + /** + * Tests an intermediate state where carrier privileges are marked as lost before active data + * subId changes during a SIM ejection. + * + * <p>The expected outcome is that the VCN is torn down after a delay, as opposed to + * immediately. + */ + @Test + public void testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges() + throws Exception { + setupActiveSubscription(TEST_UUID_2); + + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); + final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); + + // Simulate privileges lost + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_SUBSCRIPTION_ID, + TEST_UUID_2, + Collections.emptySet(), + Collections.emptyMap(), + false /* hasCarrierPrivileges */); + + // Verify teardown after delay + mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); + mTestLooper.dispatchAll(); + verify(vcn).teardownAsynchronously(); + } + + @Test public void testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances() throws Exception { + setupActiveSubscription(TEST_UUID_2); + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); // Simulate SIM unloaded - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet()); + triggerSubscriptionTrackerCbAndGetSnapshot( + INVALID_SUBSCRIPTION_ID, + null /* activeDataSubscriptionGroup */, + Collections.emptySet(), + Collections.emptyMap(), + false /* hasCarrierPrivileges */); // Simulate new SIM loaded right during teardown delay. mTestLooper.moveTimeForward( VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); mTestLooper.dispatchAll(); - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2)); + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); // Verify that even after the full timeout duration, the VCN instance is not torn down mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); @@ -422,11 +563,13 @@ public class VcnManagementServiceTest { @Test public void testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances() throws Exception { + setupActiveSubscription(TEST_UUID_2); + final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2); // Simulate SIM unloaded - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet()); + triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); // Config cleared, SIM reloaded & config re-added right before teardown delay, staring new // vcnInstance. @@ -434,6 +577,7 @@ public class VcnManagementServiceTest { VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); mTestLooper.dispatchAll(); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2); // Verify that new instance was different, and the old one was torn down @@ -538,6 +682,31 @@ public class VcnManagementServiceTest { } @Test + public void testSetVcnConfigNonActiveSimDoesNotStartVcn() throws Exception { + // Use a different UUID to simulate a new VCN config. + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2)); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + + verify(mMockDeps, never()).newVcn(any(), any(), any(), any(), any()); + } + + @Test + public void testSetVcnConfigActiveSimTearsDownExistingVcnsImmediately() throws Exception { + final Vcn vcn = startAndGetVcnInstance(TEST_UUID_1); + + // Use a different UUID to simulate a new VCN config. + setupActiveSubscription(TEST_UUID_2); + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + + verify(mMockDeps, times(2)).newVcn(any(), any(), any(), any(), any()); + verify(vcn).teardownAsynchronously(); + assertEquals(1, mVcnMgmtSvc.getAllVcns().size()); + assertFalse(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_1)); + assertTrue(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_2)); + } + + @Test public void testSetVcnConfigTestModeRequiresPermission() throws Exception { doThrow(new SecurityException("Requires MANAGE_TEST_NETWORKS")) .when(mMockContext) @@ -561,7 +730,7 @@ public class VcnManagementServiceTest { @Test public void testSetVcnConfigNotifiesStatusCallback() throws Exception { - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2)); + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); @@ -635,7 +804,9 @@ public class VcnManagementServiceTest { } @Test - public void testSetVcnConfigClearVcnConfigStartsUpdatesAndTeardsDownVcns() throws Exception { + public void testSetVcnConfigClearVcnConfigStartsUpdatesAndTearsDownVcns() throws Exception { + setupActiveSubscription(TEST_UUID_2); + // Use a different UUID to simulate a new VCN config. mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); final Map<ParcelUuid, Vcn> vcnInstances = mVcnMgmtSvc.getAllVcns(); @@ -646,12 +817,7 @@ public class VcnManagementServiceTest { // Verify Vcn is started verify(mMockDeps) - .newVcn( - eq(mVcnContext), - eq(TEST_UUID_2), - eq(TEST_VCN_CONFIG), - eq(TelephonySubscriptionSnapshot.EMPTY_SNAPSHOT), - any()); + .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), any(), any()); // Verify Vcn is updated if it was previously started mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); @@ -693,7 +859,7 @@ public class VcnManagementServiceTest { // Assert that if both UUID 1 and 2 are provisioned, the caller only gets ones that they are // privileged for. - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); final List<ParcelUuid> subGrps = mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); assertEquals(Collections.singletonList(TEST_UUID_1), subGrps); @@ -760,6 +926,7 @@ public class VcnManagementServiceTest { int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) { mVcnMgmtSvc.systemReady(); triggerSubscriptionTrackerCbAndGetSnapshot( + subGrp, Collections.singleton(subGrp), Collections.singletonMap(subId, subGrp), hasCarrierPrivileges); @@ -927,18 +1094,23 @@ public class VcnManagementServiceTest { @Test public void testSubscriptionSnapshotUpdateNotifiesVcn() { + setupActiveSubscription(TEST_UUID_2); + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); final Map<ParcelUuid, Vcn> vcnInstances = mVcnMgmtSvc.getAllVcns(); final Vcn vcnInstance = vcnInstances.get(TEST_UUID_2); TelephonySubscriptionSnapshot snapshot = - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2)); + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_2, Collections.singleton(TEST_UUID_2)); verify(vcnInstance).updateSubscriptionSnapshot(eq(snapshot)); } @Test public void testAddNewVcnUpdatesPolicyListener() throws Exception { + setupActiveSubscription(TEST_UUID_2); + mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); @@ -948,6 +1120,8 @@ public class VcnManagementServiceTest { @Test public void testRemoveVcnUpdatesPolicyListener() throws Exception { + setupActiveSubscription(TEST_UUID_2); + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); @@ -958,10 +1132,13 @@ public class VcnManagementServiceTest { @Test public void testVcnSubIdChangeUpdatesPolicyListener() throws Exception { + setupActiveSubscription(TEST_UUID_2); + startAndGetVcnInstance(TEST_UUID_2); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_2, Collections.singleton(TEST_UUID_2), Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_2)); @@ -988,7 +1165,8 @@ public class VcnManagementServiceTest { private void verifyVcnSafeModeChangesNotifiesPolicyListeners(boolean enterSafeMode) throws Exception { TelephonySubscriptionSnapshot snapshot = - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_1, Collections.singleton(TEST_UUID_1)); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); @@ -1014,7 +1192,8 @@ public class VcnManagementServiceTest { boolean hasPermissionsforSubGroup) throws Exception { TelephonySubscriptionSnapshot snapshot = - triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup)); + triggerSubscriptionTrackerCbAndGetSnapshot( + subGroup, Collections.singleton(subGroup)); setupSubscriptionAndStartVcn( TEST_SUBSCRIPTION_ID, subGroup, true /* isActive */, hasPermissionsforSubGroup); @@ -1089,6 +1268,7 @@ public class VcnManagementServiceTest { // timeout so the VCN goes inactive. final TelephonySubscriptionSnapshot snapshot = triggerSubscriptionTrackerCbAndGetSnapshot( + TEST_UUID_1, Collections.singleton(TEST_UUID_1), Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1), false /* hasCarrierPrivileges */); diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java index ca7463884d3a..1f0df62fe72c 100644 --- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java @@ -21,6 +21,7 @@ import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX; import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; +import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; @@ -54,6 +55,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.ArraySet; @@ -178,6 +180,14 @@ public class TelephonySubscriptionTrackerTest { return captor.getValue(); } + private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() { + final ArgumentCaptor<TelephonyCallback> captor = + ArgumentCaptor.forClass(TelephonyCallback.class); + verify(mTelephonyManager).registerTelephonyCallback(any(), captor.capture()); + + return (ActiveDataSubscriptionIdListener) captor.getValue(); + } + private Intent buildTestBroadcastIntent(boolean hasValidSubscription) { Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED); intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX); @@ -196,7 +206,14 @@ public class TelephonySubscriptionTrackerTest { private TelephonySubscriptionSnapshot buildExpectedSnapshot( Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages) { - return new TelephonySubscriptionSnapshot(subIdToInfoMap, privilegedPackages); + return new TelephonySubscriptionSnapshot(0, subIdToInfoMap, privilegedPackages); + } + + private TelephonySubscriptionSnapshot buildExpectedSnapshot( + int activeSubId, + Map<Integer, SubscriptionInfo> subIdToInfoMap, + Map<ParcelUuid, Set<String>> privilegedPackages) { + return new TelephonySubscriptionSnapshot(activeSubId, subIdToInfoMap, privilegedPackages); } private void verifyNoActiveSubscriptions() { @@ -250,6 +267,26 @@ public class TelephonySubscriptionTrackerTest { } @Test + public void testOnSubscriptionsChangedFired_onActiveSubIdsChanged() throws Exception { + setupReadySubIds(); + setPrivilegedPackagesForMock(Collections.emptyList()); + + doReturn(TEST_SUBSCRIPTION_ID_2).when(mDeps).getActiveDataSubscriptionId(); + final ActiveDataSubscriptionIdListener listener = getActiveDataSubscriptionIdListener(); + listener.onActiveDataSubscriptionIdChanged(TEST_SUBSCRIPTION_ID_2); + mTestLooper.dispatchAll(); + + ArgumentCaptor<TelephonySubscriptionSnapshot> snapshotCaptor = + ArgumentCaptor.forClass(TelephonySubscriptionSnapshot.class); + verify(mCallback).onNewSnapshot(snapshotCaptor.capture()); + + TelephonySubscriptionSnapshot snapshot = snapshotCaptor.getValue(); + assertNotNull(snapshot); + assertEquals(TEST_SUBSCRIPTION_ID_2, snapshot.getActiveDataSubscriptionId()); + assertEquals(TEST_PARCEL_UUID, snapshot.getActiveDataSubscriptionGroup()); + } + + @Test public void testOnSubscriptionsChangedFired_WithReadySubidsNoPrivilegedPackages() throws Exception { setupReadySubIds(); @@ -371,7 +408,8 @@ public class TelephonySubscriptionTrackerTest { @Test public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception { final TelephonySubscriptionSnapshot snapshot = - new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap()); + new TelephonySubscriptionSnapshot( + TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap()); assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1)); assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2)); @@ -380,7 +418,8 @@ public class TelephonySubscriptionTrackerTest { @Test public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception { final TelephonySubscriptionSnapshot snapshot = - new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap()); + new TelephonySubscriptionSnapshot( + TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap()); assertEquals( new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)), diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index b97023a95d72..a696b3ae28f7 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -127,7 +127,9 @@ public class VcnGatewayConnectionTestBase { protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT = new TelephonySubscriptionSnapshot( - Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), Collections.EMPTY_MAP); + TEST_SUB_ID, + Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), + Collections.EMPTY_MAP); @NonNull protected final Context mContext; @NonNull protected final TestLooper mTestLooper; |