diff options
92 files changed, 1063 insertions, 378 deletions
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/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/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/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/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/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/res/res/layout/notification_template_conversation_header.xml b/core/res/res/layout/notification_template_conversation_header.xml index 389637eb2517..2faff412565e 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" @@ -119,6 +119,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" @@ -171,4 +172,4 @@ 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-bn/strings.xml b/core/res/res/values-bn/strings.xml index 47bcbe189570..7ea226b2b261 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> 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-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-kn/strings.xml b/core/res/res/values-kn/strings.xml index a7d6ae0d1fbe..0a121539c5a9 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -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-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-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-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/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/Shell/res/values-ta/strings.xml b/packages/Shell/res/values-ta/strings.xml index a906abede3fd..30d087368d40 100644 --- a/packages/Shell/res/values-ta/strings.xml +++ b/packages/Shell/res/values-ta/strings.xml @@ -32,7 +32,7 @@ <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/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 1f817d35b46d..8505a6254b28 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -34,6 +34,8 @@ import com.android.wm.shell.startingsurface.SplashscreenContentDrawer import com.android.wm.shell.startingsurface.StartingSurface 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. @@ -43,8 +45,6 @@ class ActivityLaunchAnimator( private val startingSurface: StartingSurface?, 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 @@ -233,11 +233,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) } } 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/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/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 452164f2e42a..54790897af76 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -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-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 540be62d0f78..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> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 4a5941e38828..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> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 6e032efb2083..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> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 9ae4721d8aa0..abbb46a5e451 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> 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-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 94df302a007b..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> 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-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 6b68297dea71..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> 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..2e6f01b515e3 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/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-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-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..708462f94553 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> 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-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 53500b5d8b1e..9fd91f191837 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/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-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-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-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 2d1500965136..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> 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-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ea79e3c94840..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> @@ -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> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 9bed6001e3de..7485ef858620 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -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/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/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 e51baed065ef..ab3e042e9da7 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; @@ -47,8 +45,6 @@ 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; @@ -160,16 +156,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 @@ -437,7 +425,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); @@ -552,18 +539,7 @@ 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(EFFECT_CLICK, VIBRATION_SONIFICATION_ATTRIBUTES); } } @@ -698,7 +674,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); } @@ -853,6 +830,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); @@ -880,38 +860,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/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index c33f4fa8dee4..c7c25903923a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2311,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/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 35115144cc05..a16b92f494a4 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -181,6 +181,7 @@ public class PeopleTileViewHelper { private int mWidth; private int mHeight; private int mLayoutSize; + private boolean mIsLeftToRight; private Locale mLocale; private NumberFormat mIntegerFormat; @@ -195,6 +196,8 @@ public class PeopleTileViewHelper { mWidth = width; mHeight = height; mLayoutSize = getLayoutSize(); + mIsLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) + == View.LAYOUT_DIRECTION_LTR; } /** @@ -659,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); @@ -678,6 +681,17 @@ 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())); @@ -717,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())); @@ -803,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 @@ -913,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); } @@ -1117,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/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/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/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/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/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index b18dfd2866c4..bbaf65a399a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -807,7 +807,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/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 01f1f9dc44f4..694b84a0b949 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 @@ -26,6 +28,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 @@ -38,7 +41,6 @@ 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) @@ -49,6 +51,7 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { @Spy private val controller = TestLaunchAnimatorController(launchContainer) @Mock lateinit var iCallback: IRemoteAnimationFinishedCallback @Mock lateinit var startingSurface: StartingSurface + @Mock lateinit var failHandler: Log.TerribleFailureHandler private lateinit var activityLaunchAnimator: ActivityLaunchAnimator @get:Rule val rule = MockitoJUnit.rule() @@ -177,6 +180,13 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { 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/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/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/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4ec5559a061d..59ebbf1f0c4e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -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/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index ca357b4c2cec..f11fe8aee64f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -188,18 +188,7 @@ 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); @@ -207,9 +196,6 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement } protected final void vibrateError() { - if (!errorHapticsEnabled()) { - return; - } Vibrator vibrator = getContext().getSystemService(Vibrator.class); if (vibrator != null) { vibrator.vibrate(ERROR_VIBRATION_EFFECT, VIBRATION_SONIFICATION_ATTRIBUTES); 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..3757404d226d 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; @@ -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/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 6c0adafcf2ee..c3de7aa74d15 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; @@ -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/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 6a05ed470123..19134e46f08f 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; @@ -30,7 +29,6 @@ import android.hardware.biometrics.fingerprint.ISession; 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 +55,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, @@ -74,10 +69,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp lockoutCache, allowBackgroundAuthentication); mLockoutCache = lockoutCache; mUdfpsOverlayController = udfpsOverlayController; - - mContentResolver = context.getContentResolver(); - mCustomHaptics = Settings.Global.getInt(mContentResolver, - "fp_custom_success_error", 0) == 1; } @NonNull @@ -213,18 +204,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/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/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/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/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/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); } } |