diff options
183 files changed, 3333 insertions, 909 deletions
diff --git a/Android.bp b/Android.bp index ee3cb8fad9e7..35c7b1bc6fdd 100644 --- a/Android.bp +++ b/Android.bp @@ -502,7 +502,6 @@ java_library { sdk_version: "core_platform", static_libs: [ "libphonenumber-platform", - "nist-sip", "tagsoup", "rappor", "libtextclassifier-java", diff --git a/CleanSpec.mk b/CleanSpec.mk index f311fc81fc10..6a909c0364e9 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -253,6 +253,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DynamicAndroidInstallationService) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DefaultContainerService) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar) # ****************************************************************** # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER # ****************************************************************** diff --git a/api/current.txt b/api/current.txt index 26c90dff3c6b..2e099ed8e2a2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7216,18 +7216,18 @@ package android.app.assist { method @Nullable public android.view.autofill.AutofillValue getAutofillValue(); method public android.app.assist.AssistStructure.ViewNode getChildAt(int); method public int getChildCount(); - method public String getClassName(); - method public CharSequence getContentDescription(); + method @Nullable public String getClassName(); + method @Nullable public CharSequence getContentDescription(); method public float getElevation(); - method public android.os.Bundle getExtras(); + method @Nullable public android.os.Bundle getExtras(); method public int getHeight(); - method public String getHint(); + method @Nullable public String getHint(); method @Nullable public String getHintIdEntry(); method @Nullable public android.view.ViewStructure.HtmlInfo getHtmlInfo(); method public int getId(); - method public String getIdEntry(); - method public String getIdPackage(); - method public String getIdType(); + method @Nullable public String getIdEntry(); + method @Nullable public String getIdPackage(); + method @Nullable public String getIdType(); method public int getImportantForAutofill(); method public int getInputType(); method public int getLeft(); @@ -7237,12 +7237,12 @@ package android.app.assist { method public int getMinTextEms(); method public int getScrollX(); method public int getScrollY(); - method public CharSequence getText(); + method @Nullable public CharSequence getText(); method public int getTextBackgroundColor(); method public int getTextColor(); method @Nullable public String getTextIdEntry(); - method public int[] getTextLineBaselines(); - method public int[] getTextLineCharOffsets(); + method @Nullable public int[] getTextLineBaselines(); + method @Nullable public int[] getTextLineCharOffsets(); method public int getTextSelectionEnd(); method public int getTextSelectionStart(); method public float getTextSize(); @@ -7878,6 +7878,7 @@ package android.appwidget { method public void deleteAppWidgetId(int); method public void deleteHost(); method public int[] getAppWidgetIds(); + method public void onAppWidgetRemoved(int); method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo); method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo); method protected void onProvidersChanged(); @@ -16906,9 +16907,10 @@ package android.hardware.camera2 { method @NonNull public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(@NonNull android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException; method public abstract void createReprocessableCaptureSession(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.view.Surface>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException; method public abstract void createReprocessableCaptureSessionByConfigurations(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public int getCameraAudioRestriction() throws android.hardware.camera2.CameraAccessException; method @NonNull public abstract String getId(); method public boolean isSessionConfigurationSupported(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException; - method public int setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException; + method public void setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException; field public static final int AUDIO_RESTRICTION_NONE = 0; // 0x0 field public static final int AUDIO_RESTRICTION_VIBRATION = 1; // 0x1 field public static final int AUDIO_RESTRICTION_VIBRATION_SOUND = 3; // 0x3 @@ -50447,6 +50449,7 @@ package android.view { method public final int getScrollY(); method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor(); method @LayoutRes public int getSourceLayoutResId(); + method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription(); method public android.animation.StateListAnimator getStateListAnimator(); method protected int getSuggestedMinimumHeight(); method protected int getSuggestedMinimumWidth(); @@ -50791,6 +50794,7 @@ package android.view { method public void setScrollbarFadingEnabled(boolean); method public void setSelected(boolean); method public void setSoundEffectsEnabled(boolean); + method public void setStateDescription(@Nullable CharSequence); method public void setStateListAnimator(android.animation.StateListAnimator); method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>); method public void setSystemUiVisibility(int); @@ -52145,6 +52149,7 @@ package android.view.accessibility { field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10 field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20 field public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 8; // 0x8 + field public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 64; // 0x40 field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1 field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2 field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0 @@ -52262,6 +52267,7 @@ package android.view.accessibility { method @Nullable public CharSequence getPaneTitle(); method public android.view.accessibility.AccessibilityNodeInfo getParent(); method public android.view.accessibility.AccessibilityNodeInfo.RangeInfo getRangeInfo(); + method @Nullable public CharSequence getStateDescription(); method public CharSequence getText(); method public int getTextSelectionEnd(); method public int getTextSelectionStart(); @@ -52353,6 +52359,7 @@ package android.view.accessibility { method public void setShowingHintText(boolean); method public void setSource(android.view.View); method public void setSource(android.view.View, int); + method public void setStateDescription(@Nullable CharSequence); method public void setText(CharSequence); method public void setTextEntryKey(boolean); method public void setTextSelection(int, int); diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index f92502370566..8be95e4659b4 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -22,7 +22,6 @@ cc_binary { "libcutils", "libdl", "libhidlbase", - "libhwbinder", "liblog", "libnativeloader", "libutils", diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index ae751ce6d7ab..fe3c3d5da6df 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -4094,9 +4094,13 @@ message ProcessMemoryHighWaterMark { // Provided by ActivityManagerService or read from /proc/PID/cmdline. optional string process_name = 2; + // Deprecated: use rss_high_water_mark_in_kilobytes instead. This field is + // computed by converting kilobytes to bytes. + optional int64 rss_high_water_mark_in_bytes = 3 [deprecated = true]; + // RSS high-water mark. Peak RSS usage of the process. Read from the VmHWM field in // /proc/PID/status. - optional int64 rss_high_water_mark_in_bytes = 3; + optional int32 rss_high_water_mark_in_kilobytes = 4; } /* diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 15c642571bc6..bf7d6324764f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -146,6 +146,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -945,6 +946,10 @@ public class Activity extends ContextThemeWrapper /** @hide */ boolean mEnterAnimationComplete; + /** Track last dispatched multi-window and PiP mode to client, internal debug purpose **/ + private Boolean mLastDispatchedIsInMultiWindowMode; + private Boolean mLastDispatchedIsInPictureInPictureMode; + private static native String getDlWarning(); /** Return the intent that started this activity. */ @@ -3646,6 +3651,22 @@ public class Activity extends ContextThemeWrapper return false; } + private static final class RequestFinishCallback extends IRequestFinishCallback.Stub { + private final WeakReference<Activity> mActivityRef; + + RequestFinishCallback(WeakReference<Activity> activityRef) { + mActivityRef = activityRef; + } + + @Override + public void requestFinish() { + Activity activity = mActivityRef.get(); + if (activity != null) { + activity.mHandler.post(activity::finishAfterTransition); + } + } + } + /** * Called when the activity has detected the user's press of the back * key. The default implementation simply finishes the current activity, @@ -3671,11 +3692,7 @@ public class Activity extends ContextThemeWrapper // while at the root of the task. This call allows ActivityTaskManager // to intercept or defer finishing. ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken, - new IRequestFinishCallback.Stub() { - public void requestFinish() { - mHandler.post(() -> finishAfterTransition()); - } - }); + new RequestFinishCallback(new WeakReference<>(this))); } catch (RemoteException e) { finishAfterTransition(); } @@ -6990,6 +7007,10 @@ public class Activity extends ContextThemeWrapper writer.print(mResumed); writer.print(" mStopped="); writer.print(mStopped); writer.print(" mFinished="); writer.println(mFinished); + writer.print(innerPrefix); writer.print("mLastDispatchedIsInMultiWindowMode="); + writer.print(mLastDispatchedIsInMultiWindowMode); + writer.print(" mLastDispatchedIsInPictureInPictureMode="); + writer.println(mLastDispatchedIsInPictureInPictureMode); writer.print(innerPrefix); writer.print("mChangingConfigurations="); writer.println(mChangingConfigurations); writer.print(innerPrefix); writer.print("mCurrentConfig="); @@ -8071,6 +8092,7 @@ public class Activity extends ContextThemeWrapper if (mWindow != null) { mWindow.onMultiWindowModeChanged(); } + mLastDispatchedIsInMultiWindowMode = isInMultiWindowMode; onMultiWindowModeChanged(isInMultiWindowMode, newConfig); } @@ -8083,6 +8105,7 @@ public class Activity extends ContextThemeWrapper if (mWindow != null) { mWindow.onPictureInPictureModeChanged(isInPictureInPictureMode); } + mLastDispatchedIsInPictureInPictureMode = isInPictureInPictureMode; onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); } diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 86e768db3c52..f9e710e118ea 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -1080,6 +1080,7 @@ public class AssistStructure implements Parcelable { * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} * for more information. */ + @Nullable public String getIdPackage() { return mIdPackage; } @@ -1089,6 +1090,7 @@ public class AssistStructure implements Parcelable { * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} * for more information. */ + @Nullable public String getIdType() { return mIdType; } @@ -1098,6 +1100,7 @@ public class AssistStructure implements Parcelable { * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} * for more information. */ + @Nullable public String getIdEntry() { return mIdEntry; } @@ -1391,6 +1394,7 @@ public class AssistStructure implements Parcelable { * For example, a button will report "android.widget.Button" meaning it behaves * like a {@link android.widget.Button}. */ + @Nullable public String getClassName() { return mClassName; } @@ -1399,6 +1403,7 @@ public class AssistStructure implements Parcelable { * Returns any content description associated with the node, which semantically describes * its purpose for accessibility and other uses. */ + @Nullable public CharSequence getContentDescription() { return mContentDescription; } @@ -1473,6 +1478,7 @@ public class AssistStructure implements Parcelable { * Returns any text associated with the node that is displayed to the user, or null * if there is none. */ + @Nullable public CharSequence getText() { return mText != null ? mText.mText : null; } @@ -1560,6 +1566,7 @@ public class AssistStructure implements Parcelable { * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes, * not for autofill purposes. */ + @Nullable public int[] getTextLineCharOffsets() { return mText != null ? mText.mLineCharOffsets : null; } @@ -1573,6 +1580,7 @@ public class AssistStructure implements Parcelable { * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes, * not for autofill purposes. */ + @Nullable public int[] getTextLineBaselines() { return mText != null ? mText.mLineBaselines : null; } @@ -1592,6 +1600,7 @@ public class AssistStructure implements Parcelable { * Return additional hint text associated with the node; this is typically used with * a node that takes user input, describing to the user what the input means. */ + @Nullable public String getHint() { return mText != null ? mText.mHint : null; } @@ -1610,6 +1619,7 @@ public class AssistStructure implements Parcelable { /** * Return a Bundle containing optional vendor-specific extension information. */ + @Nullable public Bundle getExtras() { return mExtras; } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index f003d4bea028..c20cb253a6be 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -56,6 +56,7 @@ public class AppWidgetHost { static final int HANDLE_PROVIDERS_CHANGED = 3; @UnsupportedAppUsage static final int HANDLE_VIEW_DATA_CHANGED = 4; + static final int HANDLE_APP_WIDGET_REMOVED = 5; final static Object sServiceLock = new Object(); @UnsupportedAppUsage @@ -103,6 +104,14 @@ public class AppWidgetHost { msg.sendToTarget(); } + public void appWidgetRemoved(int appWidgetId) { + Handler handler = mWeakHandler.get(); + if (handler == null) { + return; + } + handler.obtainMessage(HANDLE_APP_WIDGET_REMOVED, appWidgetId, 0).sendToTarget(); + } + public void providersChanged() { Handler handler = mWeakHandler.get(); if (handler == null) { @@ -137,6 +146,10 @@ public class AppWidgetHost { updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj); break; } + case HANDLE_APP_WIDGET_REMOVED: { + dispatchOnAppWidgetRemoved(msg.arg1); + break; + } case HANDLE_PROVIDER_CHANGED: { onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj); break; @@ -224,6 +237,10 @@ public class AppWidgetHost { break; case PendingHostUpdate.TYPE_VIEW_DATA_CHANGED: viewDataChanged(update.appWidgetId, update.viewId); + break; + case PendingHostUpdate.TYPE_APP_WIDGET_REMOVED: + dispatchOnAppWidgetRemoved(update.appWidgetId); + break; } } } @@ -426,6 +443,21 @@ public class AppWidgetHost { } } + void dispatchOnAppWidgetRemoved(int appWidgetId) { + synchronized (mViews) { + mViews.remove(appWidgetId); + } + onAppWidgetRemoved(appWidgetId); + } + + /** + * Called when the app widget is removed for appWidgetId + * @param appWidgetId + */ + public void onAppWidgetRemoved(int appWidgetId) { + // Does nothing + } + /** * Called when the set of available widgets changes (ie. widget containing packages * are added, updated or removed, or widget components are enabled or disabled.) diff --git a/core/java/android/appwidget/PendingHostUpdate.java b/core/java/android/appwidget/PendingHostUpdate.java index e1bf159ccd84..1f1d64494417 100644 --- a/core/java/android/appwidget/PendingHostUpdate.java +++ b/core/java/android/appwidget/PendingHostUpdate.java @@ -28,6 +28,7 @@ public class PendingHostUpdate implements Parcelable { static final int TYPE_VIEWS_UPDATE = 0; static final int TYPE_PROVIDER_CHANGED = 1; static final int TYPE_VIEW_DATA_CHANGED = 2; + static final int TYPE_APP_WIDGET_REMOVED = 3; final int appWidgetId; final int type; @@ -53,6 +54,13 @@ public class PendingHostUpdate implements Parcelable { return update; } + /** + * IAppWidgetHost appWidgetRemoved implimentaion + */ + public static PendingHostUpdate appWidgetRemoved(int appWidgetId) { + return new PendingHostUpdate(appWidgetId, TYPE_APP_WIDGET_REMOVED); + } + private PendingHostUpdate(int appWidgetId, int type) { this.appWidgetId = appWidgetId; this.type = type; diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java index dfec4e102fd4..a0aa2dee9d34 100644 --- a/core/java/android/bluetooth/BluetoothOutputStream.java +++ b/core/java/android/bluetooth/BluetoothOutputStream.java @@ -75,16 +75,4 @@ import java.io.OutputStream; } mSocket.write(b, offset, count); } - - /** - * Wait until the data in sending queue is emptied. A polling version - * for flush implementation. Use it to ensure the writing data afterwards will - * be packed in the new RFCOMM frame. - * - * @throws IOException if an i/o error occurs. - * @since Android 4.2.3 - */ - public void flush() throws IOException { - mSocket.flush(); - } } diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index a6e3153d6af7..760166bfcc5d 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -515,20 +515,6 @@ public final class BluetoothSocket implements Closeable { return mSocketIS.available(); } - /** - * Wait until the data in sending queue is emptied. A polling version - * for flush implementation. Used to ensure the writing data afterwards will - * be packed in new RFCOMM frame. - * - * @throws IOException if an i/o error occurs. - */ - @UnsupportedAppUsage - /*package*/ void flush() throws IOException { - if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); - if (VDBG) Log.d(TAG, "flush: " + mSocketOS); - mSocketOS.flush(); - } - /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 9cf54f41a64b..ac1cbd4619df 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -23,6 +23,7 @@ import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN; import static android.content.ConfigurationProto.KEYBOARD; import static android.content.ConfigurationProto.KEYBOARD_HIDDEN; import static android.content.ConfigurationProto.LOCALES; +import static android.content.ConfigurationProto.LOCALE_LIST; import static android.content.ConfigurationProto.MCC; import static android.content.ConfigurationProto.MNC; import static android.content.ConfigurationProto.NAVIGATION; @@ -1111,7 +1112,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration protoOutputStream.write(MCC, mcc); protoOutputStream.write(MNC, mnc); if (mLocaleList != null) { - mLocaleList.writeToProto(protoOutputStream, LOCALES); + protoOutputStream.write(LOCALE_LIST, mLocaleList.toLanguageTags()); } protoOutputStream.write(SCREEN_LAYOUT, screenLayout); protoOutputStream.write(COLOR_MODE, colorMode); @@ -1283,6 +1284,14 @@ public final class Configuration implements Parcelable, Comparable<Configuration case (int) WINDOW_CONFIGURATION: windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION); break; + case (int) LOCALE_LIST: + try { + setLocales(LocaleList.forLanguageTags(protoInputStream.readString( + LOCALE_LIST))); + } catch (Exception e) { + Slog.e(TAG, "error parsing locale list in configuration.", e); + } + break; } } } finally { diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index b8ab1142e534..8e8a81d6cee6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -2169,11 +2169,18 @@ public class Camera { } /** - * Setting camera audio restriction mode. + * Set camera audio restriction mode. * * @hide */ - public native final int setAudioRestriction(int mode); + public native final void setAudioRestriction(int mode); + + /** + * Get currently applied camera audio restriction mode. + * + * @hide + */ + public native final int getAudioRestriction(); /** * Image size (width and height dimensions). diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index ed2d0c9344c6..0714884e347c 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -1251,25 +1251,43 @@ public abstract class CameraDevice implements AutoCloseable { * are setting different modes, the system will pick a the mode that's union of * all modes set by CameraDevice.</p> * - * <p>The mute settings will be automatically removed when the CameraDevice is closed or - * the application is disconnected from the camera.</p> + * <p>The mute settings from this CameraDevice will be automatically removed when the + * CameraDevice is closed or the application is disconnected from the camera.</p> * * @param mode An enumeration selecting the audio restriction mode for this camera device. * - * @return The system-wide mute mode setting resulting from this call - * * @throws IllegalArgumentException if the mode is not supported * * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error * @throws IllegalStateException if the camera device has been closed + * + * @see #getCameraAudioRestriction */ - public @CAMERA_AUDIO_RESTRICTION int setCameraAudioRestriction( + public void setCameraAudioRestriction( @CAMERA_AUDIO_RESTRICTION int mode) throws CameraAccessException { throw new UnsupportedOperationException("Subclasses must override this method"); } /** + * Get currently applied global camera audio restriction mode. + * + * <p>Application can use this method to retrieve the system-wide camera audio restriction + * settings described in {@link #setCameraAudioRestriction}.</p> + * + * @return The system-wide mute mode setting resulting from this call + * + * @throws CameraAccessException if the camera device is no longer connected or has + * encountered a fatal error + * @throws IllegalStateException if the camera device has been closed + * + * @see #setCameraAudioRestriction + */ + public @CAMERA_AUDIO_RESTRICTION int getCameraAudioRestriction() throws CameraAccessException { + throw new UnsupportedOperationException("Subclasses must override this method"); + } + + /** * To be inherited by android.hardware.camera2.* code only. * @hide */ diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 1f385dde9563..4494d27330b5 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -2570,11 +2570,19 @@ public class CameraDeviceImpl extends CameraDevice } @Override - public @CAMERA_AUDIO_RESTRICTION int setCameraAudioRestriction( + public void setCameraAudioRestriction( @CAMERA_AUDIO_RESTRICTION int mode) throws CameraAccessException { synchronized(mInterfaceLock) { checkIfCameraClosedOrInError(); - return mRemoteDevice.setCameraAudioRestriction(mode); + mRemoteDevice.setCameraAudioRestriction(mode); + } + } + + @Override + public @CAMERA_AUDIO_RESTRICTION int getCameraAudioRestriction() throws CameraAccessException { + synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); + return mRemoteDevice.getGlobalAudioRestriction(); } } } diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java index ff2819b25c00..3660f29f68d1 100644 --- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java +++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java @@ -258,9 +258,18 @@ public class ICameraDeviceUserWrapper { } } - public int setCameraAudioRestriction(int mode) throws CameraAccessException { + public void setCameraAudioRestriction(int mode) throws CameraAccessException { try { - return mRemoteDevice.setCameraAudioRestriction(mode); + mRemoteDevice.setCameraAudioRestriction(mode); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public int getGlobalAudioRestriction() throws CameraAccessException { + try { + return mRemoteDevice.getGlobalAudioRestriction(); } catch (Throwable t) { CameraManager.throwAsPublicException(t); throw new UnsupportedOperationException("Unexpected exception", t); diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index 0fa17c1fb574..5d1435ab4c8d 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -767,14 +767,25 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } @Override - public int setCameraAudioRestriction(int mode) { + public void setCameraAudioRestriction(int mode) { if (mLegacyDevice.isClosed()) { String err = "Cannot set camera audio restriction, device has been closed."; Log.e(TAG, err); throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } - return mLegacyDevice.setAudioRestriction(mode); + mLegacyDevice.setAudioRestriction(mode); + } + + @Override + public int getGlobalAudioRestriction() { + if (mLegacyDevice.isClosed()) { + String err = "Cannot set camera audio restriction, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); + } + + return mLegacyDevice.getAudioRestriction(); } @Override diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index c0d8baab0ad1..fbc9ac3229c3 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -550,8 +550,12 @@ public class LegacyCameraDevice implements AutoCloseable { return lastFrame; } - public int setAudioRestriction(int mode) { - return mRequestThreadManager.setAudioRestriction(mode); + public void setAudioRestriction(int mode) { + mRequestThreadManager.setAudioRestriction(mode); + } + + public int getAudioRestriction() { + return mRequestThreadManager.getAudioRestriction(); } /** diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index a514ee139d9c..32411fbdda2f 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -1105,9 +1105,16 @@ public class RequestThreadManager { condition.block(); } - public int setAudioRestriction(int mode) { + public void setAudioRestriction(int mode) { if (mCamera != null) { - return mCamera.setAudioRestriction(mode); + mCamera.setAudioRestriction(mode); + } + throw new IllegalStateException("Camera has been released!"); + } + + public int getAudioRestriction() { + if (mCamera != null) { + return mCamera.getAudioRestriction(); } throw new IllegalStateException("Camera has been released!"); } diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java index fe7632c25445..b066a15106af 100644 --- a/core/java/android/net/LocalSocketImpl.java +++ b/core/java/android/net/LocalSocketImpl.java @@ -157,40 +157,6 @@ class LocalSocketImpl write_native(b, myFd); } } - - /** - * Wait until the data in sending queue is emptied. A polling version - * for flush implementation. - * @throws IOException - * if an i/o error occurs. - */ - @Override - public void flush() throws IOException { - FileDescriptor myFd = fd; - if (myFd == null) throw new IOException("socket closed"); - - // Loop until the output buffer is empty. - Int32Ref pending = new Int32Ref(0); - while (true) { - try { - // See linux/net/unix/af_unix.c - Os.ioctlInt(myFd, OsConstants.TIOCOUTQ, pending); - } catch (ErrnoException e) { - throw e.rethrowAsIOException(); - } - - if (pending.value <= 0) { - // The output buffer is empty. - break; - } - - try { - Thread.sleep(10); - } catch (InterruptedException ie) { - break; - } - } - } } private native int read_native(FileDescriptor fd) throws IOException; diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java index 7782753e4abc..0de09efad8ea 100644 --- a/core/java/android/os/LocaleList.java +++ b/core/java/android/os/LocaleList.java @@ -21,9 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; import android.annotation.UnsupportedAppUsage; -import android.content.LocaleProto; import android.icu.util.ULocale; -import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -143,26 +141,6 @@ public final class LocaleList implements Parcelable { } /** - * Helper to write LocaleList to a protocol buffer output stream. Assumes the parent - * protobuf has declared the locale as repeated. - * - * @param protoOutputStream Stream to write the locale to. - * @param fieldId Field Id of the Locale as defined in the parent message. - * @hide - */ - public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) { - for (int i = 0; i < mList.length; i++) { - final Locale locale = mList[i]; - final long token = protoOutputStream.start(fieldId); - protoOutputStream.write(LocaleProto.LANGUAGE, locale.getLanguage()); - protoOutputStream.write(LocaleProto.COUNTRY, locale.getCountry()); - protoOutputStream.write(LocaleProto.VARIANT, locale.getVariant()); - protoOutputStream.write(LocaleProto.SCRIPT, locale.getScript()); - protoOutputStream.end(token); - } - } - - /** * Retrieves a String representation of the language tags in this list. */ @NonNull diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 86651060a394..5a2d8f4329dc 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -276,6 +276,7 @@ public class TextLine { final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -360,6 +361,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -417,6 +419,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 07cecd38620d..74cff205dabc 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -67,20 +67,19 @@ public class TimeUtils { * found. */ private static android.icu.util.TimeZone getIcuTimeZone( - int offset, boolean dst, long when, String country) { - if (country == null) { + int offsetMillis, boolean isDst, long whenMillis, String countryIso) { + if (countryIso == null) { return null; } android.icu.util.TimeZone bias = android.icu.util.TimeZone.getDefault(); CountryTimeZones countryTimeZones = - TimeZoneFinder.getInstance().lookupCountryTimeZones(country); + TimeZoneFinder.getInstance().lookupCountryTimeZones(countryIso); if (countryTimeZones == null) { return null; } - - CountryTimeZones.OffsetResult offsetResult = - countryTimeZones.lookupByOffsetWithBias(offset, dst, when, bias); + CountryTimeZones.OffsetResult offsetResult = countryTimeZones.lookupByOffsetWithBias( + offsetMillis, isDst, null /* dstOffsetMillis */, whenMillis, bias); return offsetResult != null ? offsetResult.mTimeZone : null; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7ee3973a40aa..bdfb3e318b3b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4356,6 +4356,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private Insets mLayoutInsets; /** + * Briefly describes the state of the view and is primarily used for accessibility support. + */ + private CharSequence mStateDescription; + + /** * Briefly describes the view and is primarily used for accessibility support. */ private CharSequence mContentDescription; @@ -9925,6 +9930,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, info.setImportantForAccessibility(isImportantForAccessibility()); info.setPackageName(mContext.getPackageName()); info.setClassName(getAccessibilityClassName()); + info.setStateDescription(getStateDescription()); info.setContentDescription(getContentDescription()); info.setEnabled(isEnabled()); @@ -10297,6 +10303,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the {@link View}'s state description. + * <p> + * <strong>Note:</strong> Do not override this method, as it will have no + * effect on the state description presented to accessibility services. + * You must call {@link #setStateDescription(CharSequence)} to modify the + * state description. + * + * @return the state description + * @see #setStateDescription(CharSequence) + */ + @ViewDebug.ExportedProperty(category = "accessibility") + public final @Nullable CharSequence getStateDescription() { + return mStateDescription; + } + + /** * Returns the {@link View}'s content description. * <p> * <strong>Note:</strong> Do not override this method, as it will have no @@ -10315,6 +10337,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Sets the {@link View}'s state description. + * <p> + * A state description briefly describes the states of the view and is primarily used + * for accessibility support to determine how the states of a view should be presented to + * the user. It is a supplement to the boolean states (for example, checked/unchecked) and + * it is used for customized state description (for example, "wifi, connected, three bars"). + * State description changes frequently while content description should change less often. + * + * @param stateDescription The state description. + * @see #getStateDescription() + */ + @RemotableViewMethod + public void setStateDescription(@Nullable CharSequence stateDescription) { + if (mStateDescription == null) { + if (stateDescription == null) { + return; + } + } else if (mStateDescription.equals(stateDescription)) { + return; + } + mStateDescription = stateDescription; + if (!TextUtils.isEmpty(stateDescription) + && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + } + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION); + } + + /** * Sets the {@link View}'s content description. * <p> * A content description briefly describes the view and is primarily used diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java index feba7bb7f195..f25206dce8ff 100644 --- a/core/java/android/view/ViewParent.java +++ b/core/java/android/view/ViewParent.java @@ -408,6 +408,7 @@ public interface ViewParent { * or more of: * <ul> * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION} + * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED} diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b2d70321178e..001ab6650551 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1475,6 +1475,9 @@ public interface WindowManager extends ViewManager { * <p>When this flag is enabled for a window, it automatically sets * the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.</p> + * + * <p>Note: For devices that support + * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE} this flag may be ignored. */ public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000; @@ -1494,6 +1497,10 @@ public interface WindowManager extends ViewManager { * <p>When this flag is enabled for a window, it automatically sets * the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.</p> + * + * <p>Note: For devices that support + * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE} this flag can be disabled + * by the car manufacturers. */ public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000; diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 584436542875..59e7bd236907 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -17,6 +17,7 @@ package android.view; import android.content.res.Configuration; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; @@ -93,6 +94,14 @@ class WindowlessWindowManager implements IWindowSession { @Override public void remove(android.view.IWindow window) {} + private boolean isOpaque(WindowManager.LayoutParams attrs) { + if (attrs.surfaceInsets.left != 0 || attrs.surfaceInsets.top != 0 || + attrs.surfaceInsets.right != 0 || attrs.surfaceInsets.bottom != 0) { + return false; + } + return !PixelFormat.formatHasAlpha(attrs.format); + } + @Override public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, @@ -109,7 +118,11 @@ class WindowlessWindowManager implements IWindowSession { "Invalid window token (never added or removed already)"); } SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - t.show(sc).setBufferSize(sc, requestedWidth, requestedHeight).apply(); + t.show(sc).setBufferSize(sc, + requestedWidth + attrs.surfaceInsets.left + attrs.surfaceInsets.right, + requestedHeight + attrs.surfaceInsets.top + attrs.surfaceInsets.bottom) + .setOpaque(sc, isOpaque(attrs)) + .apply(); outSurfaceControl.copyFrom(sc); outFrame.set(0, 0, requestedWidth, requestedHeight); diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index fd09a87aaa70..32b0f413321a 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -602,6 +602,13 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020; /** + * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: + * state description of the node as returned by + * {@link AccessibilityNodeInfo#getStateDescription} changed. + */ + public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000040; + + /** * Change type for {@link #TYPE_WINDOWS_CHANGED} event: * The window was added. */ @@ -696,6 +703,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par CONTENT_CHANGE_TYPE_SUBTREE, CONTENT_CHANGE_TYPE_TEXT, CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION, + CONTENT_CHANGE_TYPE_STATE_DESCRIPTION, CONTENT_CHANGE_TYPE_PANE_TITLE, CONTENT_CHANGE_TYPE_PANE_APPEARED, CONTENT_CHANGE_TYPE_PANE_DISAPPEARED @@ -885,6 +893,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @return The bit mask of change types. One or more of: * <ul> * <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION} + * <li>{@link #CONTENT_CHANGE_TYPE_STATE_DESCRIPTION} * <li>{@link #CONTENT_CHANGE_TYPE_SUBTREE} * <li>{@link #CONTENT_CHANGE_TYPE_TEXT} * <li>{@link #CONTENT_CHANGE_TYPE_PANE_TITLE} @@ -906,6 +915,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par switch (type) { case CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION: return "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION"; + case CONTENT_CHANGE_TYPE_STATE_DESCRIPTION: + return "CONTENT_CHANGE_TYPE_STATE_DESCRIPTION"; case CONTENT_CHANGE_TYPE_SUBTREE: return "CONTENT_CHANGE_TYPE_SUBTREE"; case CONTENT_CHANGE_TYPE_TEXT: return "CONTENT_CHANGE_TYPE_TEXT"; case CONTENT_CHANGE_TYPE_PANE_TITLE: return "CONTENT_CHANGE_TYPE_PANE_TITLE"; diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 61debc8d8468..cf29ed712793 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -744,6 +744,7 @@ public class AccessibilityNodeInfo implements Parcelable { private CharSequence mHintText; private CharSequence mError; private CharSequence mPaneTitle; + private CharSequence mStateDescription; private CharSequence mContentDescription; private CharSequence mTooltipText; private String mViewIdResourceName; @@ -2723,6 +2724,15 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Get the state description of this node. + * + * @return the state description + */ + public @Nullable CharSequence getStateDescription() { + return mStateDescription; + } + + /** * Gets the content description of this node. * * @return The content description. @@ -2731,6 +2741,25 @@ public class AccessibilityNodeInfo implements Parcelable { return mContentDescription; } + + /** + * Sets the state description of this node. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param stateDescription the state description of this node. + * + * @throws IllegalStateException If called from an AccessibilityService. + */ + public void setStateDescription(@Nullable CharSequence stateDescription) { + enforceNotSealed(); + mStateDescription = (stateDescription == null) ? null + : stateDescription.subSequence(0, stateDescription.length()); + } + /** * Sets the content description of this node. * <p> @@ -3373,6 +3402,10 @@ public class AccessibilityNodeInfo implements Parcelable { fieldIndex++; if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex); fieldIndex++; + if (!Objects.equals(mStateDescription, DEFAULT.mStateDescription)) { + nonDefaultFields |= bitAt(fieldIndex); + } + fieldIndex++; if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) { nonDefaultFields |= bitAt(fieldIndex); } @@ -3505,6 +3538,7 @@ public class AccessibilityNodeInfo implements Parcelable { if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError); + if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mStateDescription); if (isBitSet(nonDefaultFields, fieldIndex++)) { parcel.writeCharSequence(mContentDescription); } @@ -3582,6 +3616,7 @@ public class AccessibilityNodeInfo implements Parcelable { mOriginalText = other.mOriginalText; mHintText = other.mHintText; mError = other.mError; + mStateDescription = other.mStateDescription; mContentDescription = other.mContentDescription; mPaneTitle = other.mPaneTitle; mTooltipText = other.mTooltipText; @@ -3706,6 +3741,7 @@ public class AccessibilityNodeInfo implements Parcelable { if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence(); if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence(); if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence(); + if (isBitSet(nonDefaultFields, fieldIndex++)) mStateDescription = parcel.readCharSequence(); if (isBitSet(nonDefaultFields, fieldIndex++)) { mContentDescription = parcel.readCharSequence(); } @@ -4004,6 +4040,7 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; text: ").append(mText); builder.append("; error: ").append(mError); builder.append("; maxTextLength: ").append(mMaxTextLength); + builder.append("; stateDescription: ").append(mStateDescription); builder.append("; contentDescription: ").append(mContentDescription); builder.append("; tooltipText: ").append(mTooltipText); builder.append("; viewIdResName: ").append(mViewIdResourceName); diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index 0dd2587feed5..e035c620d1fd 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -211,16 +211,19 @@ public final class ViewNode extends AssistStructure.ViewNode { return mParentAutofillId; } + @Nullable @Override public AutofillId getAutofillId() { return mAutofillId; } + @Nullable @Override public CharSequence getText() { return mText != null ? mText.mText : null; } + @Nullable @Override public String getClassName() { return mClassName; @@ -231,16 +234,19 @@ public final class ViewNode extends AssistStructure.ViewNode { return mId; } + @Nullable @Override public String getIdPackage() { return mIdPackage; } + @Nullable @Override public String getIdType() { return mIdType; } + @Nullable @Override public String getIdEntry() { return mIdEntry; @@ -341,21 +347,25 @@ public final class ViewNode extends AssistStructure.ViewNode { return (mFlags & FLAGS_OPAQUE) != 0; } + @Nullable @Override public CharSequence getContentDescription() { return mContentDescription; } + @Nullable @Override public Bundle getExtras() { return mExtras; } + @Nullable @Override public String getHint() { return mText != null ? mText.mHint : null; } + @Nullable @Override public String getHintIdEntry() { return mHintIdEntry; @@ -391,11 +401,13 @@ public final class ViewNode extends AssistStructure.ViewNode { return mText != null ? mText.mTextStyle : 0; } + @Nullable @Override public int[] getTextLineCharOffsets() { return mText != null ? mText.mLineCharOffsets : null; } + @Nullable @Override public int[] getTextLineBaselines() { return mText != null ? mText.mLineBaselines : null; @@ -426,6 +438,7 @@ public final class ViewNode extends AssistStructure.ViewNode { return mMaxLength; } + @Nullable @Override public String getTextIdEntry() { return mTextIdEntry; @@ -451,6 +464,7 @@ public final class ViewNode extends AssistStructure.ViewNode { return mAutofillOptions; } + @Nullable @Override public LocaleList getLocaleList() { return mLocaleList; diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index d3c69725b45b..f58b6d192fde 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -800,6 +800,7 @@ public final class Magnifier { // The surface we allocate for the magnifier content + shadow. private final SurfaceSession mSurfaceSession; private final SurfaceControl mSurfaceControl; + private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); private final Surface mSurface; // The renderer used for the allocated surface. private final ThreadedRenderer.SimpleRenderer mRenderer; @@ -1081,16 +1082,16 @@ public final class Magnifier { return; } // Show or move the window at the content draw frame. - SurfaceControl.openTransaction(); - mSurfaceControl.deferTransactionUntil(mSurface, frame); + mTransaction.deferTransactionUntilSurface(mSurfaceControl, mSurface, frame); if (updateWindowPosition) { - mSurfaceControl.setPosition(pendingX, pendingY); + mTransaction.setPosition(mSurfaceControl, pendingX, pendingY); } if (firstDraw) { - mSurfaceControl.setLayer(SURFACE_Z); - mSurfaceControl.show(); + mTransaction.setLayer(mSurfaceControl, SURFACE_Z) + .show(mSurfaceControl); + } - SurfaceControl.closeTransaction(); + mTransaction.apply(); }; mRenderer.setLightCenter(mDisplay, pendingX, pendingY); } else { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index de77aaae1653..38cb2cc1d553 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1666,10 +1666,6 @@ public class ChooserActivity extends ResolverActivity { mServiceConnections.clear(); } - public void onSetupVoiceInteraction() { - // Do nothing. We'll send the voice stuff ourselves. - } - private void logDirectShareTargetReceived(int logCategory) { final long queryTime = logCategory == MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 58ce03baa136..407a85f1bb05 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -361,9 +361,6 @@ public class ResolverActivity extends Activity { initSuspendedColorMatrix(); - if (isVoiceInteraction()) { - onSetupVoiceInteraction(); - } final Set<String> categories = intent.getCategories(); MetricsLogger.action(this, mAdapter.hasFilteredItem() ? MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_APP_FEATURED @@ -442,24 +439,21 @@ public class ResolverActivity extends Activity { mSuspendedMatrixColorFilter = new ColorMatrixColorFilter(matrix); } - /** - * Perform any initialization needed for voice interaction. - */ - public void onSetupVoiceInteraction() { - // Do it right now. Subclasses may delay this and send it later. - sendVoiceChoicesIfNeeded(); - } - public void sendVoiceChoicesIfNeeded() { if (!isVoiceInteraction()) { // Clearly not needed. return; } - final Option[] options = new Option[mAdapter.getCount()]; for (int i = 0, N = options.length; i < N; i++) { - options[i] = optionForChooserTarget(mAdapter.getItem(i), i); + TargetInfo target = mAdapter.getItem(i); + if (target == null) { + // If this occurs, a new set of targets is being loaded. Let that complete, + // and have the next call to send voice choices proceed instead. + return; + } + options[i] = optionForChooserTarget(target, i); } mPickOptionRequest = new PickTargetOptionRequest( @@ -1872,7 +1866,7 @@ public class ResolverActivity extends Activity { } } - + sendVoiceChoicesIfNeeded(); postListReadyRunnable(); } diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl index a7f7fe19bb4d..7cbacade5797 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl @@ -27,5 +27,6 @@ oneway interface IAppWidgetHost { void providerChanged(int appWidgetId, in AppWidgetProviderInfo info); void providersChanged(); void viewDataChanged(int appWidgetId, int viewId); + void appWidgetRemoved(int appWidgetId); } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 31995f7ec821..3be1a1aefe57 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -749,7 +749,7 @@ public class ZygoteInit { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023," - + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", + + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java index 3cb6919819ab..b54e5fb56712 100644 --- a/core/java/com/android/internal/widget/ExploreByTouchHelper.java +++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java @@ -229,6 +229,7 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { * default (undefined) change type or one or more of: * <ul> * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION} + * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT} * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED} diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index f87163bb8379..bc69735d7453 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -1023,22 +1023,38 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject } } -static int32_t android_hardware_Camera_setAudioRestriction( +static void android_hardware_Camera_setAudioRestriction( JNIEnv *env, jobject thiz, jint mode) { ALOGV("setAudioRestriction"); sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) { jniThrowRuntimeException(env, "camera has been disconnected"); - return -1; + return; } int32_t ret = camera->setAudioRestriction(mode); if (ret < 0) { jniThrowRuntimeException(env, "Illegal argument or low-level eror"); + return; + } +} + +static int32_t android_hardware_Camera_getAudioRestriction( + JNIEnv *env, jobject thiz) +{ + ALOGV("getAudioRestriction"); + sp<Camera> camera = get_native_camera(env, thiz, NULL); + if (camera == 0) { + jniThrowRuntimeException(env, "camera has been disconnected"); return -1; } + int32_t ret = camera->getGlobalAudioRestriction(); + if (ret < 0) { + jniThrowRuntimeException(env, "Illegal argument or low-level eror"); + return -1; + } return ret; } @@ -1127,8 +1143,11 @@ static const JNINativeMethod camMethods[] = { "(I)V", (void *)android_hardware_Camera_enableFocusMoveCallback}, { "setAudioRestriction", - "(I)I", + "(I)V", (void *)android_hardware_Camera_setAudioRestriction}, + { "getAudioRestriction", + "()I", + (void *)android_hardware_Camera_getAudioRestriction}, }; struct field { diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto index 57ced09240f2..7fa0ff64f8bf 100644 --- a/core/proto/android/content/configuration.proto +++ b/core/proto/android/content/configuration.proto @@ -32,7 +32,7 @@ message ConfigurationProto { optional float font_scale = 1; optional uint32 mcc = 2; optional uint32 mnc = 3 [ (.android.privacy).dest = DEST_EXPLICIT ]; - repeated LocaleProto locales = 4; + repeated LocaleProto locales = 4 [deprecated = true]; optional uint32 screen_layout = 5; optional uint32 color_mode = 6; optional uint32 touchscreen = 7; @@ -48,6 +48,7 @@ message ConfigurationProto { optional uint32 smallest_screen_width_dp = 17; optional uint32 density_dpi = 18; optional .android.app.WindowConfigurationProto window_configuration = 19; + optional string locale_list = 20; } /** diff --git a/core/proto/android/content/locale.proto b/core/proto/android/content/locale.proto index bae6ec141981..a8f2a1334038 100644 --- a/core/proto/android/content/locale.proto +++ b/core/proto/android/content/locale.proto @@ -22,6 +22,7 @@ import "frameworks/base/core/proto/android/privacy.proto"; package android.content; message LocaleProto { + option deprecated = true; option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional string language = 1; diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 797d75f5a54f..839aaac16c7a 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -95,6 +95,7 @@ <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string> <string name="notification_channel_sim" msgid="4052095493875188564">"SIM status"</string> + <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"High priority SIM status"</string> <string name="peerTtyModeFull" msgid="6165351790010341421">"Peer requested TTY Mode FULL"</string> <string name="peerTtyModeHco" msgid="5728602160669216784">"Peer requested TTY Mode HCO"</string> <string name="peerTtyModeVco" msgid="1742404978686538049">"Peer requested TTY Mode VCO"</string> @@ -1256,10 +1257,10 @@ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string> <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"All networks"</string> - <string name="wifi_suggestion_title" msgid="9099832833531486167">"Connect to Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="5883181205841582873">"Suggested by <xliff:g id="NAME">%s</xliff:g>"</string> - <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"Yes"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"No"</string> + <string name="wifi_suggestion_title" msgid="6396033039578436801">"Allow suggested Wi‑Fi networks?"</string> + <string name="wifi_suggestion_content" msgid="5603992011371520746">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> + <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"Allow"</string> + <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"No, thanks"</string> <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string> <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string> <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 7ea76500e4ea..7961a865cd53 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -95,6 +95,7 @@ <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi calling"</string> <string name="notification_channel_sim" msgid="4052095493875188564">"SIM status"</string> + <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"High priority SIM status"</string> <string name="peerTtyModeFull" msgid="6165351790010341421">"Peer requested TTY Mode FULL"</string> <string name="peerTtyModeHco" msgid="5728602160669216784">"Peer requested TTY Mode HCO"</string> <string name="peerTtyModeVco" msgid="1742404978686538049">"Peer requested TTY Mode VCO"</string> @@ -1256,10 +1257,10 @@ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string> <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"All networks"</string> - <string name="wifi_suggestion_title" msgid="9099832833531486167">"Connect to Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="5883181205841582873">"Suggested by <xliff:g id="NAME">%s</xliff:g>"</string> - <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"Yes"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"No"</string> + <string name="wifi_suggestion_title" msgid="6396033039578436801">"Allow suggested Wi‑Fi networks?"</string> + <string name="wifi_suggestion_content" msgid="5603992011371520746">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> + <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"Allow"</string> + <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"No thanks"</string> <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string> <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high quality saved network"</string> <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 1346b8631935..0229cf5a0ed4 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -30,7 +30,7 @@ <string name="untitled" msgid="4638956954852782576">"<Sin título>"</string> <string name="emptyPhoneNumber" msgid="7694063042079676517">"(No hay número de teléfono)"</string> <string name="unknownName" msgid="6867811765370350269">"Desconocido"</string> - <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Correo de voz"</string> + <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Buzón de voz"</string> <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string> <string name="mmiError" msgid="5154499457739052907">"Problema de conexión o código incorrecto de MMI."</string> <string name="mmiFdnError" msgid="5224398216385316471">"La operación está limitada a números de marcación fija."</string> @@ -944,7 +944,7 @@ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los favoritos del navegador almacenados en el dispositivo. La aplicación puede utilizar este permiso para borrar o modificar los datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"programar una alarma"</string> <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string> - <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string> + <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar buzón de voz"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación agregue mensajes a la bandeja de entrada de tu buzón de voz."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modificar los permisos de ubicación geográfica del navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizar esto para permitir el envío de información de ubicación a sitios web arbitrarios."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 7c6c1594124e..b75644b469e5 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -2053,7 +2053,7 @@ <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Bližnjice ni bilo mogoče obnoviti zaradi neujemanja podpisa aplikacije"</string> <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Bližnjice ni bilo mogoče obnoviti"</string> <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Bližnjica je onemogočena"</string> - <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"ODSTRANI"</string> + <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"ODMESTI"</string> <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"VSEENO ODPRI"</string> <string name="harmful_app_warning_title" msgid="8982527462829423432">"Zaznana je bila škodljiva aplikacija"</string> <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 726e223bbc78..7028672bd5eb 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -365,9 +365,9 @@ <string name="permlab_enableCarMode" msgid="5684504058192921098">"கார் பயன்முறையை இயக்குதல்"</string> <string name="permdesc_enableCarMode" msgid="4853187425751419467">"கார் முறையை இயக்க, ஆப்ஸை அனுமதிக்கிறது."</string> <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"பிற பயன்பாடுகளை மூடுதல்"</string> - <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"பிற பயன்பாடுகளின் பின்புலச் செயல்முறைகளை நிறுத்த ஆப்ஸை அனுமதிக்கிறது. இதனால் பிற பயன்பாடுகள் இயங்குவதை நிறுத்தலாம்."</string> - <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"இந்த ஆப்ஸ் பிற பயன்பாடுகளின் மேலே தோன்றலாம்"</string> - <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"இந்த ஆப்ஸ் பிற பயன்பாடுகளின் மேலே அல்லது திரையின் பிற பகுதிகளில் தோன்றலாம். இது வழக்கமான ஆப்ஸ் உபயோகத்தில் குறுக்கிட்டு, பிற பயன்பாடுகள் தோன்றும் விதத்தை மாற்றக்கூடும்."</string> + <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"பிற ஆப்ஸின் பின்புலச் செயல்முறைகளை நிறுத்த ஆப்ஸை அனுமதிக்கிறது. இதனால் பிற பயன்பாடுகள் இயங்குவதை நிறுத்தலாம்."</string> + <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"இந்த ஆப்ஸ் பிற ஆப்ஸின் மேலே தோன்றலாம்"</string> + <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"இந்த ஆப்ஸ் பிற ஆப்ஸின் மேலே அல்லது திரையின் பிற பகுதிகளில் தோன்றலாம். இது வழக்கமான ஆப்ஸ் உபயோகத்தில் குறுக்கிட்டு, பிற பயன்பாடுகள் தோன்றும் விதத்தை மாற்றக்கூடும்."</string> <string name="permlab_runInBackground" msgid="7365290743781858803">"பின்னணியில் இயக்கு"</string> <string name="permdesc_runInBackground" msgid="7370142232209999824">"இந்த ஆப்ஸ், பின்னணியில் இயங்கலாம். இதனால் பேட்டரி விரைவாகத் தீர்ந்துவிடக்கூடும்."</string> <string name="permlab_useDataInBackground" msgid="8694951340794341809">"பின்னணியில் தரவைப் பயன்படுத்து"</string> @@ -1380,7 +1380,7 @@ <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"பிற ஆப்ஸின் மேலே காட்டு"</string> - <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற பயன்பாடுகளின் மீது தோன்றுகிறது"</string> + <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string> <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string> <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string> <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"ஆஃப் செய்"</string> @@ -2004,7 +2004,7 @@ <string name="standby_warning_message" product="default" msgid="5222741828239073484">"இந்தச் சாதனம் விரைவில் ஆஃப் ஆகலாம். இதைத் தொடர்ந்து ஆனில் வைக்கத் தட்டவும்."</string> <string name="notification_appops_camera_active" msgid="5050283058419699771">"கேமரா"</string> <string name="notification_appops_microphone_active" msgid="4335305527588191730">"மைக்ரோஃபோன்"</string> - <string name="notification_appops_overlay_active" msgid="633813008357934729">"உங்கள் திரையில் உள்ள பிற பயன்பாடுகளின் மேல் காட்டுகிறது"</string> + <string name="notification_appops_overlay_active" msgid="633813008357934729">"உங்கள் திரையில் உள்ள பிற ஆப்ஸின் மேல் காட்டுகிறது"</string> <string name="dynamic_mode_notification_channel_name" msgid="2348803891571320452">"வழக்கமான பேட்டரி சேமிப்பானுக்கான விவர அறிவிப்பு"</string> <string name="dynamic_mode_notification_title" msgid="508815255807182035">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string> <string name="dynamic_mode_notification_summary" msgid="2541166298550402690">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index d17093211040..3472cb2a0e9e 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -299,7 +299,7 @@ <string name="permgrouplab_microphone" msgid="171539900250043464">"ไมโครโฟน"</string> <string name="permgroupdesc_microphone" msgid="4988812113943554584">"บันทึกเสียง"</string> <string name="permgrouprequest_microphone" msgid="9167492350681916038">"อนุญาตให้ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> บันทึกเสียงไหม"</string> - <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"กิจกรรมการเคลื่อนไหวร่างกาย"</string> + <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"การเคลื่อนไหวร่างกาย"</string> <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณ"</string> <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"อนุญาตให้ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณไหม"</string> <string name="permgrouplab_camera" msgid="4820372495894586615">"กล้องถ่ายรูป"</string> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index a92c50059a2a..f71c8b0558cf 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -70,7 +70,7 @@ <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" /> <!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf --> - <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075" /> + <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075|30047" /> <!-- Chile: 4-5 digits (not confirmed), known premium codes listed --> <shortcode country="cl" pattern="\\d{4,5}" free="9963|9240" /> diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java index 2fc3e36e7948..4a93f42a0f7c 100644 --- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java +++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java @@ -16,16 +16,29 @@ package android.content.res; +import android.content.Context; +import android.os.LocaleList; import android.platform.test.annotations.Presubmit; +import android.util.AtomicFile; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.server.usage.IntervalStatsProto; + import junit.framework.TestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.Locale; + /** * Build/install/run: bit FrameworksCoreTests:android.content.res.ConfigurationTest */ @@ -54,4 +67,70 @@ public class ConfigurationTest extends TestCase { config2.updateFrom(config); assertEquals(config2.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED); } + + @Test + public void testReadWriteProto() throws Exception { + final Context context = InstrumentationRegistry.getTargetContext(); + final File testDir = new File(context.getFilesDir(), "ConfigurationTest"); + testDir.mkdirs(); + final File proto = new File(testDir, "configs"); + if (proto.exists()) { + proto.delete(); + } + + final Locale arabic = new Locale.Builder().setLocale(new Locale("ar", "AE")).build(); + final Locale urdu = new Locale.Builder().setLocale(new Locale("ur", "IN")).build(); + final Locale urduExtension = new Locale.Builder().setLocale(new Locale("ur", "IN")) + .setExtension('u', "nu-latn").build(); + Configuration write = new Configuration(); + write.setLocales(new LocaleList(arabic, urdu, urduExtension)); + writeToProto(proto, write); + assertTrue("Failed to write configs to proto.", proto.exists()); + + final Configuration read = new Configuration(); + try { + readFromProto(proto, read); + } finally { + proto.delete(); + } + + assertEquals("Missing locales in proto file written to disk.", + read.getLocales().size(), write.getLocales().size()); + assertTrue("Arabic locale not found in Configuration locale list.", + read.getLocales().indexOf(arabic) != -1); + assertTrue("Urdu locale not found in Configuration locale list.", + read.getLocales().indexOf(urdu) != -1); + assertTrue("Urdu locale with extensions not found in Configuration locale list.", + read.getLocales().indexOf(urduExtension) != -1); + } + + private void writeToProto(File f, Configuration config) throws Exception { + final AtomicFile af = new AtomicFile(f); + FileOutputStream fos = af.startWrite(); + try { + final ProtoOutputStream protoOut = new ProtoOutputStream(fos); + final long token = protoOut.start(IntervalStatsProto.CONFIGURATIONS); + config.writeToProto(protoOut, IntervalStatsProto.Configuration.CONFIG, false, false); + protoOut.end(token); + protoOut.flush(); + af.finishWrite(fos); + fos = null; + } finally { + af.failWrite(fos); + } + } + + private void readFromProto(File f, Configuration config) throws Exception { + final AtomicFile afRead = new AtomicFile(f); + try (FileInputStream in = afRead.openRead()) { + final ProtoInputStream protoIn = new ProtoInputStream(in); + if (protoIn.nextField(IntervalStatsProto.CONFIGURATIONS)) { + final long token = protoIn.start(IntervalStatsProto.CONFIGURATIONS); + if (protoIn.nextField(IntervalStatsProto.Configuration.CONFIG)) { + config.readFromProto(protoIn, IntervalStatsProto.Configuration.CONFIG); + protoIn.end(token); + } + } + } + } } diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java index 4c59207b2d61..1bd52af09a4d 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java @@ -46,7 +46,7 @@ public class AccessibilityNodeInfoTest { // The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest: // See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo, // and assertAccessibilityNodeInfoCleared in that class. - private static final int NUM_MARSHALLED_PROPERTIES = 34; + private static final int NUM_MARSHALLED_PROPERTIES = 35; /** * The number of properties that are purposely not marshalled diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 530926bf8dd0..67c181b452bb 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -511,13 +511,13 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& } void SkiaPipeline::dumpResourceCacheUsage() const { - int resources, maxResources; - size_t bytes, maxBytes; + int resources; + size_t bytes; mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes); - mRenderThread.getGrContext()->getResourceCacheLimits(&maxResources, &maxBytes); + size_t maxBytes = mRenderThread.getGrContext()->getResourceCacheLimit(); SkString log("Resource Cache Usage:\n"); - log.appendf("%8d items out of %d maximum items\n", resources, maxResources); + log.appendf("%8d items\n", resources); log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n", bytes, bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f))); diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 5469a6810c87..fc268138e071 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -69,8 +69,7 @@ void CacheManager::reset(sk_sp<GrContext> context) { if (context) { mGrContext = std::move(context); - mGrContext->getResourceCacheLimits(&mMaxResources, nullptr); - mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes); + mGrContext->setResourceCacheLimit(mMaxResourceBytes); } } @@ -119,8 +118,8 @@ void CacheManager::trimMemory(TrimMemoryMode mode) { // limits between the background and max amounts. This causes the unlocked resources // that have persistent data to be purged in LRU order. mGrContext->purgeUnlockedResources(true); - mGrContext->setResourceCacheLimits(mMaxResources, mBackgroundResourceBytes); - mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes); + mGrContext->setResourceCacheLimit(mBackgroundResourceBytes); + mGrContext->setResourceCacheLimit(mMaxResourceBytes); SkGraphics::SetFontCacheLimit(mBackgroundCpuFontCacheBytes); SkGraphics::SetFontCacheLimit(mMaxCpuFontCacheBytes); break; diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index ad251f2364fe..d7977cc4566d 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -71,7 +71,6 @@ private: sk_sp<GrContext> mGrContext; #endif - int mMaxResources = 0; const size_t mMaxResourceBytes; const size_t mBackgroundResourceBytes; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 0ad050d7625e..b5ef8f43dfb6 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -484,7 +484,7 @@ void CanvasContext::draw() { swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC); swap.vsyncTime = mRenderThread.timeLord().latestVsync(); if (didDraw) { - nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime(); + nsecs_t dequeueStart = ANativeWindow_getLastDequeueStartTime(mNativeSurface.get()); if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) { // Ignoring dequeue duration as it happened prior to frame render start // and thus is not part of the frame. @@ -493,9 +493,7 @@ void CanvasContext::draw() { swap.dequeueDuration = us2ns(ANativeWindow_getLastDequeueDuration(mNativeSurface.get())); } - int durationUs; - mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs); - swap.queueDuration = us2ns(durationUs); + swap.queueDuration = us2ns(ANativeWindow_getLastQueueDuration(mNativeSurface.get())); } else { swap.dequeueDuration = 0; swap.queueDuration = 0; diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp index a44b80457218..864780fb6ae8 100644 --- a/libs/hwui/renderthread/ReliableSurface.cpp +++ b/libs/hwui/renderthread/ReliableSurface.cpp @@ -308,4 +308,4 @@ int ReliableSurface::hook_perform(ANativeWindow* window, int operation, ...) { return result; } -}; // namespace android::uirenderer::renderthread
\ No newline at end of file +}; // namespace android::uirenderer::renderthread diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h index 7f1a0781dd87..0d251b1f10e7 100644 --- a/libs/hwui/renderthread/ReliableSurface.h +++ b/libs/hwui/renderthread/ReliableSurface.h @@ -39,8 +39,6 @@ public: int query(int what, int* value) const { return mSurface->query(what, value); } - nsecs_t getLastDequeueStartTime() const { return mSurface->getLastDequeueStartTime(); } - uint64_t getNextFrameNumber() const { return mSurface->getNextFrameNumber(); } int getAndClearError() { @@ -105,4 +103,4 @@ private: static int hook_queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); }; -}; // namespace android::uirenderer::renderthread
\ No newline at end of file +}; // namespace android::uirenderer::renderthread diff --git a/media/jni/Android.bp b/media/jni/Android.bp index c49b1e496c66..84fe27de15ab 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -52,7 +52,6 @@ cc_library_shared { "libandroidfw", "libhidlallocatorutils", "libhidlbase", - "libhidltransport", "android.hardware.cas@1.0", "android.hardware.cas.native@1.0", "android.hidl.memory@1.0", @@ -147,7 +146,6 @@ cc_library_shared { "android.hidl.memory@1.0", "libhidlbase", "libhidlmemory", - "libhidltransport", "libbinderthreadstate", // MediaPlayer2 implementation diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 49066950a9fb..102bbf0e5931 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -951,6 +951,8 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) ALOGV("process %p channel %d event %s", this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" : "BUFFER_END"); + // Only BUFFER_END should happen as we use static tracks. + setVolume_l(0.f, 0.f); // set volume to 0 to indicate no need to ramp volume down. mSoundPool->addToStopList(this); } else if (event == AudioTrack::EVENT_LOOP_END) { ALOGV("End loop %p channel %d", this, mChannelID); @@ -966,14 +968,18 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) bool SoundChannel::doStop_l() { if (mState != IDLE) { - setVolume_l(0, 0); ALOGV("stop"); - // Since we're forcibly halting the previously playing content, - // we sleep here to ensure the volume is ramped down before we stop the track. - // Ideally the sleep time is the mixer period, or an approximation thereof - // (Fast vs Normal tracks are different). - // TODO: consider pausing instead of stop here. - std::this_thread::sleep_for(std::chrono::milliseconds(20)); + if (mLeftVolume != 0.f || mRightVolume != 0.f) { + setVolume_l(0.f, 0.f); + if (mSoundPool->attributes()->usage != AUDIO_USAGE_GAME) { + // Since we're forcibly halting the previously playing content, + // we sleep here to ensure the volume is ramped down before we stop the track. + // Ideally the sleep time is the mixer period, or an approximation thereof + // (Fast vs Normal tracks are different). + ALOGV("sleeping: ChannelID:%d SampleID:%d", mChannelID, mSample->sampleID()); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + } mAudioTrack->stop(); mPrevSampleID = mSample->sampleID(); mSample.clear(); diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RestoreKeyFetcher.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RestoreKeyFetcher.java new file mode 100644 index 000000000000..6fb958bd1c1e --- /dev/null +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RestoreKeyFetcher.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.keys; + +import android.security.keystore.recovery.InternalRecoveryServiceException; + +import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKeyManager.RecoverableKeyStoreSecondaryKeyManagerProvider; +import com.android.server.backup.encryption.protos.nano.WrappedKeyProto; + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.util.Optional; + +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; + +/** Fetches the secondary key and uses it to unwrap the tertiary key during restore. */ +public class RestoreKeyFetcher { + + /** + * Retrieves the secondary key with the given alias and uses it to unwrap the given wrapped + * tertiary key. + * + * @param secondaryKeyManagerProvider Provider which creates {@link + * RecoverableKeyStoreSecondaryKeyManager} + * @param secondaryKeyAlias Alias of the secondary key used to wrap the tertiary key + * @param wrappedTertiaryKey Tertiary key wrapped with the secondary key above + * @return The unwrapped tertiary key + */ + public static SecretKey unwrapTertiaryKey( + RecoverableKeyStoreSecondaryKeyManagerProvider secondaryKeyManagerProvider, + String secondaryKeyAlias, + WrappedKeyProto.WrappedKey wrappedTertiaryKey) + throws KeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, + NoSuchPaddingException { + Optional<RecoverableKeyStoreSecondaryKey> secondaryKey = + getSecondaryKey(secondaryKeyManagerProvider, secondaryKeyAlias); + if (!secondaryKey.isPresent()) { + throw new KeyException("No key:" + secondaryKeyAlias); + } + + return KeyWrapUtils.unwrap(secondaryKey.get().getSecretKey(), wrappedTertiaryKey); + } + + private static Optional<RecoverableKeyStoreSecondaryKey> getSecondaryKey( + RecoverableKeyStoreSecondaryKeyManagerProvider secondaryKeyManagerProvider, + String secondaryKeyAlias) + throws KeyException { + try { + return secondaryKeyManagerProvider.get().get(secondaryKeyAlias); + } catch (InternalRecoveryServiceException | UnrecoverableKeyException e) { + throw new KeyException("Could not retrieve key:" + secondaryKeyAlias, e); + } + } +} diff --git a/packages/BackupEncryption/test/robolectric/Android.bp b/packages/BackupEncryption/test/robolectric/Android.bp index 3376ec97e02f..f84be6d4f3f4 100644 --- a/packages/BackupEncryption/test/robolectric/Android.bp +++ b/packages/BackupEncryption/test/robolectric/Android.bp @@ -23,6 +23,7 @@ android_robolectric_test { "backup-encryption-protos", "platform-test-annotations", "testng", + "truth-prebuilt", ], instrumentation_for: "BackupEncryption", } diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RestoreKeyFetcherTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RestoreKeyFetcherTest.java new file mode 100644 index 000000000000..004f8097ce39 --- /dev/null +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RestoreKeyFetcherTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.keys; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; + +import android.platform.test.annotations.Presubmit; + +import com.android.server.backup.encryption.protos.nano.WrappedKeyProto; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +import java.security.InvalidKeyException; +import java.security.KeyException; +import java.security.SecureRandom; +import java.util.Optional; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +/** Test the restore key fetcher */ +@RunWith(RobolectricTestRunner.class) +@Presubmit +public class RestoreKeyFetcherTest { + + private static final String KEY_GENERATOR_ALGORITHM = "AES"; + + private static final String TEST_SECONDARY_KEY_ALIAS = "test_2ndary_key"; + private static final byte[] TEST_SECONDARY_KEY_BYTES = new byte[256 / Byte.SIZE]; + + @Mock private RecoverableKeyStoreSecondaryKeyManager mSecondaryKeyManager; + + /** Initialise the mocks **/ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + /** Ensure the unwrap method works as expected */ + @Test + public void unwrapTertiaryKey_returnsUnwrappedKey() throws Exception { + RecoverableKeyStoreSecondaryKey secondaryKey = createSecondaryKey(); + SecretKey tertiaryKey = createTertiaryKey(); + WrappedKeyProto.WrappedKey wrappedTertiaryKey = + KeyWrapUtils.wrap(secondaryKey.getSecretKey(), tertiaryKey); + when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS)) + .thenReturn(Optional.of(secondaryKey)); + + SecretKey actualTertiaryKey = + RestoreKeyFetcher.unwrapTertiaryKey( + () -> mSecondaryKeyManager, + TEST_SECONDARY_KEY_ALIAS, + wrappedTertiaryKey); + + assertThat(actualTertiaryKey).isEqualTo(tertiaryKey); + } + + /** Ensure that missing secondary keys are detected and an appropriate exception is thrown */ + @Test + public void unwrapTertiaryKey_missingSecondaryKey_throwsSpecificException() throws Exception { + WrappedKeyProto.WrappedKey wrappedTertiaryKey = + KeyWrapUtils.wrap(createSecondaryKey().getSecretKey(), createTertiaryKey()); + when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS)).thenReturn(Optional.empty()); + + assertThrows( + KeyException.class, + () -> + RestoreKeyFetcher.unwrapTertiaryKey( + () -> mSecondaryKeyManager, + TEST_SECONDARY_KEY_ALIAS, + wrappedTertiaryKey)); + } + + /** Ensure that invalid secondary keys are detected and an appropriate exception is thrown */ + @Test + public void unwrapTertiaryKey_badSecondaryKey_throws() throws Exception { + RecoverableKeyStoreSecondaryKey badSecondaryKey = + new RecoverableKeyStoreSecondaryKey( + TEST_SECONDARY_KEY_ALIAS, + new SecretKeySpec(new byte[] {0, 1}, KEY_GENERATOR_ALGORITHM)); + + WrappedKeyProto.WrappedKey wrappedTertiaryKey = + KeyWrapUtils.wrap(createSecondaryKey().getSecretKey(), createTertiaryKey()); + when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS)) + .thenReturn(Optional.of(badSecondaryKey)); + + assertThrows( + InvalidKeyException.class, + () -> + RestoreKeyFetcher.unwrapTertiaryKey( + () -> mSecondaryKeyManager, + TEST_SECONDARY_KEY_ALIAS, + wrappedTertiaryKey)); + } + + private static RecoverableKeyStoreSecondaryKey createSecondaryKey() { + return new RecoverableKeyStoreSecondaryKey( + TEST_SECONDARY_KEY_ALIAS, + new SecretKeySpec(TEST_SECONDARY_KEY_BYTES, KEY_GENERATOR_ALGORITHM)); + } + + private static SecretKey createTertiaryKey() { + return new TertiaryKeyGenerator(new SecureRandom(new byte[] {0})).generate(); + } +} diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index e0ae45662390..5fcf38fce3cc 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -32,7 +32,7 @@ <color name="system_bar_background_opaque">#ff172026</color> <color name="status_bar_background_color">#33000000</color> - <drawable name="system_bar_background">@android:color/transparent</drawable> + <drawable name="system_bar_background">@color/status_bar_background_color</drawable> <!-- The background color of the notification shade --> <color name="notification_shade_background_color">#D6000000</color> diff --git a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml index 7846be161c0f..363d88544a03 100644 --- a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1604061903696928905">"Definições de pesquisa"</string> + <string name="search_menu" msgid="1604061903696928905">"Pesquisar definições"</string> </resources> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 13890e029274..f1fc9f9e3d4e 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -452,7 +452,7 @@ <string name="cancel" msgid="6859253417269739139">"বাতিল"</string> <string name="okay" msgid="1997666393121016642">"ঠিক আছে"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"চালু করুন"</string> - <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'বিরক্ত করবেন না\' মোড চালু করুন"</string> + <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'বিরক্ত করবে না\' মোড চালু করুন"</string> <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"কখনও নয়"</string> <string name="zen_interruption_level_priority" msgid="2078370238113347720">"শুধুমাত্র অগ্রাধিকার"</string> <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index beb1ac546949..7874aeb02996 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -141,7 +141,7 @@ <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string> <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaciones y usuarios eliminados"</string> <string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string> - <string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión USB"</string> + <string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión a red por USB"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string> <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión Bluetooth"</string> <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Compartir conexión"</string> @@ -286,7 +286,7 @@ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Esperar que se conecte el depurador para iniciar la aplicación"</string> <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"Dibujo"</string> - <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Representación acelerada mediante hardware"</string> + <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Procesamiento acelerado mediante hardware"</string> <string name="media_category" msgid="4388305075496848353">"Multimedia"</string> <string name="debug_monitoring_category" msgid="7640508148375798343">"Supervisión"</string> <string name="strict_mode" msgid="1938795874357830695">"Modo estricto"</string> diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index 5ad9b0191c77..3d9a78e99204 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -76,7 +76,7 @@ <item msgid="3422726142222090896">"avrcp16"</item> </string-array> <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="7065842274271279580">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item> @@ -86,7 +86,7 @@ <item msgid="3304843301758635896">"वैकल्पिक कोडेक अक्षम करें"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="5062108632402595000">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item> @@ -96,38 +96,38 @@ <item msgid="741805482892725657">"वैकल्पिक कोडेक अक्षम करें"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> - <item msgid="3093023430402746802">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="3093023430402746802">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> <item msgid="2909915718994807056">"48.0 kHz"</item> <item msgid="3347287377354164611">"88.2 kHz"</item> <item msgid="1234212100239985373">"96.0 kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> - <item msgid="3214516120190965356">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="3214516120190965356">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="4482862757811638365">"44.1 kHz"</item> <item msgid="354495328188724404">"48.0 kHz"</item> <item msgid="7329816882213695083">"88.2 kHz"</item> <item msgid="6967397666254430476">"96.0 kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> - <item msgid="2684127272582591429">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="2684127272582591429">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="5618929009984956469">"16 बिट/नमूना"</item> <item msgid="3412640499234627248">"24 बिट/नमूना"</item> <item msgid="121583001492929387">"32 बिट/नमूना"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> - <item msgid="1081159789834584363">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="1081159789834584363">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="4726688794884191540">"16 बिट/नमूना"</item> <item msgid="305344756485516870">"24 बिट/नमूना"</item> <item msgid="244568657919675099">"32 बिट/नमूना"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> - <item msgid="5226878858503393706">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="5226878858503393706">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="4106832974775067314">"मोनो"</item> <item msgid="5571632958424639155">"स्टीरियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> - <item msgid="4118561796005528173">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="4118561796005528173">"सिस्टम चुनाव का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="8900559293912978337">"मोनो"</item> <item msgid="8883739882299884241">"स्टीरियो"</item> </string-array> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 5d512a84ef99..3a20d04d7ab2 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -46,7 +46,7 @@ <string name="wifi_limited_connection" msgid="7717855024753201527">"सीमित कनेक्शन"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट कनेक्शन नहीं है"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करना ज़रूरी है"</string> - <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस पॉइंट फ़िलहाल भरा हुआ है"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ऐक्सेस पॉइंट फ़िलहाल भरा हुआ है"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s के ज़रिए कनेक्ट"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string> <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> खोला जा रहा है"</string> @@ -68,7 +68,7 @@ <string name="bluetooth_pairing" msgid="1426882272690346242">"युग्मित कर रहा है…"</string> <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"जुड़ गया (मीडिया ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"जुड़ गया (मैसेज का एक्सेस नहीं)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"जुड़ गया (मैसेज का ऐक्सेस नहीं)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"जुड़ गया, बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string> <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string> @@ -88,7 +88,7 @@ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"संपर्क साझाकरण के लिए उपयोग करें"</string> <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"इंटरनेट कनेक्शन साझाकरण"</string> <string name="bluetooth_profile_map" msgid="1019763341565580450">"लेख संदेश"</string> - <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम एक्सेस"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम ऐक्सेस"</string> <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडियो"</string> <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"सुनने में मदद करने वाले डिवाइस"</string> @@ -200,7 +200,7 @@ <string name="development_settings_not_available" msgid="4308569041701535607">"यह उपयोगकर्ता, डेवलपर के लिए सेटिंग और टूल का इस्तेमाल नहीं कर सकता"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"टेदरिंग सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> - <string name="apn_settings_not_available" msgid="7873729032165324000">"एक्सेस पॉइंट के नाम की सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"ऐक्सेस पॉइंट के नाम की सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> <string name="enable_adb" msgid="7982306934419797485">"USB डीबग करना"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"डीबग मोड जब USB कनेक्ट किया गया हो"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करने की मंज़ूरी रद्द करें"</string> @@ -361,7 +361,7 @@ <string name="runningservices_settings_summary" msgid="854608995821032748">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string> <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबव्यू लागू करें"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबव्यू सेट करें"</string> - <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"यह चयन अब मान्य नहीं है. पुनः प्रयास करें."</string> + <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"यह चुनाव अब मान्य नहीं है. दोबारा कोशिश करें."</string> <string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल आधारित सुरक्षित करने के तरीके में बदलें"</string> <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string> <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string> @@ -414,7 +414,7 @@ <string name="disabled" msgid="9206776641295849915">"बंद किया गया"</string> <string name="external_source_trusted" msgid="2707996266575928037">"अनुमति है"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"अनुमति नहीं है"</string> - <string name="install_other_apps" msgid="6986686991775883017">"अनजान ऐप्लिकेशन इंस्टॉल करने का एक्सेस"</string> + <string name="install_other_apps" msgid="6986686991775883017">"अनजान ऐप्लिकेशन इंस्टॉल करने का ऐक्सेस"</string> <string name="home" msgid="3256884684164448244">"सेटिंग का होम पेज"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml index 5cffafed6689..7368f1d105f2 100644 --- a/packages/SettingsLib/res/values-hy/arrays.xml +++ b/packages/SettingsLib/res/values-hy/arrays.xml @@ -43,7 +43,7 @@ <item msgid="8937994881315223448">"Միացված է <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ին"</item> <item msgid="1330262655415760617">"Անջատված"</item> <item msgid="7698638434317271902">"Անջատվում է <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ից…"</item> - <item msgid="197508606402264311">"Անջատած է"</item> + <item msgid="197508606402264311">"Անջատված է"</item> <item msgid="8578370891960825148">"Անհաջող"</item> <item msgid="5660739516542454527">"Արգելափակված"</item> <item msgid="1805837518286731242">"Վատ ցանցից ժամանակավոր խուսափում"</item> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index bf587405c668..a74b4ae3ae9e 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -263,7 +263,7 @@ <string name="debug_view_attributes" msgid="6485448367803310384">"Միացնել ցուցադրման հատկանիշների ստուգումը"</string> <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Միշտ ակտիվացրած պահել բջջային տվյալները, նույնիսկ Wi‑Fi-ը միացրած ժամանակ (ցանցերի միջև արագ փոխարկման համար):"</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Օգտագործել սարքակազմի արագացման միացումը, եթե հասանելի է"</string> - <string name="adb_warning_title" msgid="6234463310896563253">"Թույլատրե՞լ USB-ի վրիպազերծումը:"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Թույլատրե՞լ USB վրիպազերծումը:"</string> <string name="adb_warning_message" msgid="7316799925425402244">"USB վրիպազերծումը միայն ծրագրավորման նպատակների համար է: Օգտագործեք այն ձեր համակարգչից տվյալները ձեր սարք պատճենելու համար, առանց ծանուցման ձեր սարքի վրա ծրագրեր տեղադրելու և տվյալների մատյանը ընթերցելու համար:"</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Փակե՞լ USB-ի վրիպազերծման մուտքը` անջատելով այն բոլոր համակարգիչներից, որտեղ նախկինում թույլատրել էիք:"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Ընդունե՞լ ծրագրավորման կարգավորումներ:"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index e5d29bff8b65..50543d8bfbee 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -385,10 +385,10 @@ <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(使用状況に基づく)(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) --> <skip /> - <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)"</string> - <string name="power_discharge_by" msgid="6453537733650125582">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only" msgid="107616694963545745">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)"</string> + <string name="power_discharge_by" msgid="6453537733650125582">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only" msgid="107616694963545745">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> まで"</string> <string name="power_suggestion_extend_battery" msgid="4401408879069551485">"<xliff:g id="TIME">%1$s</xliff:g>まで電池消費量を抑える"</string> <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index fd45cb0a1f3c..f1934c37369e 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -248,7 +248,7 @@ <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string> <string name="wifi_scan_throttling_summary" msgid="4461922728822495763">"ब्याट्रीको खपत कम गरी नेटवर्कको कार्यसम्पादनमा सुधार गर्दछ"</string> - <string name="wifi_metered_label" msgid="4514924227256839725">"मिटर गरिएको जडान भनी चिन्ह लगाइएको"</string> + <string name="wifi_metered_label" msgid="4514924227256839725">"सशुल्क वाइफाइ"</string> <string name="wifi_unmetered_label" msgid="6124098729457992931">"मिटर नगरिएको"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index cf442b73e721..0073003bdcca 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -159,7 +159,7 @@ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ஒலித்திறன்"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string> - <string name="tts_lang_use_system" msgid="2679252467416513208">"அமைப்பின் மொழியில்"</string> + <string name="tts_lang_use_system" msgid="2679252467416513208">"அமைப்பின் மொழியைப் பயன்படுத்தவும்"</string> <string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string> <string name="tts_default_lang_summary" msgid="5219362163902707785">"பேசப்படும் உரைக்கு மொழி சார்ந்த குரலை அமைக்கிறது"</string> <string name="tts_play_example_title" msgid="7094780383253097230">"எடுத்துக்காட்டைக் கவனிக்கவும்"</string> @@ -264,7 +264,7 @@ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"வைஃபை இயங்கும் போதும் (வேகமான நெட்வொர்க் மாற்றத்திற்கு), மொபைல் டேட்டாவை எப்போதும் இயக்கத்தில் வைக்கும்."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை கிடைக்கும் போது, அதைப் பயன்படுத்தும்"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைதிருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைதிருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் ஆப்ஸை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"நீங்கள் ஏற்கனவே அனுமதித்த எல்லா கணினிகளிலிருந்தும் USB பிழைத்திருத்தத்திற்கான அணுகலைத் திரும்பப்பெற வேண்டுமா?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"மேம்பட்ட அமைப்புகளை அனுமதிக்கவா?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 83636dc19beb..e591121d4b59 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -143,7 +143,7 @@ <string name="data_usage_ota" msgid="5377889154805560860">"సిస్టమ్ అప్డేట్లు"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB టీథరింగ్"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"పోర్టబుల్ హాట్స్పాట్"</string> - <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టీథరింగ్"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టెథెరింగ్"</string> <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"టీథరింగ్"</string> <string name="tether_settings_title_all" msgid="8356136101061143841">"టీథరింగ్ & పోర్టబుల్ హాట్స్పాట్"</string> <string name="managed_user_title" msgid="8109605045406748842">"అన్ని కార్యాలయ అనువర్తనాలు"</string> @@ -376,7 +376,7 @@ <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string> <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ ఫీచర్ ప్రయోగాత్మకమైనది, పనితీరుపై ప్రభావం చూపవచ్చు."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_settings_home_page" msgid="4845022416859002011">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="6123167166221295462">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> @@ -414,7 +414,7 @@ <string name="disabled" msgid="9206776641295849915">"నిలిపివేయబడింది"</string> <string name="external_source_trusted" msgid="2707996266575928037">"అనుమతించినవి"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"అనుమతించబడలేదు"</string> - <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్లను ఇన్స్టాల్ చేయండి"</string> + <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్లను ఇన్స్టాల్ చేయడం"</string> <string name="home" msgid="3256884684164448244">"సెట్టింగ్ల హోమ్"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 5dca4759a629..0d3e8de0559d 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -201,7 +201,7 @@ <string name="vpn_settings_not_available" msgid="956841430176985598">"Ushbu foydalanuvchi uchun VPN sozlamalari mavjud emas"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"Ushbu foydalanuvchi uchun Modem rejimi sozlamalari mavjud emas"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"Ushbu foydalanuvchi uchun Internetga kirish nuqtasi (APN) sozlamalari mavjud emas"</string> - <string name="enable_adb" msgid="7982306934419797485">"USB orqali nosozliklarni tuzatish"</string> + <string name="enable_adb" msgid="7982306934419797485">"USB orqali nosozliklarni aniqlash"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"USB orqali kompyuterga ulanganda tuzatish rejimi yoqilsin"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB orqali nosozliklarni tuzatishni taqiqlash"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"Xatoliklar hisoboti"</string> @@ -264,7 +264,7 @@ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mobil internet har doim yoniq tursin, hatto Wi-Fi yoniq bo‘lsa ham (bir tarmoqdan ikkinchisiga tezroq o‘tish uchun)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Modem rejimida apparatli tezlashtirishdan foydalanish (agar mavjud bo‘lsa)"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB orqali nosozliklarni tuzatish faqat dasturlash maqsadlarida yoqiladi. Undan ma‘lumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal ma‘lumotlarini o‘qish uchun foydalaniladi."</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB orqali nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal maʼlumotlarini o‘qish uchun foydalaniladi."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"USB orqali nosozliklarni tuzatishga berilgan ruxsat siz hisobingizga kirgan barcha kompyuterlar uchun bekor qilinsinmi?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Dasturlash sozlamalariga ruxsat berilsinmi?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"Bu sozlamalar faqat dasturlash maqsadlariga mo‘ljallangan. Shuning uchun, ular qurilmangizga va undagi ilovalariga shikast yetkazib, noto‘g‘ri ishlashiga sabab bo‘lishi mumkin."</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 4e2d6fa76ad0..5c06c80a049c 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -201,7 +201,7 @@ <string name="vpn_settings_not_available" msgid="956841430176985598">"Cài đặt VPN không khả dụng cho người dùng này"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"Cài đặt chia sẻ kết nối không khả dụng cho người dùng này"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"Cài đặt tên điểm truy cập không khả dụng cho người dùng này"</string> - <string name="enable_adb" msgid="7982306934419797485">"Gỡ lỗi USB"</string> + <string name="enable_adb" msgid="7982306934419797485">"Gỡ lỗi qua USB"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"Bật chế độ gỡ lỗi khi kết nối USB"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"Thu hồi ủy quyền gỡ lỗi USB"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"Phím tắt báo cáo lỗi"</string> @@ -263,7 +263,7 @@ <string name="debug_view_attributes" msgid="6485448367803310384">"Cho phép kiểm tra thuộc tính của chế độ xem"</string> <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Luôn bật dữ liệu di động ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ kết nối nếu có"</string> - <string name="adb_warning_title" msgid="6234463310896563253">"Cho phép gỡ lỗi USB?"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Cho phép gỡ lỗi qua USB?"</string> <string name="adb_warning_message" msgid="7316799925425402244">"Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Thu hồi quyền truy cập gỡ lỗi USB từ tất cả máy tính mà bạn đã ủy quyền trước đó?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Cho phép cài đặt phát triển?"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index e85199f9ca0d..c64130210d37 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -329,7 +329,7 @@ <string name="show_all_anrs" msgid="4924885492787069007">"顯示背景 ANR"</string> <string name="show_all_anrs_summary" msgid="6636514318275139826">"為背景應用程式顯示「應用程式無回應」對話方塊"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"顯示通知管道警告"</string> - <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發佈通知時,在畫面上顯示警告"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發布通知時,在畫面上顯示警告"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string> <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string> diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml index fc6397dc2013..96671c8c0175 100644 --- a/packages/Shell/res/values-zh-rTW/strings.xml +++ b/packages/Shell/res/values-zh-rTW/strings.xml @@ -25,9 +25,9 @@ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"系統即將在手機上顯示錯誤報告"</string> <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"選取即可分享錯誤報告"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕觸即可分享錯誤報告"</string> - <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕擷取畫面的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> <string name="bugreport_confirm" msgid="5917407234515812495">"錯誤報告的資料來自系統的各種記錄檔,當中可能包含敏感資料 (例如應用程式使用情形和位置資料)。請務必只與你信任的使用者和應用程式分享錯誤報告。"</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"不要再顯示"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string> @@ -35,9 +35,9 @@ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"無法在 ZIP 檔案中加入錯誤報告"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"未命名"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"詳細資料"</string> - <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕擷取畫面"</string> - <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕擷取畫面。"</string> - <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string> + <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕截圖"</string> + <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕截圖。"</string> + <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕截圖。"</string> <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string> <string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string> <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4f74605b4003..403e894a68e4 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -609,6 +609,10 @@ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden" android:process=":ui" android:visibleToInstantApps="true"> + <intent-filter> + <action android:name="android.intent.action.CHOOSER" /> + <category android:name="android.intent.category.VOICE" /> + </intent-filter> </activity> <!-- Doze with notifications, run in main sysui process for every user --> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 834f4fc75dce..638858a38335 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -14,6 +14,9 @@ package com.android.systemui.plugins.qs; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; import android.content.Context; import android.graphics.drawable.Drawable; import android.metrics.LogMaker; @@ -25,6 +28,7 @@ import com.android.systemui.plugins.qs.QSTile.Callback; import com.android.systemui.plugins.qs.QSTile.Icon; import com.android.systemui.plugins.qs.QSTile.State; +import java.lang.annotation.Retention; import java.util.Objects; import java.util.function.Supplier; @@ -72,6 +76,17 @@ public interface QSTile { return logMaker; } + @Retention(SOURCE) + @IntDef({COLOR_TILE_ACCENT, COLOR_TILE_RED, COLOR_TILE_BLUE, COLOR_TILE_YELLOW, + COLOR_TILE_GREEN}) + @interface ColorTile {} + int COLOR_TILE_ACCENT = 0; + int COLOR_TILE_RED = 1; + int COLOR_TILE_BLUE = 2; + int COLOR_TILE_YELLOW = 3; + int COLOR_TILE_GREEN = 4; + default void setColor(@ColorTile int color) {} + @ProvidesInterface(version = Callback.VERSION) public interface Callback { public static final int VERSION = 1; @@ -118,6 +133,7 @@ public interface QSTile { public SlashState slash; public boolean handlesLongClick = true; public boolean showRippleEffect = true; + public int colorActive = -1; public boolean copyTo(State other) { if (other == null) throw new IllegalArgumentException(); @@ -137,7 +153,8 @@ public interface QSTile { || !Objects.equals(other.dualTarget, dualTarget) || !Objects.equals(other.slash, slash) || !Objects.equals(other.handlesLongClick, handlesLongClick) - || !Objects.equals(other.showRippleEffect, showRippleEffect); + || !Objects.equals(other.showRippleEffect, showRippleEffect) + || !Objects.equals(other.colorActive, colorActive); other.icon = icon; other.iconSupplier = iconSupplier; other.label = label; @@ -152,6 +169,7 @@ public interface QSTile { other.slash = slash != null ? slash.copy() : null; other.handlesLongClick = handlesLongClick; other.showRippleEffect = showRippleEffect; + other.colorActive = colorActive; return changed; } diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index 0d88a2074efa..3adc2792ef10 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -41,7 +41,7 @@ <string name="keyguard_low_battery" msgid="9218432555787624490">"Připojte dobíjecí zařízení."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Klávesy odemknete stisknutím tlačítka nabídky."</string> <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Síť je blokována"</string> - <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Není vložena SIM karta"</string> + <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Chybí SIM karta"</string> <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"V tabletu není SIM karta."</string> <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"V telefonu není SIM karta."</string> <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Vložte SIM kartu."</string> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index 22c4c48a7e37..9c9de22b96d9 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -37,7 +37,7 @@ <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ بیسیم"</string> <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string> - <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ آهسته"</string> + <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهستهآهسته شارژ میشود"</string> <string name="keyguard_low_battery" msgid="9218432555787624490">"شارژر را وصل کنید."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"برای باز کردن قفل روی «منو» فشار دهید."</string> <string name="keyguard_network_locked_message" msgid="6743537524631420759">"شبکه قفل شد"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index dcd31bda79b3..36745648b051 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -329,7 +329,7 @@ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Вызначэнне месцазнаходжання адключана"</string> <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Мультымедыйная прылада"</string> <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string> - <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Толькі экстраныя выклікі"</string> + <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Толькі экстранныя выклікі"</string> <string name="quick_settings_settings_label" msgid="5326556592578065401">"Налады"</string> <string name="quick_settings_time_label" msgid="4635969182239736408">"Час"</string> <string name="quick_settings_user_label" msgid="5238995632130897840">"Я"</string> @@ -423,7 +423,7 @@ <string name="keyguard_indication_charging_time_wireless" msgid="6959284458466962592">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе бесправадная зарадка (да поўнага зараду засталося <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string> <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Ідзе зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string> <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Ідзе хуткая зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string> - <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string> + <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> да канца)"</string> <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Перайсці да іншага карыстальніка"</string> <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Перайсці да іншага карыстальніка, бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 5141b57ec295..6b7561bdcd3b 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -232,9 +232,9 @@ <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"বিমান মোড চালু হয়েছে।"</string> <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"সম্পূর্ণ নীরব"</string> <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"শুধুমাত্র অ্যালার্ম"</string> - <string name="accessibility_quick_settings_dnd" msgid="5555155552520665891">"বিরক্ত করবেন না।"</string> - <string name="accessibility_quick_settings_dnd_changed_off" msgid="2757071272328547807">"\'বিরক্ত করবেন না\' বন্ধ আছে।"</string> - <string name="accessibility_quick_settings_dnd_changed_on" msgid="6808220653747701059">"\'বিরক্ত করবেন না\' চালু করা হয়েছে।"</string> + <string name="accessibility_quick_settings_dnd" msgid="5555155552520665891">"বিরক্ত করবে না।"</string> + <string name="accessibility_quick_settings_dnd_changed_off" msgid="2757071272328547807">"\'বিরক্ত করবে না\' বন্ধ আছে।"</string> + <string name="accessibility_quick_settings_dnd_changed_on" msgid="6808220653747701059">"\'বিরক্ত করবে না\' চালু করা হয়েছে।"</string> <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"ব্লুটুথ"</string> <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ব্লুটুথ বন্ধ আছে।"</string> <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ব্লুটুথ চালু আছে।"</string> @@ -299,7 +299,7 @@ <string name="start_dreams" msgid="5640361424498338327">"স্ক্রিন সেভার"</string> <string name="ethernet_label" msgid="7967563676324087464">"ইথারনেট"</string> <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"আরও বিকল্পের জন্য আইকনগুলি টাচ করে ধরে থাকুন"</string> - <string name="quick_settings_dnd_label" msgid="7112342227663678739">"বিরক্ত করবেন না"</string> + <string name="quick_settings_dnd_label" msgid="7112342227663678739">"বিরক্ত করবে না"</string> <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"শুধুমাত্র অগ্রাধিকার"</string> <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"শুধুমাত্র অ্যালার্মগুলি"</string> <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"একদম নিরব"</string> @@ -461,7 +461,7 @@ <string name="manage_notifications_text" msgid="2386728145475108753">"পরিচালনা করুন"</string> <string name="notification_section_header_gentle" msgid="4372438504154095677">"নীরব বিজ্ঞপ্তি"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"সব নীরব বিজ্ঞপ্তি মুছুন"</string> - <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'বিরক্ত করবেন না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string> + <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'বিরক্ত করবে না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string> <string name="media_projection_action_text" msgid="8470872969457985954">"এখন শুরু করুন"</string> <string name="empty_shade_text" msgid="708135716272867002">"কোনো বিজ্ঞপ্তি নেই"</string> <string name="profile_owned_footer" msgid="8021888108553696069">"প্রোফাইল পর্যবেক্ষণ করা হতে পারে"</string> @@ -737,9 +737,9 @@ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ক্যালেন্ডার"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string> - <string name="volume_and_do_not_disturb" msgid="1750270820297253561">"বিরক্ত করবেন না"</string> + <string name="volume_and_do_not_disturb" msgid="1750270820297253561">"বিরক্ত করবে না"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"ভলিউম বোতামের শর্টকাট"</string> - <string name="volume_up_silent" msgid="7545869833038212815">"ভলিউম বাড়িয়ে \'বিরক্ত করবেন না\' মোড থেকে বেরিয়ে আসুন"</string> + <string name="volume_up_silent" msgid="7545869833038212815">"ভলিউম বাড়িয়ে \'বিরক্ত করবে না\' মোড থেকে বেরিয়ে আসুন"</string> <string name="battery" msgid="7498329822413202973">"ব্যাটারি"</string> <string name="clock" msgid="7416090374234785905">"ঘড়ি"</string> <string name="headset" msgid="4534219457597457353">"হেডসেট"</string> @@ -883,10 +883,10 @@ <string name="mobile_carrier_text_format" msgid="3241721038678469804">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string> <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string> <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string> - <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবেন না বিকল্পটি বন্ধ আছে"</string> - <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string> - <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"বিরক্ত করবেন না বিকল্পটি একটি অ্যাপ <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string> - <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে।"</string> + <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবে না বিকল্পটি বন্ধ আছে"</string> + <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"বিরক্ত করবে না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string> + <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"বিরক্ত করবে না বিকল্পটি একটি অ্যাপ <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string> + <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"বিরক্ত করবে না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে।"</string> <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> পর্যন্ত"</string> <string name="qs_dnd_keep" msgid="1825009164681928736">"রাখুন"</string> <string name="qs_dnd_replace" msgid="8019520786644276623">"বদলে দিন"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index abea52a0adf8..87aaa94d1dd3 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -194,7 +194,7 @@ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Sdílené připojení přes Bluetooth."</string> <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim Letadlo."</string> <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN je zapnuto."</string> - <string name="accessibility_no_sims" msgid="3957997018324995781">"Není vložena SIM karta"</string> + <string name="accessibility_no_sims" msgid="3957997018324995781">"Chybí SIM karta"</string> <string name="carrier_network_change_mode" msgid="8149202439957837762">"Probíhá změna sítě operátora"</string> <string name="accessibility_battery_details" msgid="7645516654955025422">"Otevřít podrobnosti o baterii"</string> <string name="accessibility_battery_level" msgid="7451474187113371965">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 6a97ee6e9352..57c934e5657d 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -215,7 +215,7 @@ <skip /> <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifikationen er annulleret."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notifikationspanel."</string> - <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hurtige indstillinger."</string> + <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Kvikmenu."</string> <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Låseskærm."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"Indstillinger"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Oversigt."</string> @@ -588,7 +588,7 @@ <string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string> <string name="show_battery_percentage" msgid="5444136600512968798">"Vis procent for det indbyggede batteri"</string> <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis procenttallet for batteriniveauet i ikonet for statusbjælken, når der ikke oplades"</string> - <string name="quick_settings" msgid="10042998191725428">"Hurtige indstillinger"</string> + <string name="quick_settings" msgid="10042998191725428">"Kvikmenu"</string> <string name="status_bar" msgid="4877645476959324760">"Statusbjælke"</string> <string name="overview" msgid="4018602013895926956">"Oversigt"</string> <string name="demo_mode" msgid="2532177350215638026">"Demotilstand for systemets brugerflade"</string> @@ -604,7 +604,7 @@ <string name="zen_alarm_warning" msgid="444533119582244293">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="alarm_template" msgid="3980063409350522735">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="alarm_template_far" msgid="4242179982586714810">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string> - <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Hurtige indstillinger <xliff:g id="TITLE">%s</xliff:g>."</string> + <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Kvikmenu <xliff:g id="TITLE">%s</xliff:g>."</string> <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"Arbejdsprofil"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"Sjovt for nogle, men ikke for alle"</string> @@ -617,8 +617,8 @@ <string name="activity_not_found" msgid="348423244327799974">"Applikationen er ikke installeret på din enhed."</string> <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string> - <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string> - <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string> + <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Kvikmenu"</string> + <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Kvikmenu"</string> <string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string> <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string> <string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string> @@ -813,15 +813,15 @@ <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Føj <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string> - <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj for Hurtige indstillinger."</string> + <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj til Kvikmenu."</string> <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen fungerer muligvis ikke i opdelt skærm."</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen understøtter ikke opdelt skærm."</string> <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"Appen fungerer muligvis ikke på sekundære skærme."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Appen kan ikke åbnes på sekundære skærme."</string> <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Åbn Indstillinger."</string> - <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Åbn Hurtige indstillinger."</string> - <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Luk Hurtige indstillinger."</string> + <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Åbn Kvikmenu."</string> + <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Luk Kvikmenu."</string> <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Alarmen er indstillet."</string> <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"Logget ind som <xliff:g id="ID_1">%s</xliff:g>"</string> <string name="data_connection_no_internet" msgid="4503302451650972989">"Intet internet"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 9903cc04e97a..938cb0dd3b12 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -401,6 +401,7 @@ <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string> <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string> <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string> + <string name="keyguard_retry" msgid="5221600879614948709">"Swipe up to try again"</string> <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string> <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string> @@ -544,6 +545,7 @@ <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string> <string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string> <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"To unpin this screen, touch & hold Back and Home buttons"</string> + <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"To unpin this screen, swipe up & hold"</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string> <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string> <string name="screen_pinning_start" msgid="1022122128489278317">"Screen pinned"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index d8c862affe08..139215aa196f 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -401,6 +401,7 @@ <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string> <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string> <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string> + <string name="keyguard_retry" msgid="5221600879614948709">"Swipe up to try again"</string> <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string> <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string> @@ -544,6 +545,7 @@ <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string> <string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string> <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"To unpin this screen, touch & hold Back and Home buttons"</string> + <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"To unpin this screen, swipe up & hold"</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string> <string name="screen_pinning_negative" msgid="3741602308343880268">"No thanks"</string> <string name="screen_pinning_start" msgid="1022122128489278317">"Screen pinned"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 137b780fee2a..e8e4232063e3 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -417,7 +417,7 @@ <string name="keyguard_indication_charging_time_wireless" msgid="6959284458466962592">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • En recharge sans fil (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à la recharge complète)"</string> <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à charge complète)"</string> <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string> - <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string> + <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string> <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string> <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string> <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 15d9c2b6167a..5480eab8cf65 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -599,7 +599,7 @@ <string name="status_bar_work" msgid="6022553324802866373">"Perfil de traballo"</string> <string name="status_bar_airplane" msgid="7057575501472249002">"Modo avión"</string> <string name="add_tile" msgid="2995389510240786221">"Engade un atallo"</string> - <string name="broadcast_tile" msgid="3894036511763289383">"Atallo de emisión"</string> + <string name="broadcast_tile" msgid="3894036511763289383">"Atallo de difusión"</string> <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g> a menos que desactives esta opción antes desa hora"</string> <string name="zen_alarm_warning" msgid="444533119582244293">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="alarm_template" msgid="3980063409350522735">"ás <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index f90f494fe3a2..1a15cf705d91 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -314,7 +314,7 @@ <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="4930931771490695395">"શ્રવણ યંત્રો"</string> <string name="quick_settings_bluetooth_secondary_label_transient" msgid="4551281899312150640">"ચાલુ કરી રહ્યાં છીએ…"</string> <string name="quick_settings_brightness_label" msgid="6968372297018755815">"તેજ"</string> - <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"આપમેળે ફેરવો"</string> + <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ઑટો રોટેટ"</string> <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"સ્ક્રીનને આપમેળે ફેરવો"</string> <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> મોડ"</string> <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"પરિભ્રમણ લૉક થયું"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 5f47e20e7466..3e3696b45ad9 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -647,7 +647,7 @@ <string name="inline_minimize_button" msgid="966233327974702195">"Kis méret"</string> <string name="inline_silent_button_silent" msgid="5315879183296940969">"Néma"</string> <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"Néma megjelenítés"</string> - <string name="inline_silent_button_alert" msgid="6008435419895088034">"Értesítések"</string> + <string name="inline_silent_button_alert" msgid="6008435419895088034">"Figyelemfelkeltő"</string> <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"Értesítések folytatása"</string> <string name="inline_turn_off_notifications" msgid="8635596135532202355">"Az értesítések kikapcsolása"</string> <string name="inline_keep_showing_app" msgid="1723113469580031041">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string> diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index 7b55d18676da..0febc8ed4262 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -83,4 +83,9 @@ <color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal --> <color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 --> + <color name="GM2_green_500">#FF41Af6A</color> + <color name="GM2_blue_500">#5195EA</color> + <color name="GM2_red_500">#E25142</color> + <color name="GM2_yellow_500">#F5C518</color> + </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 3760007b2291..e9b150c1a66e 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -250,9 +250,9 @@ <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"ପ୍ୟାନେଲ୍ ବନ୍ଦ କରନ୍ତୁ।"</string> <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ଅଧିକ ସମୟ।"</string> <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"କମ୍ ସମୟ।"</string> - <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ଫ୍ଲାଶ୍ଲାଇଟ୍ ଅଫ୍ ଅଛି।"</string> + <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ଫ୍ଲାସ୍ଲାଇଟ୍ ବନ୍ଦ ଅଛି।"</string> <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଅନୁପଲବ୍ଧ।"</string> - <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ଫ୍ଲାଶ୍ଲାଇଟ୍ ଅନ୍ ଅଛି।"</string> + <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ଫ୍ଲାସ୍ଲାଇଟ୍ ଚାଲୁଅଛି।"</string> <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ବନ୍ଦ ଅଛି।"</string> <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଅନ୍ ଅଛି।"</string> <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"ରଙ୍ଗ ବିପରୀତିକରଣକୁ ବନ୍ଦ କରିଦିଆଗଲା।"</string> @@ -362,7 +362,7 @@ <item quantity="one">%d ଡିଭାଇସ୍</item> </plurals> <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ବିଜ୍ଞପ୍ତି"</string> - <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାଶ୍ଲାଇଟ"</string> + <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାସ୍ଲାଇଟ୍"</string> <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ମୋବାଇଲ୍ ଡାଟା"</string> <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ଡାଟାର ବ୍ୟବହାର"</string> <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ଅବଶିଷ୍ଟ ଡାଟା"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 93a2c124782a..4be1a0f3aa17 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -465,10 +465,10 @@ <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Podczas nagrywania lub przesyłania usługa udostępniająca tę funkcję może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string> <string name="media_projection_dialog_title" msgid="8124184308671641248">"Ujawnianie poufnych informacji podczas przesyłania/nagrywania"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Nie pokazuj ponownie"</string> - <string name="clear_all_notifications_text" msgid="814192889771462828">"Ukryj wszystkie"</string> + <string name="clear_all_notifications_text" msgid="814192889771462828">"Usuń wszystkie"</string> <string name="manage_notifications_text" msgid="2386728145475108753">"Zarządzaj"</string> - <string name="notification_section_header_gentle" msgid="4372438504154095677">"Powiadomienia ciche"</string> - <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Wyczyść wszystkie ciche powiadomienia"</string> + <string name="notification_section_header_gentle" msgid="4372438504154095677">"Ciche powiadomienia"</string> + <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Usuń wszystkie ciche powiadomienia"</string> <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string> <string name="media_projection_action_text" msgid="8470872969457985954">"Rozpocznij teraz"</string> <string name="empty_shade_text" msgid="708135716272867002">"Brak powiadomień"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index d56ccefba43d..2b12149e06ad 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -845,7 +845,7 @@ <string name="pip_skip_to_prev" msgid="1955311326688637914">"முந்தையதற்குச் செல்"</string> <string name="thermal_shutdown_title" msgid="4458304833443861111">"வெப்பத்தினால் ஃபோன் ஆஃப் செய்யப்பட்டது"</string> <string name="thermal_shutdown_message" msgid="9006456746902370523">"இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது"</string> - <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n • அதிகளவு தரவைப் பயன்படுத்தும் பயன்பாடுகளை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் பயன்பாடுகள்) பயன்படுத்துவது\n • பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n • அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string> + <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n • அதிகளவு தரவைப் பயன்படுத்தும் ஆப்ஸை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் பயன்பாடுகள்) பயன்படுத்துவது\n • பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n • அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string> <string name="high_temp_title" msgid="4589508026407318374">"மொபைல் சூடாகிறது"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"மொபைலின் வெப்ப அளவு குறையும் போது, சில அம்சங்களைப் பயன்படுத்த முடியாது"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 6f38b18693d3..d3caa2b2c75d 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -55,11 +55,11 @@ <string name="label_view" msgid="6304565553218192990">"Xem"</string> <string name="always_use_device" msgid="4015357883336738417">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string> <string name="always_use_accessory" msgid="3257892669444535154">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string> - <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi USB?"</string> + <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi qua USB?"</string> <string name="usb_debugging_message" msgid="2220143855912376496">"Tệp tham chiếu khóa RSA của máy tính là:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Luôn cho phép từ máy tính này"</string> <string name="usb_debugging_allow" msgid="2272145052073254852">"Cho phép"</string> - <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Tính năng gỡ lỗi USB không được phép"</string> + <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Không cho phép chế độ gỡ lỗi qua USB"</string> <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi USB. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string> <string name="usb_contaminant_title" msgid="206854874263058490">"Đã tắt cổng USB"</string> <string name="usb_contaminant_message" msgid="7379089091591609111">"Để bảo vệ thiết bị của bạn khỏi chất lỏng hay mảnh vỡ, cổng USB sẽ tắt và không phát hiện được bất kỳ phụ kiện nào.\n\nBạn sẽ nhận được thông báo khi có thể sử dụng lại cổng USB."</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 03e31cdc7ee6..457206dc9dc1 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -264,8 +264,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已關閉。"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已開啟。"</string> - <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver 已關閉。"</string> - <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver 已開啟。"</string> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"數據節省模式已關閉。"</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"數據節省模式已開啟。"</string> <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="5152819588955163090">"已關閉感應器隱私設定。"</string> <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="529705259565826355">"已開啟感應器隱私設定。"</string> <string name="accessibility_brightness" msgid="8003681285547803095">"螢幕亮度"</string> @@ -459,8 +459,8 @@ <string name="media_projection_remember_text" msgid="3103510882172746752">"不要再顯示"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string> <string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string> - <string name="notification_section_header_gentle" msgid="4372438504154095677">"無聲通知"</string> - <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"清除所有無聲通知"</string> + <string name="notification_section_header_gentle" msgid="4372438504154095677">"靜音通知"</string> + <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"清除所有靜音通知"</string> <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"「零打擾」模式已將通知設為暫停"</string> <string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string> <string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string> @@ -645,7 +645,7 @@ <string name="inline_block_button" msgid="8735843688021655065">"封鎖"</string> <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string> <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string> - <string name="inline_silent_button_silent" msgid="5315879183296940969">"無聲"</string> + <string name="inline_silent_button_silent" msgid="5315879183296940969">"靜音"</string> <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"繼續顯示通知但不發出音效"</string> <string name="inline_silent_button_alert" msgid="6008435419895088034">"快訊"</string> <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"繼續顯示通知"</string> @@ -747,8 +747,8 @@ <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已與耳機連線"</string> <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已與耳機連線"</string> <string name="data_saver" msgid="5037565123367048522">"數據節省模式"</string> - <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver 已開啟"</string> - <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver 已關閉"</string> + <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省模式已開啟"</string> + <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省模式已關閉"</string> <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string> <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string> <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 61816f60d0ba..bda1c52f27c0 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -204,4 +204,6 @@ <color name="GM2_yellow_500">#FFFBBC04</color> <color name="GM2_green_500">#FF34A853</color> + <color name="GM2_blue_500">#FF4285F4</color> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java new file mode 100644 index 000000000000..0e079e36a175 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import android.annotation.NonNull; +import android.app.Notification; +import android.os.Handler; +import android.os.Looper; +import android.util.ArraySet; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.statusbar.NotificationLifetimeExtender; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +/** + * Extends the lifetime of foreground notification services such that they show for at least + * five seconds + */ +public class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender { + + private static final String TAG = "FGSLifetimeExtender"; + @VisibleForTesting + static final int MIN_FGS_TIME_MS = 5000; + + private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback; + private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>(); + private Handler mHandler = new Handler(Looper.getMainLooper()); + + public ForegroundServiceLifetimeExtender() { + } + + @Override + public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) { + mNotificationSafeToRemoveCallback = callback; + } + + @Override + public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) { + if ((entry.notification.getNotification().flags + & Notification.FLAG_FOREGROUND_SERVICE) == 0) { + return false; + } + + long currentTime = System.currentTimeMillis(); + return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS; + } + + @Override + public boolean shouldExtendLifetimeForPendingNotification( + @NonNull NotificationEntry entry) { + return shouldExtendLifetime(entry); + } + + @Override + public void setShouldManageLifetime( + @NonNull NotificationEntry entry, boolean shouldManage) { + if (!shouldManage) { + mManagedEntries.remove(entry); + return; + } + + mManagedEntries.add(entry); + + Runnable r = () -> { + if (mManagedEntries.contains(entry)) { + mManagedEntries.remove(entry); + if (mNotificationSafeToRemoveCallback != null) { + mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key); + } + } + }; + mHandler.postDelayed(r, MIN_FGS_TIME_MS); + } +} + diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index 96b62ac918ab..f9d877142d21 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -50,12 +50,12 @@ public class ForegroundServiceNotificationListener { notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { @Override public void onPendingEntryAdded(NotificationEntry entry) { - addNotification(entry.notification, entry.importance); + addNotification(entry.notification, entry.getImportance()); } @Override public void onPostEntryUpdated(NotificationEntry entry) { - updateNotification(entry.notification, entry.importance); + updateNotification(entry.notification, entry.getImportance()); } @Override @@ -66,6 +66,9 @@ public class ForegroundServiceNotificationListener { removeNotification(entry.notification); } }); + + notificationEntryManager.addNotificationLifetimeExtender( + new ForegroundServiceLifetimeExtender()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java index 33950144ac19..ff4eb83bd796 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.PackageManager; +import com.android.systemui.assist.AssistModule; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.KeyguardLiftController; @@ -34,7 +35,7 @@ import dagger.Provides; * A dagger module for injecting components of System UI that are not overridden by the System UI * implementation. */ -@Module +@Module(includes = {AssistModule.class}) public abstract class SystemUIModule { @Singleton diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java index 38ca70865a58..9bdfa03408aa 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java @@ -16,6 +16,8 @@ package com.android.systemui.assist; +import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME; + import android.content.ComponentName; import android.content.Context; import android.os.Handler; @@ -28,20 +30,21 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.AssistUtils; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.Dependency; import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.ScreenDecorations; -import com.android.systemui.SysUiServiceProvider; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.phone.NavigationModeController; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.EnumMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; /** * A class for managing Assistant handle logic. @@ -49,6 +52,7 @@ import java.util.function.Supplier; * Controls when visual handles for Assistant gesture affordance should be shown or hidden using an * {@link AssistHandleBehavior}. */ +@Singleton public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable { private static final String TAG = "AssistHandleBehavior"; @@ -67,10 +71,9 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac private final Handler mHandler; private final Runnable mHideHandles = this::hideHandles; private final Runnable mShowAndGo = this::showAndGoInternal; - private final Supplier<ScreenDecorations> mScreenDecorationsSupplier; + private final Provider<ScreenDecorations> mScreenDecorations; private final PhenotypeHelper mPhenotypeHelper; - private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap = - new EnumMap<>(AssistHandleBehavior.class); + private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap; private boolean mHandlesShowing = false; private long mHandlesLastHiddenAt; @@ -82,41 +85,25 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF; private boolean mInGesturalMode; - AssistHandleBehaviorController(Context context, AssistUtils assistUtils, Handler handler) { - this( - context, - assistUtils, - handler, - () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class), - new PhenotypeHelper(), - /* testBehavior = */ null); - } - - @VisibleForTesting + @Inject AssistHandleBehaviorController( Context context, AssistUtils assistUtils, - Handler handler, - Supplier<ScreenDecorations> screenDecorationsSupplier, + @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler, + Provider<ScreenDecorations> screenDecorations, PhenotypeHelper phenotypeHelper, - @Nullable BehaviorController testBehavior) { + Map<AssistHandleBehavior, BehaviorController> behaviorMap, + NavigationModeController navigationModeController, + DumpController dumpController) { mContext = context; mAssistUtils = assistUtils; mHandler = handler; - mScreenDecorationsSupplier = screenDecorationsSupplier; + mScreenDecorations = screenDecorations; mPhenotypeHelper = phenotypeHelper; - mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior()); - mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior()); - mBehaviorMap.put( - AssistHandleBehavior.REMINDER_EXP, - new AssistHandleReminderExpBehavior(handler, phenotypeHelper)); - if (testBehavior != null) { - mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior); - } + mBehaviorMap = behaviorMap; mInGesturalMode = QuickStepContract.isGesturalMode( - Dependency.get(NavigationModeController.class) - .addListener(this::handleNavigationModeChange)); + navigationModeController.addListener(this::handleNavigationModeChange)); setBehavior(getBehaviorMode()); mPhenotypeHelper.addOnPropertiesChangedListener( @@ -128,7 +115,8 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null)); } }); - Dependency.get(DumpController.class).registerDumpable(TAG, this); + + dumpController.registerDumpable(TAG, this); } @Override // AssistHandleCallbacks @@ -241,7 +229,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac } if (handlesUnblocked(ignoreThreshold)) { - ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get(); + ScreenDecorations screenDecorations = mScreenDecorations.get(); if (screenDecorations == null) { Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable"); } else { @@ -256,7 +244,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac return; } - ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get(); + ScreenDecorations screenDecorations = mScreenDecorations.get(); if (screenDecorations == null) { Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable"); } else { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java index 763315d2c4e2..a0d8b4c58f1a 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java @@ -20,56 +20,82 @@ import android.content.Context; import androidx.annotation.Nullable; -import com.android.systemui.Dependency; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; -import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; import java.io.PrintWriter; +import javax.inject.Inject; +import javax.inject.Singleton; + +import dagger.Lazy; + /** * Assistant Handle behavior that makes Assistant handles show/hide when the home handle is * shown/hidden, respectively. */ +@Singleton final class AssistHandleLikeHomeBehavior implements BehaviorController { - private final StatusBarStateController.StateListener mStatusBarStateListener = - new StatusBarStateController.StateListener() { + private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver = + new WakefulnessLifecycle.Observer() { + @Override + public void onStartedWakingUp() { + handleDozingChanged(/* isDozing = */ true); + } + + @Override + public void onFinishedWakingUp() { + handleDozingChanged(/* isDozing = */ false); + } + + @Override + public void onStartedGoingToSleep() { + handleDozingChanged(/* isDozing = */ true); + } + @Override - public void onDozingChanged(boolean isDozing) { - handleDozingChanged(isDozing); + public void onFinishedGoingToSleep() { + handleDozingChanged(/* isDozing = */ true); } }; private final SysUiState.SysUiStateCallback mSysUiStateCallback = this::handleSystemUiStateChange; - private final StatusBarStateController mStatusBarStateController; - private final SysUiState mSysUiFlagContainer; + + private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle; + private final Lazy<SysUiState> mSysUiFlagContainer; private boolean mIsDozing; private boolean mIsHomeHandleHiding; @Nullable private AssistHandleCallbacks mAssistHandleCallbacks; - AssistHandleLikeHomeBehavior() { - mStatusBarStateController = Dependency.get(StatusBarStateController.class); - mSysUiFlagContainer = Dependency.get(SysUiState.class); + @Inject + AssistHandleLikeHomeBehavior( + Lazy<WakefulnessLifecycle> wakefulnessLifecycle, + Lazy<SysUiState> sysUiFlagContainer) { + mWakefulnessLifecycle = wakefulnessLifecycle; + mSysUiFlagContainer = sysUiFlagContainer; } @Override public void onModeActivated(Context context, AssistHandleCallbacks callbacks) { mAssistHandleCallbacks = callbacks; - mIsDozing = mStatusBarStateController.isDozing(); - mStatusBarStateController.addCallback(mStatusBarStateListener); - mSysUiFlagContainer.addCallback(mSysUiStateCallback); + mIsDozing = mWakefulnessLifecycle.get().getWakefulness() + != WakefulnessLifecycle.WAKEFULNESS_AWAKE; + mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver); + mSysUiFlagContainer.get().addCallback(mSysUiStateCallback); callbackForCurrentState(); } @Override public void onModeDeactivated() { mAssistHandleCallbacks = null; - mSysUiFlagContainer.removeCallback(mSysUiStateCallback); + mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver); + mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback); } private static boolean isHomeHandleHiding(int sysuiStateFlags) { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java index f4130aeb1d08..df913f9ce9cd 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java @@ -20,9 +20,17 @@ import android.content.Context; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; +import javax.inject.Inject; +import javax.inject.Singleton; + /** Assistant handle behavior that hides the Assistant handles. */ +@Singleton final class AssistHandleOffBehavior implements BehaviorController { + @Inject + AssistHandleOffBehavior() { + } + @Override public void onModeActivated(Context context, AssistHandleCallbacks callbacks) { callbacks.hide(); diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index 5dd3cb1d8bdc..d371dbead42b 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -16,7 +16,8 @@ package com.android.systemui.assist; -import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME; +import static com.android.systemui.assist.AssistModule.UPTIME_NAME; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -26,14 +27,14 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ResolveInfo; import android.os.Handler; -import android.os.SystemClock; import android.provider.Settings; import androidx.annotation.Nullable; +import androidx.slice.Clock; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; -import com.android.systemui.Dependency; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; @@ -49,11 +50,18 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Lazy; + /** * Assistant handle behavior that hides the handles when the phone is dozing or in immersive mode, * shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or * entering overview. */ +@Singleton final class AssistHandleReminderExpBehavior implements BehaviorController { private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed"; @@ -86,11 +94,6 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { public void onStateChanged(int newState) { handleStatusBarStateChanged(newState); } - - @Override - public void onDozingChanged(boolean isDozing) { - handleDozingChanged(isDozing); - } }; private final TaskStackChangeListener mTaskStackChangeListener = new TaskStackChangeListener() { @@ -111,9 +114,20 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { handleOverviewShown(); } }; - private final SysUiState.SysUiStateCallback mSysUiStateCallback = this::handleSystemUiStateChanged; + private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver = + new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedWakingUp() { + handleDozingChanged(false); + } + + @Override + public void onStartedGoingToSleep() { + handleDozingChanged(true); + } + }; private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -123,12 +137,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { private final IntentFilter mDefaultHomeIntentFilter; private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches; + private final Clock mClock; private final Handler mHandler; private final PhenotypeHelper mPhenotypeHelper; - private final StatusBarStateController mStatusBarStateController; - private final ActivityManagerWrapper mActivityManagerWrapper; - private final OverviewProxyService mOverviewProxyService; - private final SysUiState mSysUiFlagContainer; + private final Lazy<StatusBarStateController> mStatusBarStateController; + private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper; + private final Lazy<OverviewProxyService> mOverviewProxyService; + private final Lazy<SysUiState> mSysUiFlagContainer; + private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle; + private final Lazy<PackageManagerWrapper> mPackageManagerWrapper; private boolean mOnLockscreen; private boolean mIsDozing; @@ -150,13 +167,26 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { @Nullable private AssistHandleCallbacks mAssistHandleCallbacks; @Nullable private ComponentName mDefaultHome; - AssistHandleReminderExpBehavior(Handler handler, PhenotypeHelper phenotypeHelper) { + @Inject + AssistHandleReminderExpBehavior( + @Named(UPTIME_NAME) Clock clock, + @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler, + PhenotypeHelper phenotypeHelper, + Lazy<StatusBarStateController> statusBarStateController, + Lazy<ActivityManagerWrapper> activityManagerWrapper, + Lazy<OverviewProxyService> overviewProxyService, + Lazy<SysUiState> sysUiFlagContainer, + Lazy<WakefulnessLifecycle> wakefulnessLifecycle, + Lazy<PackageManagerWrapper> packageManagerWrapper) { + mClock = clock; mHandler = handler; mPhenotypeHelper = phenotypeHelper; - mStatusBarStateController = Dependency.get(StatusBarStateController.class); - mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); - mOverviewProxyService = Dependency.get(OverviewProxyService.class); - mSysUiFlagContainer = Dependency.get(SysUiState.class); + mStatusBarStateController = statusBarStateController; + mActivityManagerWrapper = activityManagerWrapper; + mOverviewProxyService = overviewProxyService; + mSysUiFlagContainer = sysUiFlagContainer; + mWakefulnessLifecycle = wakefulnessLifecycle; + mPackageManagerWrapper = packageManagerWrapper; mDefaultHomeIntentFilter = new IntentFilter(); for (String action : DEFAULT_HOME_CHANGE_ACTIONS) { mDefaultHomeIntentFilter.addAction(action); @@ -170,14 +200,17 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { mConsecutiveTaskSwitches = 0; mDefaultHome = getCurrentDefaultHome(); context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter); - mOnLockscreen = onLockscreen(mStatusBarStateController.getState()); - mIsDozing = mStatusBarStateController.isDozing(); - mStatusBarStateController.addCallback(mStatusBarStateListener); - ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask(); + mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState()); + mStatusBarStateController.get().addCallback(mStatusBarStateListener); + ActivityManager.RunningTaskInfo runningTaskInfo = + mActivityManagerWrapper.get().getRunningTask(); mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId; - mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener); - mOverviewProxyService.addCallback(mOverviewProxyListener); - mSysUiFlagContainer.addCallback(mSysUiStateCallback); + mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener); + mOverviewProxyService.get().addCallback(mOverviewProxyListener); + mSysUiFlagContainer.get().addCallback(mSysUiStateCallback); + mIsDozing = mWakefulnessLifecycle.get().getWakefulness() + != WakefulnessLifecycle.WAKEFULNESS_AWAKE; + mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver); mLearningTimeElapsed = Settings.Secure.getLong( context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0); @@ -185,7 +218,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0); mLearnedHintLastShownEpochDay = Settings.Secure.getLong( context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0); - mLastLearningTimestamp = SystemClock.uptimeMillis(); + mLastLearningTimestamp = mClock.currentTimeMillis(); callbackForCurrentState(/* justUnlocked = */ false); } @@ -200,10 +233,11 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0); mContext = null; } - mStatusBarStateController.removeCallback(mStatusBarStateListener); - mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener); - mOverviewProxyService.removeCallback(mOverviewProxyListener); - mSysUiFlagContainer.removeCallback(mSysUiStateCallback); + mStatusBarStateController.get().removeCallback(mStatusBarStateListener); + mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener); + mOverviewProxyService.get().removeCallback(mOverviewProxyListener); + mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback); + mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver); } @Override @@ -223,15 +257,10 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { } } - private static boolean isNavBarHidden(int sysuiStateFlags) { - return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0; - } - @Nullable - private static ComponentName getCurrentDefaultHome() { + private ComponentName getCurrentDefaultHome() { List<ResolveInfo> homeActivities = new ArrayList<>(); - ComponentName defaultHome = - PackageManagerWrapper.getInstance().getHomeActivities(homeActivities); + ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities); if (defaultHome != null) { return defaultHome; } @@ -287,7 +316,8 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { } private void handleSystemUiStateChanged(int sysuiStateFlags) { - boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags); + boolean isNavBarHidden = + (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0; if (mIsNavBarHidden == isNavBarHidden) { return; } @@ -374,24 +404,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { return; } - long currentTimestamp = SystemClock.uptimeMillis(); + long currentTimestamp = mClock.currentTimeMillis(); mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp; mLastLearningTimestamp = currentTimestamp; - // TODO(b/140034473) - whitelistIpcs(() -> Settings.Secure.putLong( - mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed)); mIsLearned = mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs(); - mHandler.post(this::recordLearnTimeElapsed); - } - - private void recordLearnTimeElapsed() { - if (mContext != null) { - Settings.Secure.putLong( - mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed); - } + mHandler.post(() -> Settings.Secure.putLong( + mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed)); } private void resetConsecutiveTaskSwitches() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index eb60b3db7a11..1f950f60fd6a 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -21,7 +21,6 @@ import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerThread; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -157,17 +156,18 @@ public class AssistManager implements ConfigurationChangedReceiver { }; @Inject - public AssistManager(DeviceProvisionedController controller, Context context) { + public AssistManager( + DeviceProvisionedController controller, + Context context, + AssistUtils assistUtils, + AssistHandleBehaviorController handleController) { mContext = context; mDeviceProvisionedController = controller; mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); - mAssistUtils = new AssistUtils(context); + mAssistUtils = assistUtils; mAssistDisclosure = new AssistDisclosure(context, new Handler()); mPhoneStateMonitor = new PhoneStateMonitor(context); - final HandlerThread assistHandleThread = new HandlerThread("AssistHandleThread"); - assistHandleThread.start(); - mHandleController = new AssistHandleBehaviorController( - context, mAssistUtils, assistHandleThread.getThreadHandler()); + mHandleController = handleController; registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java new file mode 100644 index 000000000000..2a82d215e44a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist; + +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.SystemClock; + +import androidx.slice.Clock; + +import com.android.internal.app.AssistUtils; +import com.android.systemui.ScreenDecorations; +import com.android.systemui.SysUiServiceProvider; + +import java.util.EnumMap; +import java.util.Map; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +/** Module for dagger injections related to the Assistant. */ +@Module +public abstract class AssistModule { + + static final String ASSIST_HANDLE_THREAD_NAME = "assist_handle_thread"; + static final String UPTIME_NAME = "uptime"; + + @Provides + @Singleton + @Named(ASSIST_HANDLE_THREAD_NAME) + static Handler provideBackgroundHandler() { + final HandlerThread backgroundHandlerThread = + new HandlerThread("AssistHandleThread"); + backgroundHandlerThread.start(); + return backgroundHandlerThread.getThreadHandler(); + } + + @Provides + @Singleton + static Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> + provideAssistHandleBehaviorControllerMap( + AssistHandleOffBehavior offBehavior, + AssistHandleLikeHomeBehavior likeHomeBehavior, + AssistHandleReminderExpBehavior reminderExpBehavior) { + Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> map = + new EnumMap<>(AssistHandleBehavior.class); + map.put(AssistHandleBehavior.OFF, offBehavior); + map.put(AssistHandleBehavior.LIKE_HOME, likeHomeBehavior); + map.put(AssistHandleBehavior.REMINDER_EXP, reminderExpBehavior); + return map; + } + + @Provides + static ScreenDecorations provideScreenDecorations(Context context) { + return SysUiServiceProvider.getComponent(context, ScreenDecorations.class); + } + + @Provides + @Singleton + static AssistUtils provideAssistUtils(Context context) { + return new AssistUtils(context); + } + + @Provides + @Singleton + @Named(UPTIME_NAME) + static Clock provideSystemClock() { + return SystemClock::uptimeMillis; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java index c21a717dc8cf..cbb56e8e979d 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java @@ -24,8 +24,18 @@ import androidx.annotation.Nullable; import java.util.concurrent.Executor; +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Wrapper class for retrieving phenotype flag values. + * + * Can be mocked in tests for ease of testing the effects of particular values. + */ +@Singleton public class PhenotypeHelper { + @Inject public PhenotypeHelper() {} public long getLong(String name, long defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 94d9ede5c8b1..67fc3e32883f 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -511,7 +511,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi void updateBubble(NotificationEntry notif, boolean suppressFlyout) { // If this is an interruptive notif, mark that it's interrupted - if (notif.importance >= NotificationManager.IMPORTANCE_HIGH) { + if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { notif.setInterruption(); } mBubbleData.notificationEntryUpdated(notif, suppressFlyout); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSColorController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSColorController.kt new file mode 100644 index 000000000000..3f0c5bb7f620 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSColorController.kt @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs + +import android.content.ContentResolver +import android.database.ContentObserver +import android.net.Uri +import android.os.Handler +import android.os.Looper +import android.provider.Settings +import android.util.Log +import com.android.systemui.plugins.qs.QSTile + +private const val TAG = "QSColorController" +private const val QS_COLOR_ICON = "qs_color_icon" +private const val QS_COLOR_ENABLED = "qs_color_enabled" +private const val QS_COLOR_OVERRIDDEN_TILES = "qs_color_overridden_tiles" +private val qsColorIconUri = Settings.System.getUriFor(QS_COLOR_ICON) +private val qsColorEnabledUri = Settings.System.getUriFor(QS_COLOR_ENABLED) +class QSColorController private constructor() { + + private var overrideColor = false + private var colorIcon = false + private lateinit var colorCache: SettingBackedMap + + companion object { + val instance = QSColorController() + internal fun overrideColor() = instance.overrideColor + internal fun colorIcon() = instance.colorIcon + + @QSTile.ColorTile + private fun getColorFromSetting(setting: String): Int { + return when (setting.toLowerCase()) { + "red" -> QSTile.COLOR_TILE_RED + "blue" -> QSTile.COLOR_TILE_BLUE + "green" -> QSTile.COLOR_TILE_GREEN + "yellow" -> QSTile.COLOR_TILE_YELLOW + else -> QSTile.COLOR_TILE_ACCENT + } + } + } + + private fun getBooleanSetting(key: String, default: Boolean = false): Boolean = + try { + Settings.System.getInt(contentResolver, key) != 0 + } catch (_: Settings.SettingNotFoundException) { + default + } + + private lateinit var tileHost: QSHost + private lateinit var contentResolver: ContentResolver + + fun initQSTileHost(host: QSHost) { + tileHost = host + contentResolver = tileHost.context.contentResolver + colorCache = SettingBackedMap(contentResolver, mutableMapOf()) + colorIcon = getBooleanSetting(QS_COLOR_ICON) + overrideColor = getBooleanSetting(QS_COLOR_ENABLED) + readExistingSettings() + contentResolver.registerContentObserver(qsColorEnabledUri, true, settingsListener) + contentResolver.registerContentObserver(qsColorIconUri, false, settingsListener) + } + + private fun readExistingSettings() { + Settings.System.getString(contentResolver, QS_COLOR_OVERRIDDEN_TILES)?.split(",") + ?.mapNotNull { spec -> + Settings.System.getString(contentResolver, "$QS_COLOR_ENABLED/$spec")?.let { + spec to it + } + }?.forEach { + modifyTileColor(it.first, getColorFromSetting(it.second)) + } + } + + private val settingsListener = object : ContentObserver(Handler(Looper.getMainLooper())) { + override fun onChange(selfChange: Boolean, uri: Uri) { + super.onChange(selfChange, uri) + when (uri) { + qsColorIconUri -> colorIcon = getBooleanSetting(QS_COLOR_ICON) + qsColorEnabledUri -> overrideColor = getBooleanSetting(QS_COLOR_ENABLED) + else -> { + uri.path?.drop("/system/".length)?.let { + val color = getColorFromSetting( + Settings.System.getString(contentResolver, it) ?: "accent") + val tileSpec = uri.lastPathSegment ?: "" + modifyTileColor(tileSpec, color) + } + } + } + } + } + + private fun modifyTileColor(spec: String, @QSTile.ColorTile color: Int) { + Log.w(TAG, "Setting color of tile $spec to $color") + colorCache.put(spec, color) + tileHost.tiles.firstOrNull { it.tileSpec == spec }?.setColor(color) + } + + fun applyColorToTile(tile: QSTile) { + colorCache.get(tile.tileSpec)?.let { + modifyTileColor(tile.tileSpec, it) + } + } + + fun applyColorToAllTiles() = tileHost.tiles.forEach(::applyColorToTile) + + fun destroy() { + contentResolver.unregisterContentObserver(settingsListener) + } + + class SettingBackedMap( + private val contentResolver: ContentResolver, + private val map: MutableMap<String, Int> + ) : MutableMap<String, @QSTile.ColorTile Int> by map { + override fun put(key: String, @QSTile.ColorTile value: Int): Int? { + return map.put(key, value).also { + Settings.System.putString(contentResolver, QS_COLOR_OVERRIDDEN_TILES, + map.filterValues { it != QSTile.COLOR_TILE_ACCENT } + .keys + .joinToString(",")) + } + } + } +} +fun overrideColor() = QSColorController.overrideColor() +fun colorIcon() = QSColorController.colorIcon()
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index b27bf32b9382..61d7498ced94 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -88,6 +88,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D private int mCurrentUser; private StatusBar mStatusBar; + private QSColorController mQSColorController = QSColorController.Companion.getInstance(); + @Inject public QSTileHost(Context context, StatusBarIconController iconController, @@ -119,6 +121,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D // AutoTileManager can modify mTiles so make sure mTiles has already been initialized. mAutoTiles = autoTiles.get(); }); + + mQSColorController.initQSTileHost(this); } public StatusBarIconController getIconController() { @@ -132,6 +136,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D mServices.destroy(); mPluginManager.removePluginListener(this); mDumpController.unregisterDumpable(this); + + mQSColorController.destroy(); } @Override @@ -275,6 +281,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D mCallbacks.get(i).onTilesChanged(); } } + + mQSColorController.applyColorToAllTiles(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index 31526bf8f5e1..88c7964144c1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -14,10 +14,12 @@ package com.android.systemui.qs.tileimpl; +import static com.android.systemui.qs.QSColorControllerKt.colorIcon; import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.ColorStateList; @@ -148,10 +150,15 @@ public class QSIconViewImpl extends QSIconView { iv.clearColorFilter(); } if (state.state != mState) { - int color = getColor(state.state); + int color = getColor(state.state, state.colorActive); mState = state.state; if (mTint != 0 && allowAnimations && shouldAnimate(iv)) { - animateGrayScale(mTint, color, iv, () -> updateIcon(iv, state, allowAnimations)); + if (colorIcon()) { + animateColor(mTint, color, iv, () -> updateIcon(iv, state, allowAnimations)); + } else { + animateGrayScale(mTint, color, iv, + () -> updateIcon(iv, state, allowAnimations)); + } mTint = color; } else { if (iv instanceof AlphaControlledSlashImageView) { @@ -168,8 +175,12 @@ public class QSIconViewImpl extends QSIconView { } } + protected int getColor(int state, int colorActive) { + return getColorForState(getContext(), state, colorActive); + } + protected int getColor(int state) { - return getColorForState(getContext(), state); + return getColor(state, -1); } private void animateGrayScale(int fromColor, int toColor, ImageView iv, @@ -206,6 +217,37 @@ public class QSIconViewImpl extends QSIconView { } } + private void animateColor(int fromColor, int toColor, ImageView iv, + final Runnable endRunnable) { + if (iv instanceof AlphaControlledSlashImageView) { + ((AlphaControlledSlashImageView) iv) + .setFinalImageTintList(ColorStateList.valueOf(toColor)); + } + if (mAnimationEnabled && ValueAnimator.areAnimatorsEnabled()) { + + + ValueAnimator anim = ValueAnimator.ofFloat(0, 1); + anim.setDuration(QS_ANIM_LENGTH); + anim.addUpdateListener(animation -> { + float fraction = animation.getAnimatedFraction(); + int color = (int) ArgbEvaluator.getInstance().evaluate(fraction, fromColor, + toColor); + + setTint(iv, color); + }); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + endRunnable.run(); + } + }); + anim.start(); + } else { + setTint(iv, toColor); + endRunnable.run(); + } + } + public static void setTint(ImageView iv, int color) { iv.setImageTintList(ColorStateList.valueOf(color)); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index c186e59056aa..f4a516261ade 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -13,6 +13,8 @@ */ package com.android.systemui.qs.tileimpl; +import static com.android.systemui.qs.QSColorControllerKt.colorIcon; +import static com.android.systemui.qs.QSColorControllerKt.overrideColor; import static com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH; import android.animation.ValueAnimator; @@ -71,6 +73,9 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { private int mCircleColor; private int mBgSize; + private final boolean mQsColors = overrideColor(); + private final boolean mQSIcons = colorIcon(); + public QSTileBaseView(Context context, QSIconView icon) { this(context, icon, false); } @@ -194,7 +199,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { } protected void handleStateChanged(QSTile.State state) { - int circleColor = getCircleColor(state.state); + int circleColor = getCircleColor(state.state, mQsColors ? state.colorActive : -1); boolean allowAnimations = animationsEnabled(); if (circleColor != mCircleColor) { if (allowAnimations) { @@ -239,10 +244,11 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { return mLocInScreen[1] >= -getHeight(); } - private int getCircleColor(int state) { + private int getCircleColor(int state, int colorActive) { switch (state) { case Tile.STATE_ACTIVE: - return mColorActive; + int color = (colorActive == -1) ? mColorActive : colorActive; + return mQsColors && mQSIcons ? Utils.applyAlpha(0.5f, color) : color; case Tile.STATE_INACTIVE: case Tile.STATE_UNAVAILABLE: return mColorDisabled; @@ -252,6 +258,10 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { } } + private int getCircleColor(int state) { + return getCircleColor(state, -1); + } + @Override public void setClickable(boolean clickable) { super.setClickable(clickable); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 3d6ee4cf9617..681de378ff57 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -26,6 +26,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_BAR_STATE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import static com.android.systemui.qs.QSColorControllerKt.colorIcon; import android.app.ActivityManager; import android.content.Context; @@ -54,6 +55,7 @@ import com.android.settingslib.Utils; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.Prefs; +import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSIconView; @@ -98,8 +100,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy private final ArrayList<Callback> mCallbacks = new ArrayList<>(); private final Object mStaleListener = new Object(); - protected TState mState = newTileState(); - private TState mTmpState = newTileState(); + protected TState mState; + private TState mTmpState; private boolean mAnnounceNextStateChange; private String mTileSpec; @@ -132,6 +134,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy protected QSTileImpl(QSHost host) { mHost = host; mContext = host.getContext(); + mState = newTileState(); + mTmpState = newTileState(); mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption(); } @@ -422,6 +426,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy public abstract CharSequence getTileLabel(); public static int getColorForState(Context context, int state) { + return getColorForState(context, state, -1); + } + + public static int getColorForState(Context context, int state, int colorActive) { switch (state) { case Tile.STATE_UNAVAILABLE: return Utils.getDisabled(context, @@ -429,13 +437,25 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy case Tile.STATE_INACTIVE: return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary); case Tile.STATE_ACTIVE: - return Utils.getColorAttrDefaultColor(context, android.R.attr.colorPrimary); + return getActiveColor(context, colorActive); default: Log.e("QSTile", "Invalid state " + state); return 0; } } + private static int getActiveColor(Context context, int colorActive) { + if (colorIcon()) { + if (colorActive == -1) { + return Utils.getColorAccentDefaultColor(context); + } else { + return colorActive; + } + } else { + return Utils.getColorAttrDefaultColor(context, android.R.attr.colorPrimary); + } + } + protected final class H extends Handler { private static final int ADD_CALLBACK = 1; private static final int CLICK = 2; @@ -614,4 +634,27 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy pw.println(this.getClass().getSimpleName() + ":"); pw.print(" "); pw.println(getState().toString()); } + + @Override + public void setColor(@ColorTile int color) { + int resId; + switch(color) { + case COLOR_TILE_RED: + resId = R.color.GM2_red_500; + break; + case COLOR_TILE_BLUE: + resId = R.color.GM2_blue_500; + break; + case COLOR_TILE_GREEN: + resId = R.color.GM2_green_500; + break; + case COLOR_TILE_YELLOW: + resId = R.color.GM2_yellow_500; + break; + default: + resId = -1; + } + mTmpState.colorActive = resId == -1 ? -1 : mContext.getColor(resId); + refreshState(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java index 0f295ba75fe4..48e2923c97d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java @@ -27,6 +27,18 @@ public interface NotificationLifetimeExtender { boolean shouldExtendLifetime(@NonNull NotificationEntry entry); /** + * It's possible that a notification was canceled before it ever became visible. This callback + * gives lifetime extenders a chance to make sure it shows up. For example if a foreground + * service is canceled too quickly but we still want to make sure a FGS notification shows. + * @param pendingEntry the canceled (but pending) entry + * @return true if the notification lifetime should be extended + */ + default boolean shouldExtendLifetimeForPendingNotification( + @NonNull NotificationEntry pendingEntry) { + return false; + } + + /** * Sets whether or not the lifetime should be managed by the extender. In practice, if * shouldManage is true, this is where the extender starts managing the entry internally and is * now responsible for calling {@link NotificationSafeToRemoveCallback#onSafeToRemove(String)} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java index 3db02b9743da..266fe8dc2708 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java @@ -26,8 +26,6 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -39,22 +37,24 @@ public class NotificationUiAdjustment { public final String key; public final List<Notification.Action> smartActions; - public final CharSequence[] smartReplies; + public final List<CharSequence> smartReplies; @VisibleForTesting NotificationUiAdjustment( - String key, List<Notification.Action> smartActions, CharSequence[] smartReplies) { + String key, List<Notification.Action> smartActions, List<CharSequence> smartReplies) { this.key = key; this.smartActions = smartActions == null ? Collections.emptyList() - : new ArrayList<>(smartActions); - this.smartReplies = smartReplies == null ? new CharSequence[0] : smartReplies.clone(); + : smartActions; + this.smartReplies = smartReplies == null + ? Collections.emptyList() + : smartReplies; } public static NotificationUiAdjustment extractFromNotificationEntry( NotificationEntry entry) { return new NotificationUiAdjustment( - entry.key, entry.systemGeneratedSmartActions, entry.systemGeneratedSmartReplies); + entry.key, entry.getSmartActions(), entry.getSmartReplies()); } public static boolean needReinflate( @@ -66,7 +66,7 @@ public class NotificationUiAdjustment { if (areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions)) { return true; } - if (!Arrays.equals(oldAdjustment.smartReplies, newAdjustment.smartReplies)) { + if (!newAdjustment.smartReplies.equals(oldAdjustment.smartReplies)) { return true; } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 66a06193d0bf..50d9bae77bea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -436,7 +436,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } row.showAppOpsIcons(entry.mActiveAppOps); - row.setLastAudiblyAlertedMs(entry.lastAudiblyAlertedMs); + row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs()); } Trace.beginSection("NotificationPresenter#onUpdateRowStates"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 00321744f75a..4a27a4ed31a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -281,10 +281,24 @@ public class NotificationEntryManager implements } final NotificationEntry entry = mNotificationData.get(key); + boolean lifetimeExtended = false; - abortExistingInflation(key); + // Notification was canceled before it got inflated + if (entry == null) { + NotificationEntry pendingEntry = mPendingNotifications.get(key); + if (pendingEntry != null) { + for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { + if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) { + extendLifetime(pendingEntry, extender); + lifetimeExtended = true; + } + } + } + } - boolean lifetimeExtended = false; + if (!lifetimeExtended) { + abortExistingInflation(key); + } if (entry != null) { // If a manager needs to keep the notification around for whatever reason, we @@ -471,7 +485,7 @@ public class NotificationEntryManager implements NotificationUiAdjustment adjustment = NotificationUiAdjustment.extractFromNotificationEntry(entry); oldAdjustments.put(entry.key, adjustment); - oldImportances.put(entry.key, entry.importance); + oldImportances.put(entry.key, entry.getImportance()); } // Populate notification entries from the new rankings. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java index f99662e69b8e..5a0b88cbdc28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java @@ -110,7 +110,7 @@ public class NotificationFilter { return true; } - if (entry.suspended) { + if (entry.isSuspended()) { return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java index 150667b86828..9362d2d5e2c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java @@ -169,7 +169,7 @@ public class NotificationInterruptionStateProvider { return false; } - if (!entry.canBubble) { + if (!entry.canBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); } @@ -244,7 +244,7 @@ public class NotificationInterruptionStateProvider { return false; } - if (entry.importance < NotificationManager.IMPORTANCE_HIGH) { + if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: unimportant notification: " + sbn.getKey()); } @@ -307,7 +307,7 @@ public class NotificationInterruptionStateProvider { return false; } - if (entry.importance < NotificationManager.IMPORTANCE_DEFAULT) { + if (entry.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: not important enough: " + sbn.getKey()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java index 4a6c7d27516c..6fe4abee6133 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java @@ -73,7 +73,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl @Override public void onPreEntryUpdated(NotificationEntry entry) { final boolean mAmbientStateHasChanged = - entry.ambient != entry.getRow().isLowPriority(); + entry.isAmbient() != entry.getRow().isLowPriority(); if (mAmbientStateHasChanged) { mLowPriorityReorderingViews.add(entry); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 6f5fe8b629fb..d1b05603223d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -38,7 +38,6 @@ import android.app.Person; import android.content.Context; import android.graphics.drawable.Icon; import android.os.Bundle; -import android.os.Parcelable; import android.os.SystemClock; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; @@ -61,7 +60,6 @@ import com.android.systemui.statusbar.notification.row.NotificationContentInflat import com.android.systemui.statusbar.notification.row.NotificationGuts; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -86,14 +84,12 @@ public final class NotificationEntry { private static final long INITIALIZATION_DELAY = 400; private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN; private static final int COLOR_INVALID = 1; + public final String key; public StatusBarNotification notification; private Ranking mRanking; - public long lastAudiblyAlertedMs; public boolean noisy; - public boolean ambient; - public int importance; public StatusBarIconView icon; public StatusBarIconView expandedIcon; public StatusBarIconView centeredIcon; @@ -103,14 +99,6 @@ public final class NotificationEntry { public int targetSdk; private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET; public CharSequence remoteInputText; - public List<SnoozeCriterion> snoozeCriteria; - public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL; - /** Smart Actions provided by the NotificationAssistantService. */ - @NonNull - public List<Notification.Action> systemGeneratedSmartActions = Collections.emptyList(); - /** Smart replies provided by the NotificationAssistantService. */ - @NonNull - public CharSequence[] systemGeneratedSmartReplies = new CharSequence[0]; /** * If {@link android.app.RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is @@ -119,10 +107,6 @@ public final class NotificationEntry { */ public EditedSuggestionInfo editedSuggestionInfo; - @VisibleForTesting - public int suppressedVisualEffects; - public boolean suspended; - private NotificationEntry parent; // our parent (if we're in a group) private ExpandableNotificationRow row; // the outer expanded view @@ -151,12 +135,6 @@ public final class NotificationEntry { private boolean hasSentReply; /** - * Whether this notification has been approved globally, at the app level, and at the channel - * level for bubbling. - */ - public boolean canBubble; - - /** * Whether this notification is shown to the user as a high priority notification: visible on * the lock screen/status bar and in the top section in the shade. */ @@ -191,14 +169,13 @@ public final class NotificationEntry { } /** - * Method for old tests that build NotificationEntries with a ranking. + * Method for old tests that build NotificationEntries without a ranking. * - * @deprecated New tests should pass a ranking object as well. + * @deprecated Use NotificationEntryBuilder instead. */ @VisibleForTesting @Deprecated public static NotificationEntry buildForTest(StatusBarNotification sbn) { - // TODO START here this will NPE on all tests return new NotificationEntry(sbn, null, true); } @@ -242,26 +219,54 @@ public final class NotificationEntry { */ public void setRanking(@NonNull Ranking ranking) { mRanking = ranking; - - lastAudiblyAlertedMs = ranking.getLastAudiblyAlertedMillis(); - importance = ranking.getImportance(); - ambient = ranking.isAmbient(); - snoozeCriteria = ranking.getSnoozeCriteria(); - userSentiment = ranking.getUserSentiment(); - systemGeneratedSmartActions = ranking.getSmartActions() == null - ? Collections.emptyList() : ranking.getSmartActions(); - systemGeneratedSmartReplies = ranking.getSmartReplies() == null - ? new CharSequence[0] - : ranking.getSmartReplies().toArray(new CharSequence[0]); - suppressedVisualEffects = ranking.getSuppressedVisualEffects(); - suspended = ranking.isSuspended(); - canBubble = ranking.canBubble(); } public NotificationChannel getChannel() { return mRanking.getChannel(); } + public long getLastAudiblyAlertedMs() { + return mRanking.getLastAudiblyAlertedMillis(); + } + + public boolean isAmbient() { + return mRanking.isAmbient(); + } + + public int getImportance() { + return mRanking.getImportance(); + } + + public List<SnoozeCriterion> getSnoozeCriteria() { + return mRanking.getSnoozeCriteria(); + } + + public int getUserSentiment() { + return mRanking.getUserSentiment(); + } + + public int getSuppressedVisualEffects() { + return mRanking.getSuppressedVisualEffects(); + } + + public boolean isSuspended() { + return mRanking.isSuspended(); + } + + /** @see Ranking#canBubble() */ + public boolean canBubble() { + return mRanking.canBubble(); + } + + public @NonNull List<Notification.Action> getSmartActions() { + return mRanking.getSmartActions(); + } + + public @NonNull List<CharSequence> getSmartReplies() { + return mRanking.getSmartReplies(); + } + + public void setInterruption() { interruption = true; } @@ -788,7 +793,7 @@ public final class NotificationEntry { if (isExemptFromDndVisualSuppression()) { return false; } - return (suppressedVisualEffects & effect) != 0; + return (getSuppressedVisualEffects() & effect) != 0; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java index 247c31fc80a3..60cf995ad8d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java @@ -214,7 +214,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { // no-op here. } } else { - if (oldImportance != null && entry.importance != oldImportance) { + if (oldImportance != null && entry.getImportance() != oldImportance) { if (entry.rowExists()) { entry.getRow().onNotificationRankingUpdated(); } @@ -228,7 +228,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { PackageManager pmUser, StatusBarNotification sbn, ExpandableNotificationRow row) { - row.setIsLowPriority(entry.ambient); + row.setIsLowPriority(entry.isAmbient()); // Extract target SDK version. try { @@ -248,7 +248,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { row.setOnActivatedListener(mPresenter); boolean useIncreasedCollapsedHeight = - mMessagingUtil.isImportantMessaging(sbn, entry.importance); + mMessagingUtil.isImportantMessaging(sbn, entry.getImportance()); boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && !mPresenter.isPresenterFullyCollapsed(); row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java index 2c15e87ee1e6..73093c6f471f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java @@ -87,7 +87,7 @@ public class NotificationBlockingHelperManager { // - The row is blockable (i.e. not non-blockable) // - The dismissed row is a valid group (>1 or 0 children from the same channel) // or the only child in the group - if ((row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE || DEBUG) + if ((row.getEntry().getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG) && mIsShadeExpanded && !row.getIsNonblockable() && ((!row.isChildInGroup() || row.isOnlyChildInGroup()) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 0c5b27b92878..cc2078bd158b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1181,7 +1181,7 @@ public class NotificationContentView extends FrameLayout { mCurrentSmartRepliesAndActions.smartActions == null ? 0 : mCurrentSmartRepliesAndActions.smartActions.actions.size(), mCurrentSmartRepliesAndActions.smartReplies == null ? 0 : - mCurrentSmartRepliesAndActions.smartReplies.choices.length)); + mCurrentSmartRepliesAndActions.smartReplies.choices.size())); } applySmartReplyView(mCurrentSmartRepliesAndActions, entry); } @@ -1295,7 +1295,7 @@ public class NotificationContentView extends FrameLayout { if (smartRepliesAndActions.smartReplies != null || smartRepliesAndActions.smartActions != null) { int numSmartReplies = smartRepliesAndActions.smartReplies == null - ? 0 : smartRepliesAndActions.smartReplies.choices.length; + ? 0 : smartRepliesAndActions.smartReplies.choices.size(); int numSmartActions = smartRepliesAndActions.smartActions == null ? 0 : smartRepliesAndActions.smartActions.actions.size(); boolean fromAssistant = smartRepliesAndActions.smartReplies == null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 3e8825d735da..9d0dd6b683cf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -241,7 +241,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper()); notificationSnoozeView.setStatusBarNotification(sbn); - notificationSnoozeView.setSnoozeOptions(row.getEntry().snoozeCriteria); + notificationSnoozeView.setSnoozeOptions(row.getEntry().getSnoozeCriteria()); guts.setHeightChangedListener((NotificationGuts g) -> { mListContainer.onHeightChanged(row, row.isShown() /* needsAnimation */); }); @@ -325,7 +325,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mDeviceProvisionedController.isDeviceProvisioned(), row.getIsNonblockable(), isForBlockingHelper, - row.getEntry().importance, + row.getEntry().getImportance(), row.getEntry().isHighPriority()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 6a611a623c69..1c9b2256af9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -5782,7 +5782,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd if (mHighPriorityBeforeSpeedBump) { beforeSpeedBump = row.getEntry().isTopBucket(); } else { - beforeSpeedBump = !row.getEntry().ambient; + beforeSpeedBump = !row.getEntry().isAmbient(); } if (beforeSpeedBump) { speedBumpIndex = currentIndex; 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 bec53a1b2d3c..320243b3ee22 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -411,7 +411,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit if (DEBUG) { Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.key); } - } else if (entry.importance < NotificationManager.IMPORTANCE_HIGH) { + } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { if (DEBUG) { Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.key); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index d8b223960953..4732049d635e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -224,7 +224,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, mVisualStabilityManager.setUpWithPresenter(this); mGutsManager.setUpWithPresenter(this, notifListContainer, mCheckSaveListener, mOnSettingsClickListener); - // ForegroundServiceControllerListener adds its listener in its constructor + // ForegroundServiceNotificationListener adds its listener in its constructor // but we need to request it here in order for it to be instantiated. // TODO: figure out how to do this correctly once Dependency.get() is gone. Dependency.get(ForegroundServiceNotificationListener.class); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java index ee78a723a49c..25a32b330f7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java @@ -123,7 +123,7 @@ public class InflatedSmartReplies { if (left == right) return true; if (left == null || right == null) return false; - if (!Arrays.equals(left.getSmartReplies(), right.getSmartReplies())) { + if (!left.getSmartReplies().equals(right.getSmartReplies())) { return false; } @@ -199,7 +199,7 @@ public class InflatedSmartReplies { SmartReplyView.SmartActions smartActions = null; if (appGeneratedSmartRepliesExist) { smartReplies = new SmartReplyView.SmartReplies( - remoteInputActionPair.first.getChoices(), + Arrays.asList(remoteInputActionPair.first.getChoices()), remoteInputActionPair.first, remoteInputActionPair.second.actionIntent, false /* fromAssistant */); @@ -210,22 +210,22 @@ public class InflatedSmartReplies { } // Apps didn't provide any smart replies / actions, use those from NAS (if any). if (!appGeneratedSmartRepliesExist && !appGeneratedSmartActionsExist) { - boolean useGeneratedReplies = !ArrayUtils.isEmpty(entry.systemGeneratedSmartReplies) + boolean useGeneratedReplies = !ArrayUtils.isEmpty(entry.getSmartReplies()) && freeformRemoteInputActionPair != null && freeformRemoteInputActionPair.second.getAllowGeneratedReplies() && freeformRemoteInputActionPair.second.actionIntent != null; if (useGeneratedReplies) { smartReplies = new SmartReplyView.SmartReplies( - entry.systemGeneratedSmartReplies, + entry.getSmartReplies(), freeformRemoteInputActionPair.first, freeformRemoteInputActionPair.second.actionIntent, true /* fromAssistant */); } - boolean useSmartActions = !ArrayUtils.isEmpty(entry.systemGeneratedSmartActions) + boolean useSmartActions = !ArrayUtils.isEmpty(entry.getSmartActions()) && notification.getAllowSystemGeneratedContextualActions(); if (useSmartActions) { List<Notification.Action> systemGeneratedActions = - entry.systemGeneratedSmartActions; + entry.getSmartActions(); // Filter actions if we're in kiosk-mode - we don't care about screen pinning mode, // since notifications aren't shown there anyway. ActivityManagerWrapper activityManagerWrapper = @@ -288,8 +288,8 @@ public class InflatedSmartReplies { this.smartActions = smartActions; } - @NonNull public CharSequence[] getSmartReplies() { - return smartReplies == null ? new CharSequence[0] : smartReplies.choices; + @NonNull public List<CharSequence> getSmartReplies() { + return smartReplies == null ? Collections.emptyList() : smartReplies.choices; } @NonNull public List<Notification.Action> getSmartActions() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 282d28c3b20c..4fdaa6300065 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -220,7 +220,7 @@ public class SmartReplyView extends ViewGroup { if (smartReplies.remoteInput != null && smartReplies.pendingIntent != null) { if (smartReplies.choices != null) { - for (int i = 0; i < smartReplies.choices.length; ++i) { + for (int i = 0; i < smartReplies.choices.size(); ++i) { buttons.add(inflateReplyButton( this, getContext(), i, smartReplies, smartReplyController, entry, delayOnClickListener)); @@ -265,7 +265,7 @@ public class SmartReplyView extends ViewGroup { NotificationEntry entry, boolean useDelayedOnClickListener) { Button b = (Button) LayoutInflater.from(context).inflate( R.layout.smart_reply_button, smartReplyView, false); - CharSequence choice = smartReplies.choices[replyIndex]; + CharSequence choice = smartReplies.choices.get(replyIndex); b.setText(choice); OnDismissAction action = () -> { @@ -944,10 +944,10 @@ public class SmartReplyView extends ViewGroup { @NonNull public final PendingIntent pendingIntent; @NonNull - public final CharSequence[] choices; + public final List<CharSequence> choices; public final boolean fromAssistant; - public SmartReplies(CharSequence[] choices, RemoteInput remoteInput, + public SmartReplies(List<CharSequence> choices, RemoteInput remoteInput, PendingIntent pendingIntent, boolean fromAssistant) { this.choices = choices; this.remoteInput = remoteInput; diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index ccd2138ced54..9aeb147cc725 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.messages.nano.SystemMessageProto; +import com.android.systemui.statusbar.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -397,14 +398,18 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } private void entryAdded(StatusBarNotification notification, int importance) { - NotificationEntry entry = NotificationEntry.buildForTest(notification); - entry.importance = importance; + NotificationEntry entry = new NotificationEntryBuilder() + .setSbn(notification) + .setImportance(importance) + .build(); mEntryListener.onPendingEntryAdded(entry); } private void entryUpdated(StatusBarNotification notification, int importance) { - NotificationEntry entry = NotificationEntry.buildForTest(notification); - entry.importance = importance; + NotificationEntry entry = new NotificationEntryBuilder() + .setSbn(notification) + .setImportance(importance) + .build(); mEntryListener.onPostEntryUpdated(entry); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java new file mode 100644 index 000000000000..5943b02b4e4a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.service.notification.NotificationListenerService.Ranking; +import android.service.notification.StatusBarNotification; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ForegroundServiceNotificationListenerTest extends SysuiTestCase { + private ForegroundServiceLifetimeExtender mExtender = new ForegroundServiceLifetimeExtender(); + private StatusBarNotification mSbn; + private NotificationEntry mEntry; + private Notification mNotif; + + @Before + public void setup() { + mNotif = new Notification.Builder(mContext, "") + .setSmallIcon(R.drawable.ic_person) + .setContentTitle("Title") + .setContentText("Text") + .build(); + + mSbn = mock(StatusBarNotification.class); + when(mSbn.getNotification()).thenReturn(mNotif); + + mEntry = new NotificationEntry(mSbn, mock(Ranking.class)); + } + + /** + * ForegroundServiceLifetimeExtenderTest + */ + @Test + public void testShouldExtendLifetime_should_foreground() { + // Extend the lifetime of a FGS notification iff it has not been visible + // for the minimum time + mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis()); + assertTrue(mExtender.shouldExtendLifetime(mEntry)); + } + + @Test + public void testShouldExtendLifetime_shouldNot_foreground() { + mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); + assertFalse(mExtender.shouldExtendLifetime(mEntry)); + } + + @Test + public void testShouldExtendLifetime_shouldNot_notForeground() { + mNotif.flags = 0; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); + assertFalse(mExtender.shouldExtendLifetime(mEntry)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java index 6db5ef92c12c..9c920f52d56a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java @@ -42,6 +42,7 @@ import com.android.systemui.ScreenDecorations; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.statusbar.phone.NavigationModeController; import org.junit.After; import org.junit.Before; @@ -51,6 +52,9 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.EnumMap; +import java.util.Map; + @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper @@ -64,7 +68,12 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { @Mock private AssistUtils mMockAssistUtils; @Mock private Handler mMockHandler; @Mock private PhenotypeHelper mMockPhenotypeHelper; - @Mock private AssistHandleBehaviorController.BehaviorController mMockBehaviorController; + @Mock private AssistHandleOffBehavior mMockOffBehavior; + @Mock private AssistHandleLikeHomeBehavior mMockLikeHomeBehavior; + @Mock private AssistHandleReminderExpBehavior mMockReminderExpBehavior; + @Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior; + @Mock private NavigationModeController mMockNavigationModeController; + @Mock private DumpController mMockDumpController; @Before public void setup() { @@ -76,13 +85,23 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { doAnswer(answerVoid(Runnable::run)).when(mMockHandler) .postDelayed(any(Runnable.class), anyLong()); + Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> behaviorMap = + new EnumMap<>(AssistHandleBehavior.class); + behaviorMap.put(AssistHandleBehavior.OFF, mMockOffBehavior); + behaviorMap.put(AssistHandleBehavior.LIKE_HOME, mMockLikeHomeBehavior); + behaviorMap.put(AssistHandleBehavior.REMINDER_EXP, mMockReminderExpBehavior); + behaviorMap.put(AssistHandleBehavior.TEST, mMockTestBehavior); + mAssistHandleBehaviorController = new AssistHandleBehaviorController( mContext, mMockAssistUtils, - mMockHandler, () -> mMockScreenDecorations, + mMockHandler, + () -> mMockScreenDecorations, mMockPhenotypeHelper, - mMockBehaviorController); + behaviorMap, + mMockNavigationModeController, + mMockDumpController); } @After @@ -316,8 +335,8 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST); // Assert - verify(mMockBehaviorController).onModeActivated(mContext, mAssistHandleBehaviorController); - verifyNoMoreInteractions(mMockBehaviorController); + verify(mMockTestBehavior).onModeActivated(mContext, mAssistHandleBehaviorController); + verifyNoMoreInteractions(mMockTestBehavior); } @Test @@ -326,14 +345,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST); mAssistHandleBehaviorController.setInGesturalModeForTest(true); - reset(mMockBehaviorController); + reset(mMockTestBehavior); // Act mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF); // Assert - verify(mMockBehaviorController).onModeDeactivated(); - verifyNoMoreInteractions(mMockBehaviorController); + verify(mMockTestBehavior).onModeDeactivated(); + verifyNoMoreInteractions(mMockTestBehavior); } @Test @@ -346,6 +365,6 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST); // Assert - verifyNoMoreInteractions(mMockBehaviorController); + verifyNoMoreInteractions(mMockTestBehavior); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java new file mode 100644 index 000000000000..c53289c62d94 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.model.SysUiState; +import com.android.systemui.shared.system.QuickStepContract; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class AssistHandleLikeHomeBehaviorTest extends SysuiTestCase { + + private AssistHandleLikeHomeBehavior mAssistHandleLikeHomeBehavior; + + @Mock private WakefulnessLifecycle mMockWakefulnessLifecycle; + @Mock private SysUiState mMockSysUiState; + @Mock private AssistHandleCallbacks mMockAssistHandleCallbacks; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mAssistHandleLikeHomeBehavior = new AssistHandleLikeHomeBehavior( + () -> mMockWakefulnessLifecycle, () -> mMockSysUiState); + } + + @Test + public void onModeActivated_beginsObserving() { + // Arrange + + // Act + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + + // Assert + verify(mMockWakefulnessLifecycle).getWakefulness(); + verify(mMockWakefulnessLifecycle).addObserver(any(WakefulnessLifecycle.Observer.class)); + verify(mMockSysUiState).addCallback(any(SysUiState.SysUiStateCallback.class)); + verifyNoMoreInteractions(mMockWakefulnessLifecycle, mMockSysUiState); + } + + @Test + public void onModeActivated_showsHandlesWhenAwake() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE); + + // Act + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + + // Assert + verify(mMockAssistHandleCallbacks).showAndStay(); + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } + + @Test + public void onModeActivated_hidesHandlesWhenNotAwake() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP); + + // Act + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + + // Assert + verify(mMockAssistHandleCallbacks).hide(); + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } + + @Test + public void onModeDeactivated_stopsObserving() { + // Arrange + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + ArgumentCaptor<WakefulnessLifecycle.Observer> observer = + ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); + ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback = + ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class); + verify(mMockWakefulnessLifecycle).addObserver(observer.capture()); + verify(mMockSysUiState).addCallback(sysUiStateCallback.capture()); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + mAssistHandleLikeHomeBehavior.onModeDeactivated(); + + // Assert + verify(mMockWakefulnessLifecycle).removeObserver(eq(observer.getValue())); + verify(mMockSysUiState).removeCallback(eq(sysUiStateCallback.getValue())); + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onAssistantGesturePerformed_doesNothing() { + // Arrange + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + mAssistHandleLikeHomeBehavior.onAssistantGesturePerformed(); + + // Assert + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onAssistHandlesRequested_doesNothing() { + // Arrange + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + mAssistHandleLikeHomeBehavior.onAssistHandlesRequested(); + + // Assert + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onWake_handlesShow() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP); + ArgumentCaptor<WakefulnessLifecycle.Observer> observer = + ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + verify(mMockWakefulnessLifecycle).addObserver(observer.capture()); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + observer.getValue().onStartedWakingUp(); + + // Assert + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + observer.getValue().onFinishedWakingUp(); + + // Assert + verify(mMockAssistHandleCallbacks).showAndStay(); + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onSleep_handlesHide() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE); + ArgumentCaptor<WakefulnessLifecycle.Observer> observer = + ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + verify(mMockWakefulnessLifecycle).addObserver(observer.capture()); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + observer.getValue().onStartedGoingToSleep(); + + // Assert + verify(mMockAssistHandleCallbacks).hide(); + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + observer.getValue().onFinishedGoingToSleep(); + + // Assert + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onHomeHandleHide_handlesHide() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE); + ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback = + ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class); + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + verify(mMockSysUiState).addCallback(sysUiStateCallback.capture()); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + sysUiStateCallback.getValue().onSystemUiStateChanged( + QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN); + + // Assert + verify(mMockAssistHandleCallbacks).hide(); + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } + + @Test + public void onHomeHandleUnhide_handlesShow() { + // Arrange + when(mMockWakefulnessLifecycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE); + ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback = + ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class); + mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + verify(mMockSysUiState).addCallback(sysUiStateCallback.capture()); + sysUiStateCallback.getValue().onSystemUiStateChanged( + QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN); + reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + + // Act + sysUiStateCallback.getValue().onSystemUiStateChanged( + ~QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN); + + // Assert + verify(mMockAssistHandleCallbacks).showAndStay(); + verifyNoMoreInteractions( + mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java new file mode 100644 index 000000000000..15d4d5b4792f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist; + +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class AssistHandleOffBehaviorTest extends SysuiTestCase { + + private AssistHandleOffBehavior mAssistHandleOffBehavior; + + @Mock private AssistHandleCallbacks mMockAssistHandleCallbacks; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mAssistHandleOffBehavior = new AssistHandleOffBehavior(); + } + + @Test + public void onModeActivated_hidesHandles() { + // Arrange + + // Act + mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + + // Assert + verify(mMockAssistHandleCallbacks).hide(); + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } + + @Test + public void onModeDeactivated_doesNothing() { + // Arrange + mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + reset(mMockAssistHandleCallbacks); + + // Act + mAssistHandleOffBehavior.onModeDeactivated(); + + // Assert + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } + + @Test + public void onAssistantGesturePerformed_doesNothing() { + // Arrange + mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + reset(mMockAssistHandleCallbacks); + + // Act + mAssistHandleOffBehavior.onAssistantGesturePerformed(); + + // Assert + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } + + @Test + public void onAssistHandlesRequested_doesNothing() { + // Arrange + mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks); + reset(mMockAssistHandleCallbacks); + + // Act + mAssistHandleOffBehavior.onAssistHandlesRequested(); + + // Assert + verifyNoMoreInteractions(mMockAssistHandleCallbacks); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java new file mode 100644 index 000000000000..ded3ba592abe --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import android.annotation.Nullable; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager.Importance; +import android.os.UserHandle; +import android.service.notification.SnoozeCriterion; +import android.service.notification.StatusBarNotification; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import java.util.ArrayList; + +/** + * Combined builder for constructing a NotificationEntry and its associated StatusBarNotification + * and Ranking. Is largely a proxy for the SBN and Ranking builders, but does a little extra magic + * to make sure the keys match between the two, etc. + * + * Only for use in tests. + */ +public class NotificationEntryBuilder { + private final SbnBuilder mSbnBuilder = new SbnBuilder(); + private final RankingBuilder mRankingBuilder = new RankingBuilder(); + + private StatusBarNotification mSbn = null; + + public NotificationEntry build() { + StatusBarNotification sbn = mSbn != null ? mSbn : mSbnBuilder.build(); + mRankingBuilder.setKey(sbn.getKey()); + return new NotificationEntry(sbn, mRankingBuilder.build()); + } + + /** + * Sets the SBN directly. If set, causes all calls to delegated SbnBuilder methods to be + * ignored. + */ + public NotificationEntryBuilder setSbn(@Nullable StatusBarNotification sbn) { + mSbn = sbn; + return this; + } + + /* Delegated to SbnBuilder */ + + public NotificationEntryBuilder setPkg(String pkg) { + mSbnBuilder.setPkg(pkg); + return this; + } + + public NotificationEntryBuilder setOpPkg(String opPkg) { + mSbnBuilder.setOpPkg(opPkg); + return this; + } + + public NotificationEntryBuilder setId(int id) { + mSbnBuilder.setId(id); + return this; + } + + public NotificationEntryBuilder setTag(String tag) { + mSbnBuilder.setTag(tag); + return this; + } + + public NotificationEntryBuilder setUid(int uid) { + mSbnBuilder.setUid(uid); + return this; + } + + public NotificationEntryBuilder setInitialPid(int initialPid) { + mSbnBuilder.setInitialPid(initialPid); + return this; + } + + public NotificationEntryBuilder setNotification(Notification notification) { + mSbnBuilder.setNotification(notification); + return this; + } + + public NotificationEntryBuilder setUser(UserHandle user) { + mSbnBuilder.setUser(user); + return this; + } + + public NotificationEntryBuilder setOverrideGroupKey(String overrideGroupKey) { + mSbnBuilder.setOverrideGroupKey(overrideGroupKey); + return this; + } + + public NotificationEntryBuilder setPostTime(long postTime) { + mSbnBuilder.setPostTime(postTime); + return this; + } + + /* Delegated to RankingBuilder */ + + public NotificationEntryBuilder setRank(int rank) { + mRankingBuilder.setRank(rank); + return this; + } + + public NotificationEntryBuilder setMatchesInterruptionFilter( + boolean matchesInterruptionFilter) { + mRankingBuilder.setMatchesInterruptionFilter(matchesInterruptionFilter); + return this; + } + + public NotificationEntryBuilder setVisibilityOverride(int visibilityOverride) { + mRankingBuilder.setVisibilityOverride(visibilityOverride); + return this; + } + + public NotificationEntryBuilder setSuppressedVisualEffects(int suppressedVisualEffects) { + mRankingBuilder.setSuppressedVisualEffects(suppressedVisualEffects); + return this; + } + + public NotificationEntryBuilder setExplanation(CharSequence explanation) { + mRankingBuilder.setExplanation(explanation); + return this; + } + + public NotificationEntryBuilder setAdditionalPeople(ArrayList<String> additionalPeople) { + mRankingBuilder.setAdditionalPeople(additionalPeople); + return this; + } + + public NotificationEntryBuilder setSnoozeCriteria( + ArrayList<SnoozeCriterion> snoozeCriteria) { + mRankingBuilder.setSnoozeCriteria(snoozeCriteria); + return this; + } + + public NotificationEntryBuilder setCanShowBadge(boolean canShowBadge) { + mRankingBuilder.setCanShowBadge(canShowBadge); + return this; + } + + public NotificationEntryBuilder setSuspended(boolean suspended) { + mRankingBuilder.setSuspended(suspended); + return this; + } + + public NotificationEntryBuilder setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) { + mRankingBuilder.setLastAudiblyAlertedMs(lastAudiblyAlertedMs); + return this; + } + + public NotificationEntryBuilder setNoisy(boolean noisy) { + mRankingBuilder.setNoisy(noisy); + return this; + } + + public NotificationEntryBuilder setCanBubble(boolean canBubble) { + mRankingBuilder.setCanBubble(canBubble); + return this; + } + + public NotificationEntryBuilder setImportance(@Importance int importance) { + mRankingBuilder.setImportance(importance); + return this; + } + + public NotificationEntryBuilder setUserSentiment(int userSentiment) { + mRankingBuilder.setUserSentiment(userSentiment); + return this; + } + + public NotificationEntryBuilder setChannel(NotificationChannel channel) { + mRankingBuilder.setChannel(channel); + return this; + } + + public NotificationEntryBuilder setSmartActions( + ArrayList<Notification.Action> smartActions) { + mRankingBuilder.setSmartActions(smartActions); + return this; + } + + public NotificationEntryBuilder setSmartReplies(ArrayList<CharSequence> smartReplies) { + mRankingBuilder.setSmartReplies(smartReplies); + return this; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java new file mode 100644 index 000000000000..b5168c6452d1 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import android.service.notification.NotificationListenerService.Ranking; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +@VisibleForTesting +public class NotificationEntryHelper { + public static ModifiedRankingBuilder modifyRanking(NotificationEntry entry) { + return new ModifiedRankingBuilder(entry); + } + + public static class ModifiedRankingBuilder extends RankingBuilder { + private final NotificationEntry mTarget; + + private ModifiedRankingBuilder(NotificationEntry target) { + super(target.ranking()); + mTarget = target; + } + + @Override + public Ranking build() { + final Ranking ranking = super.build(); + mTarget.setRanking(ranking); + return ranking; + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java index b044595e5a8e..350ab5afdf95 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java @@ -23,6 +23,7 @@ import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.google.common.truth.Truth.assertThat; @@ -40,9 +41,7 @@ import android.graphics.drawable.Icon; import android.hardware.display.AmbientDisplayConfiguration; import android.os.PowerManager; import android.os.RemoteException; -import android.os.UserHandle; import android.service.dreams.IDreamManager; -import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; @@ -231,15 +230,17 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { public void testCanAlertCommon_false_suppressedForGroups() { ensureStateForAlertCommon(); - Notification n = new Notification.Builder(getContext(), "a") - .setGroup("a") - .setGroupSummary(true) - .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(new Notification.Builder(getContext(), "a") + .setGroup("a") + .setGroupSummary(true) + .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) + .build()) + .setImportance(IMPORTANCE_DEFAULT) .build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.importance = IMPORTANCE_DEFAULT; assertThat(mNotifInterruptionStateProvider.canAlertCommon(entry)).isFalse(); } @@ -288,7 +289,9 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { ensureStateForHeadsUpWhenDozing(); NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT); - entry.suppressedVisualEffects = SUPPRESSED_EFFECT_AMBIENT; + modifyRanking(entry) + .setSuppressedVisualEffects(SUPPRESSED_EFFECT_AMBIENT) + .build(); assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse(); } @@ -379,7 +382,9 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { ensureStateForHeadsUpWhenAwake(); NotificationEntry entry = createNotification(IMPORTANCE_HIGH); - entry.suppressedVisualEffects = SUPPRESSED_EFFECT_PEEK; + modifyRanking(entry) + .setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK) + .build(); assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse(); } @@ -481,7 +486,9 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { ensureStateForBubbleUp(); NotificationEntry entry = createBubble(); - entry.canBubble = false; + modifyRanking(entry) + .setCanBubble(false) + .build(); assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse(); } @@ -494,7 +501,9 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { ensureStateForBubbleUp(); NotificationEntry entry = createNotification(IMPORTANCE_HIGH); - entry.canBubble = true; + modifyRanking(entry) + .setCanBubble(true) + .build(); assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse(); } @@ -507,8 +516,10 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { ensureStateForBubbleUp(); NotificationEntry entry = createNotification(IMPORTANCE_HIGH); - entry.canBubble = true; - entry.notification.getNotification().flags |= FLAG_BUBBLE; + modifyRanking(entry) + .setCanBubble(true) + .build(); + entry.sbn().getNotification().flags |= FLAG_BUBBLE; assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse(); } @@ -549,13 +560,16 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { .setContentText("content text") .setBubbleMetadata(data) .build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.notification.getNotification().flags |= FLAG_BUBBLE; - entry.importance = IMPORTANCE_HIGH; - entry.canBubble = true; - return entry; + n.flags |= FLAG_BUBBLE; + + return new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(IMPORTANCE_HIGH) + .setCanBubble(true) + .build(); } private NotificationEntry createNotification(int importance) { @@ -563,11 +577,14 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase { .setContentTitle("title") .setContentText("content text") .build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.importance = importance; - return entry; + + return new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(importance) + .build(); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 7cd58193a3e7..b1e76120b752 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -20,6 +20,8 @@ import static android.app.Notification.FLAG_BUBBLE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; + import static org.mockito.Mockito.mock; import android.annotation.Nullable; @@ -187,7 +189,9 @@ public class NotificationTestHelper { n.flags |= FLAG_BUBBLE; ExpandableNotificationRow row = generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); - row.getEntry().canBubble = true; + modifyRanking(row.getEntry()) + .setCanBubble(true) + .build(); return row; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java index f63389c911c9..d00be568cbff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java @@ -30,6 +30,7 @@ import com.android.systemui.SysuiTestCase; import org.junit.Test; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -199,11 +200,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { private NotificationUiAdjustment createUiAdjustmentFromSmartActions( String key, List<Notification.Action> actions) { - return new NotificationUiAdjustment(key, actions, new CharSequence[0]); + return new NotificationUiAdjustment(key, actions, null); } private NotificationUiAdjustment createUiAdjustmentFromSmartReplies( String key, CharSequence[] replies) { - return new NotificationUiAdjustment(key, Collections.emptyList(), replies); + return new NotificationUiAdjustment(key, null, Arrays.asList(replies)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java index bbdc4b7fc360..b45077ade3e3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java @@ -16,12 +16,15 @@ package com.android.systemui.statusbar; +import android.annotation.NonNull; import android.app.Notification; import android.app.NotificationChannel; +import android.app.NotificationManager.Importance; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; import java.util.ArrayList; +import java.util.List; /** * Standard builder class for Ranking objects. For use in tests that need to craft the underlying @@ -33,27 +36,143 @@ public class RankingBuilder { private boolean mMatchesInterruptionFilter = false; private int mVisibilityOverride = 0; private int mSuppressedVisualEffects = 0; - private int mImportance = 0; + @Importance private int mImportance = 0; private CharSequence mExplanation = "test_explanation"; private String mOverrideGroupKey = null; private NotificationChannel mChannel = null; - private ArrayList<String> mOverridePeople = null; + private ArrayList<String> mAdditionalPeople = null; private ArrayList<SnoozeCriterion> mSnoozeCriteria = null; - private boolean mShowBadge = false; + private boolean mCanShowBadge = false; private int mUserSentiment = 0; - private boolean mHidden = false; + private boolean mIsSuspended = false; private long mLastAudiblyAlertedMs = 0; private boolean mNoisy = false; - private ArrayList<Notification.Action> mSmartActions = null; - private ArrayList<CharSequence> mSmartReplies = null; + private ArrayList<Notification.Action> mSmartActions = new ArrayList<>(); + private ArrayList<CharSequence> mSmartReplies = new ArrayList<>(); private boolean mCanBubble = false; + public RankingBuilder() { + } + + public RankingBuilder(Ranking ranking) { + mKey = ranking.getKey(); + mRank = ranking.getRank(); + mMatchesInterruptionFilter = ranking.matchesInterruptionFilter(); + mVisibilityOverride = ranking.getVisibilityOverride(); + mSuppressedVisualEffects = ranking.getSuppressedVisualEffects(); + mImportance = ranking.getImportance(); + mExplanation = ranking.getImportanceExplanation(); + mOverrideGroupKey = ranking.getOverrideGroupKey(); + mChannel = ranking.getChannel(); + mAdditionalPeople = copyList(ranking.getAdditionalPeople()); + mSnoozeCriteria = copyList(ranking.getSnoozeCriteria()); + mCanShowBadge = ranking.canShowBadge(); + mUserSentiment = ranking.getUserSentiment(); + mIsSuspended = ranking.isSuspended(); + mLastAudiblyAlertedMs = ranking.getLastAudiblyAlertedMillis(); + mNoisy = ranking.isNoisy(); + mSmartActions = copyList(ranking.getSmartActions()); + mSmartReplies = copyList(ranking.getSmartReplies()); + mCanBubble = ranking.canBubble(); + } + + public Ranking build() { + final Ranking ranking = new Ranking(); + ranking.populate( + mKey, + mRank, + mMatchesInterruptionFilter, + mVisibilityOverride, + mSuppressedVisualEffects, + mImportance, + mExplanation, + mOverrideGroupKey, + mChannel, + mAdditionalPeople, + mSnoozeCriteria, + mCanShowBadge, + mUserSentiment, + mIsSuspended, + mLastAudiblyAlertedMs, + mNoisy, + mSmartActions, + mSmartReplies, + mCanBubble); + return ranking; + } + public RankingBuilder setKey(String key) { mKey = key; return this; } - public RankingBuilder setImportance(int importance) { + public RankingBuilder setRank(int rank) { + mRank = rank; + return this; + } + + public RankingBuilder setMatchesInterruptionFilter(boolean matchesInterruptionFilter) { + mMatchesInterruptionFilter = matchesInterruptionFilter; + return this; + } + + public RankingBuilder setVisibilityOverride(int visibilityOverride) { + mVisibilityOverride = visibilityOverride; + return this; + } + + public RankingBuilder setSuppressedVisualEffects(int suppressedVisualEffects) { + mSuppressedVisualEffects = suppressedVisualEffects; + return this; + } + + public RankingBuilder setExplanation(CharSequence explanation) { + mExplanation = explanation; + return this; + } + + public RankingBuilder setOverrideGroupKey(String overrideGroupKey) { + mOverrideGroupKey = overrideGroupKey; + return this; + } + + public RankingBuilder setAdditionalPeople(ArrayList<String> additionalPeople) { + mAdditionalPeople = additionalPeople; + return this; + } + + public RankingBuilder setSnoozeCriteria( + ArrayList<SnoozeCriterion> snoozeCriteria) { + mSnoozeCriteria = snoozeCriteria; + return this; + } + + public RankingBuilder setCanShowBadge(boolean canShowBadge) { + mCanShowBadge = canShowBadge; + return this; + } + + public RankingBuilder setSuspended(boolean suspended) { + mIsSuspended = suspended; + return this; + } + + public RankingBuilder setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) { + mLastAudiblyAlertedMs = lastAudiblyAlertedMs; + return this; + } + + public RankingBuilder setNoisy(boolean noisy) { + mNoisy = noisy; + return this; + } + + public RankingBuilder setCanBubble(boolean canBubble) { + mCanBubble = canBubble; + return this; + } + + public RankingBuilder setImportance(@Importance int importance) { mImportance = importance; return this; } @@ -68,38 +187,21 @@ public class RankingBuilder { return this; } - public RankingBuilder setSmartActions(ArrayList<Notification.Action> smartActions) { + public RankingBuilder setSmartActions(@NonNull ArrayList<Notification.Action> smartActions) { mSmartActions = smartActions; return this; } - public RankingBuilder setSmartReplies(ArrayList<CharSequence> smartReplies) { + public RankingBuilder setSmartReplies(@NonNull ArrayList<CharSequence> smartReplies) { mSmartReplies = smartReplies; return this; } - public Ranking build() { - final Ranking ranking = new Ranking(); - ranking.populate( - mKey, - mRank, - mMatchesInterruptionFilter, - mVisibilityOverride, - mSuppressedVisualEffects, - mImportance, - mExplanation, - mOverrideGroupKey, - mChannel, - mOverridePeople, - mSnoozeCriteria, - mShowBadge, - mUserSentiment, - mHidden, - mLastAudiblyAlertedMs, - mNoisy, - mSmartActions, - mSmartReplies, - mCanBubble); - return ranking; + private static <E> ArrayList<E> copyList(List<E> list) { + if (list == null) { + return null; + } else { + return new ArrayList<>(list); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java new file mode 100644 index 000000000000..a9aab7f56cd3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import android.app.Notification; +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; + +/** + * Convenience builder for {@link StatusBarNotification} since its constructor is terrifying. + * + * Only for use in tests. + */ +public class SbnBuilder { + private String mPkg = "test_pkg"; + private String mOpPkg; + private int mId; + private String mTag; + private int mUid; + private int mInitialPid; + private Notification mNotification = new Notification(); + private UserHandle mUser = UserHandle.of(0); + private String mOverrideGroupKey; + private long mPostTime; + + public StatusBarNotification build() { + return new StatusBarNotification( + mPkg, + mOpPkg, + mId, + mTag, + mUid, + mInitialPid, + mNotification, + mUser, + mOverrideGroupKey, + mPostTime); + } + + public SbnBuilder setPkg(String pkg) { + mPkg = pkg; + return this; + } + + public SbnBuilder setOpPkg(String opPkg) { + mOpPkg = opPkg; + return this; + } + + public SbnBuilder setId(int id) { + mId = id; + return this; + } + + public SbnBuilder setTag(String tag) { + mTag = tag; + return this; + } + + public SbnBuilder setUid(int uid) { + mUid = uid; + return this; + } + + public SbnBuilder setInitialPid(int initialPid) { + mInitialPid = initialPid; + return this; + } + + public SbnBuilder setNotification(Notification notification) { + mNotification = notification; + return this; + } + + public SbnBuilder setUser(UserHandle user) { + mUser = user; + return this; + } + + public SbnBuilder setOverrideGroupKey(String overrideGroupKey) { + mOverrideGroupKey = overrideGroupKey; + return this; + } + + public SbnBuilder setPostTime(long postTime) { + mPostTime = postTime; + return this; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 36b143bdace7..53d6bffdc896 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -65,6 +65,7 @@ import com.android.systemui.InitController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.NotificationEntryBuilder; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -237,9 +238,16 @@ public class NotificationEntryManagerTest extends SysuiTestCase { .setSmallIcon(R.drawable.ic_person) .setContentTitle("Title") .setContentText("Text"); - mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, - 0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0); - mEntry = NotificationEntry.buildForTest(mSbn); + + mEntry = new NotificationEntryBuilder() + .setPkg(TEST_PACKAGE_NAME) + .setOpPkg(TEST_PACKAGE_NAME) + .setUid(TEST_UID) + .setNotification(n.build()) + .setUser(new UserHandle(ActivityManager.getCurrentUser())) + .build(); + mSbn = mEntry.sbn(); + mEntry.expandedIcon = mock(StatusBarIconView.class); mEntryManager = new TestableNotificationEntryManager(mContext); @@ -292,7 +300,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry); assertNotNull(entry.getRow()); - assertEquals(mEntry.userSentiment, + assertEquals(mEntry.getUserSentiment(), NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL); } @@ -317,7 +325,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(mEntryListener).onPostEntryUpdated(mEntry); assertNotNull(mEntry.getRow()); - assertEquals(mEntry.userSentiment, + assertEquals(mEntry.getUserSentiment(), NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE); } @@ -403,8 +411,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.updateNotificationRanking(mRankingMap); verify(mRow).setEntry(eq(mEntry)); - assertEquals(1, mEntry.systemGeneratedSmartActions.size()); - assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title); + assertEquals(1, mEntry.getSmartActions().size()); + assertEquals("action", mEntry.getSmartActions().get(0).title); verify(mEntryListener).onNotificationRankingUpdated(mRankingMap); } @@ -419,7 +427,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.updateNotificationRanking(mRankingMap); verify(mRow, never()).setEntry(eq(mEntry)); - assertEquals(0, mEntry.systemGeneratedSmartActions.size()); + assertNull(mEntry.getSmartActions()); } @Test @@ -433,8 +441,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.updateNotificationRanking(mRankingMap); verify(mRow, never()).setEntry(eq(mEntry)); - assertEquals(1, mEntry.systemGeneratedSmartActions.size()); - assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title); + assertEquals(1, mEntry.getSmartActions().size()); + assertEquals("action", mEntry.getSmartActions().get(0).title); } @Test @@ -448,8 +456,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.updateNotificationRanking(mRankingMap); verify(mRow, never()).setEntry(eq(mEntry)); - assertEquals(1, mEntry.systemGeneratedSmartActions.size()); - assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title); + assertEquals(1, mEntry.getSmartActions().size()); + assertEquals("action", mEntry.getSmartActions().get(0).title); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java index b5223161dae4..edd0a10672fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java @@ -41,6 +41,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.ForegroundServiceController; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.NotificationEntryBuilder; import com.android.systemui.statusbar.NotificationTestHelper; import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -195,13 +196,16 @@ public class NotificationFilterTest extends SysuiTestCase { // test should filter out hidden notifications: // hidden - NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); - entry.suspended = true; + NotificationEntry entry = new NotificationEntryBuilder() + .setSuspended(true) + .build(); + assertTrue(mNotificationFilter.shouldFilterOut(entry)); // not hidden - entry = NotificationEntry.buildForTest(mMockStatusBarNotification); - entry.suspended = false; + entry = new NotificationEntryBuilder() + .setSuspended(false) + .build(); assertFalse(mNotificationFilter.shouldFilterOut(entry)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java index 45173a2ef797..365b80b50723 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java @@ -342,10 +342,10 @@ public class NotificationDataTest extends SysuiTestCase { NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification, ranking); - assertEquals(systemGeneratedSmartActions, entry.systemGeneratedSmartActions); + assertEquals(systemGeneratedSmartActions, entry.getSmartActions()); assertEquals(NOTIFICATION_CHANNEL, entry.getChannel()); - assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.userSentiment); - assertEquals(snoozeCriterions, entry.snoozeCriteria); + assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.getUserSentiment()); + assertEquals(snoozeCriterions, entry.getSnoozeCriteria()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index a14557bd9684..c56a168a29d9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL; import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP; import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC; @@ -51,7 +52,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationTestHelper; -import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer; @@ -328,11 +328,11 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { // Give each child a unique channel id/name. int i = 0; for (ExpandableNotificationRow childRow : childRows) { - childRow.getEntry().setRanking(new RankingBuilder() + modifyRanking(childRow.getEntry()) .setChannel( new NotificationChannel( "id" + i, "dinnertime" + i, IMPORTANCE_DEFAULT)) - .build()); + .build(); i++; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java index a26cdbd30b47..6d6439532912 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java @@ -21,6 +21,8 @@ import static android.service.notification.NotificationListenerService.Ranking.U import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -44,7 +46,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.NotificationTestHelper; -import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.util.Assert; @@ -130,7 +131,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Test public void testPerhapsShowBlockingHelper_shown() throws Exception { ExpandableNotificationRow row = createBlockableRowSpy(); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow)); @@ -142,14 +145,16 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10); int i = 0; for (ExpandableNotificationRow childRow : groupRow.getNotificationChildren()) { - childRow.getEntry().setRanking(new RankingBuilder() + modifyRanking(childRow.getEntry()) .setChannel( new NotificationChannel( Integer.toString(i++), "", IMPORTANCE_DEFAULT)) - .build()); + .build(); } - groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(groupRow.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow)); @@ -159,7 +164,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Test public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception { ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10); - groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(groupRow.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow)); @@ -174,7 +181,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { // as other factors such as view expansion may cause us to get the parent row back instead // of the child row. ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0); - childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(childRow.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertFalse(childRow.getIsNonblockable()); assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow)); @@ -185,7 +194,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Test public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception { ExpandableNotificationRow row = createBlockableRowSpy(); - row.getEntry().userSentiment = USER_SENTIMENT_NEUTRAL; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEUTRAL) + .build(); assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow)); } @@ -194,7 +205,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment() throws Exception { ExpandableNotificationRow row = createBlockableRowSpy(); - row.getEntry().userSentiment = USER_SENTIMENT_POSITIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_POSITIVE) + .build(); assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow)); } @@ -202,7 +215,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Test public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception { ExpandableNotificationRow row = createBlockableRowSpy(); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); // Hide the shade mBlockingHelperManager.setNotificationShadeExpanded(0f); @@ -213,7 +228,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception { ExpandableNotificationRow row = createBlockableRowSpy(); when(row.getIsNonblockable()).thenReturn(true); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow)); } @@ -226,7 +243,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { // as other factors such as view expansion may cause us to get the parent row back instead // of the child row. ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0); - childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(childRow.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow)); } @@ -234,7 +253,9 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Test public void testBlockingHelperShowAndDismiss() throws Exception{ ExpandableNotificationRow row = createBlockableRowSpy(); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); when(row.isAttachedToWindow()).thenReturn(true); // Show check diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 09c4179185fc..db6b6130ebf1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -22,6 +22,8 @@ import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; + import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; @@ -62,7 +64,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationTestHelper; -import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -313,7 +314,9 @@ public class NotificationGutsManagerTest extends SysuiTestCase { NotificationInfo notificationInfoView = mock(NotificationInfo.class); ExpandableNotificationRow row = spy(mHelper.createRow()); row.setBlockingHelperShowing(true); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); when(row.getIsNonblockable()).thenReturn(false); StatusBarNotification statusBarNotification = row.getStatusBarNotification(); @@ -342,7 +345,9 @@ public class NotificationGutsManagerTest extends SysuiTestCase { NotificationInfo notificationInfoView = mock(NotificationInfo.class); ExpandableNotificationRow row = spy(mHelper.createRow()); row.setBlockingHelperShowing(false); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); when(row.getIsNonblockable()).thenReturn(false); StatusBarNotification statusBarNotification = row.getStatusBarNotification(); @@ -371,8 +376,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase { NotificationInfo notificationInfoView = mock(NotificationInfo.class); ExpandableNotificationRow row = spy(mHelper.createRow()); row.setBlockingHelperShowing(true); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; - row.getEntry().importance = IMPORTANCE_DEFAULT; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .setImportance(IMPORTANCE_DEFAULT) + .build(); row.getEntry().setIsHighPriority(true); when(row.getIsNonblockable()).thenReturn(false); StatusBarNotification statusBarNotification = row.getStatusBarNotification(); @@ -402,7 +409,9 @@ public class NotificationGutsManagerTest extends SysuiTestCase { NotificationInfo notificationInfoView = mock(NotificationInfo.class); ExpandableNotificationRow row = spy(mHelper.createRow()); row.setBlockingHelperShowing(false); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); when(row.getIsNonblockable()).thenReturn(false); StatusBarNotification statusBarNotification = row.getStatusBarNotification(); when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true); @@ -432,7 +441,9 @@ public class NotificationGutsManagerTest extends SysuiTestCase { NotificationInfo notificationInfoView = mock(NotificationInfo.class); ExpandableNotificationRow row = spy(mHelper.createRow()); row.setBlockingHelperShowing(true); - row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; + modifyRanking(row.getEntry()) + .setUserSentiment(USER_SENTIMENT_NEGATIVE) + .build(); when(row.getIsNonblockable()).thenReturn(false); StatusBarNotification statusBarNotification = row.getStatusBarNotification(); @@ -499,10 +510,9 @@ public class NotificationGutsManagerTest extends SysuiTestCase { try { ExpandableNotificationRow row = mHelper.createRow(nb.build()); - row.getEntry().setRanking( - new RankingBuilder() - .setChannel(mTestNotificationChannel) - .build()); + modifyRanking(row.getEntry()) + .setChannel(mTestNotificationChannel) + .build(); return row; } catch (Exception e) { fail(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index a1afd1d9de29..4eb9a3151116 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -51,9 +51,7 @@ import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; -import android.os.UserHandle; import android.service.dreams.IDreamManager; -import android.service.notification.StatusBarNotification; import android.support.test.metricshelper.MetricsAsserts; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -88,6 +86,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NavigationBarController; +import com.android.systemui.statusbar.NotificationEntryBuilder; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; @@ -417,10 +416,14 @@ public class StatusBarTest extends SysuiTestCase { .setGroupSummary(true) .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY) .build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.importance = IMPORTANCE_HIGH; + + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(IMPORTANCE_HIGH) + .build(); assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); } @@ -438,10 +441,14 @@ public class StatusBarTest extends SysuiTestCase { .setGroupSummary(true) .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) .build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.importance = IMPORTANCE_HIGH; + + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(IMPORTANCE_HIGH) + .build(); assertFalse(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); } @@ -455,11 +462,15 @@ public class StatusBarTest extends SysuiTestCase { when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true); Notification n = new Notification.Builder(getContext(), "a").build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.suppressedVisualEffects = SUPPRESSED_EFFECT_PEEK; - entry.importance = IMPORTANCE_HIGH; + + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(IMPORTANCE_HIGH) + .setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK) + .build(); assertFalse(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); } @@ -473,10 +484,14 @@ public class StatusBarTest extends SysuiTestCase { when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true); Notification n = new Notification.Builder(getContext(), "a").build(); - StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, - UserHandle.of(0), null, 0); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); - entry.importance = IMPORTANCE_HIGH; + + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("a") + .setOpPkg("a") + .setTag("a") + .setNotification(n) + .setImportance(IMPORTANCE_HIGH) + .build(); assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java index bda0e39fb572..c1f376bee525 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java @@ -15,6 +15,8 @@ package com.android.systemui.statusbar.policy; +import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; @@ -29,7 +31,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ResolveInfo; import android.graphics.drawable.Icon; -import android.service.notification.StatusBarNotification; import android.util.Pair; import androidx.test.annotation.UiThreadTest; @@ -41,6 +42,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; +import com.android.systemui.statusbar.NotificationEntryBuilder; +import com.android.systemui.statusbar.NotificationEntryHelper; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; import com.android.systemui.statusbar.policy.SmartReplyView.SmartActions; @@ -65,7 +68,6 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { new Intent("com.android.WHITELISTED_TEST_ACTION"); @Mock SmartReplyConstants mSmartReplyConstants; - @Mock StatusBarNotification mStatusBarNotification; @Mock Notification mNotification; NotificationEntry mEntry; @Mock RemoteInput mRemoteInput; @@ -87,8 +89,9 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { mDependency.injectTestDependency(PackageManagerWrapper.class, mPackageManagerWrapper); when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(true); - when(mStatusBarNotification.getNotification()).thenReturn(mNotification); - mEntry = NotificationEntry.buildForTest(mStatusBarNotification); + mEntry = new NotificationEntryBuilder() + .setNotification(mNotification) + .build(); when(mSmartReplyConstants.isEnabled()).thenReturn(true); mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person); @@ -99,7 +102,7 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { public void chooseSmartRepliesAndActions_smartRepliesOff_noAppGeneratedSmartSuggestions() { CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"}; List<Notification.Action> smartActions = - createActions(new String[] {"Test Action 1", "Test Action 2"}); + createActions("Test Action 1", "Test Action 2"); setupAppGeneratedSuggestions(smartReplies, smartActions); when(mSmartReplyConstants.isEnabled()).thenReturn(false); @@ -112,10 +115,11 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { @Test public void chooseSmartRepliesAndActions_smartRepliesOff_noSystemGeneratedSmartSuggestions() { - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); + when(mSmartReplyConstants.isEnabled()).thenReturn(false); SmartRepliesAndActions repliesAndActions = @@ -133,7 +137,7 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); - assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies); + assertThat(repliesAndActions.smartReplies.choices).isEqualTo(Arrays.asList(smartReplies)); assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse(); assertThat(repliesAndActions.smartActions).isNull(); } @@ -142,13 +146,13 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { public void chooseSmartRepliesAndActions_appGeneratedSmartRepliesAndActions() { CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"}; List<Notification.Action> smartActions = - createActions(new String[] {"Test Action 1", "Test Action 2"}); + createActions("Test Action 1", "Test Action 2"); setupAppGeneratedSuggestions(smartReplies, smartActions); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); - assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies); + assertThat(repliesAndActions.smartReplies.choices).isEqualTo(Arrays.asList(smartReplies)); assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse(); assertThat(repliesAndActions.smartActions.actions).isEqualTo(smartActions); assertThat(repliesAndActions.smartActions.fromAssistant).isFalse(); @@ -160,13 +164,15 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // replies. setupAppGeneratedReplies(null /* smartReplies */); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .build(); + SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); assertThat(repliesAndActions.smartReplies.choices).isEqualTo( - mEntry.systemGeneratedSmartReplies); + mEntry.getSmartReplies()); assertThat(repliesAndActions.smartReplies.fromAssistant).isTrue(); assertThat(repliesAndActions.smartActions).isNull(); } @@ -177,8 +183,9 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // replies. setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; + NotificationEntryHelper.modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); @@ -192,14 +199,15 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // actions. setupAppGeneratedReplies(null /* smartReplies */); - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + modifyRanking(mEntry) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); assertThat(repliesAndActions.smartReplies).isNull(); assertThat(repliesAndActions.smartActions.actions) - .isEqualTo(mEntry.systemGeneratedSmartActions); + .isEqualTo(mEntry.getSmartActions()); assertThat(repliesAndActions.smartActions.fromAssistant).isTrue(); } @@ -209,18 +217,19 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart // replies. List<Notification.Action> appGenSmartActions = - createActions(new String[] {"Test Action 1", "Test Action 2"}); + createActions("Test Action 1", "Test Action 2"); setupAppGeneratedSuggestions(appGenSmartReplies, appGenSmartActions); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); - assertThat(repliesAndActions.smartReplies.choices).isEqualTo(appGenSmartReplies); + assertThat(repliesAndActions.smartReplies.choices) + .isEqualTo(Arrays.asList(appGenSmartReplies)); assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse(); assertThat(repliesAndActions.smartActions.actions).isEqualTo(appGenSmartActions); assertThat(repliesAndActions.smartActions.fromAssistant).isFalse(); @@ -232,10 +241,11 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // actions. setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */); when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(false); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); @@ -253,16 +263,17 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart // suggestions. setupAppGeneratedReplies(null /* smartReplies */); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); assertThat(repliesAndActions.smartReplies.choices).isEqualTo( - mEntry.systemGeneratedSmartReplies); + mEntry.getSmartReplies()); // Since no apps are whitelisted no actions should be shown. assertThat(repliesAndActions.smartActions.actions).isEmpty(); } @@ -285,12 +296,14 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart // suggestions. setupAppGeneratedReplies(null /* smartReplies */); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - List<Notification.Action> actions = new ArrayList<>(); + ArrayList<Notification.Action> actions = new ArrayList<>(); actions.add(createAction("allowed action", WHITELISTED_TEST_INTENT)); actions.add(createAction("non-allowed action", TEST_INTENT)); - mEntry.systemGeneratedSmartActions = actions; + + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(actions) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); @@ -298,7 +311,7 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // Only the action for the whitelisted package should be allowed. assertThat(repliesAndActions.smartActions.actions.size()).isEqualTo(1); assertThat(repliesAndActions.smartActions.actions.get(0)).isEqualTo( - mEntry.systemGeneratedSmartActions.get(0)); + mEntry.getSmartActions().get(0)); } @Test @@ -310,25 +323,25 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart // suggestions. setupAppGeneratedReplies(null /* smartReplies */); - mEntry.systemGeneratedSmartReplies = - new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"}; - mEntry.systemGeneratedSmartActions = - createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"}); + modifyRanking(mEntry) + .setSmartReplies(createReplies("Sys Smart Reply 1", "Sys Smart Reply 2")) + .setSmartActions(createActions("Sys Smart Action 1", "Sys Smart Action 2")) + .build(); SmartRepliesAndActions repliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry); // We don't restrict replies or actions in screen pinning mode. assertThat(repliesAndActions.smartReplies.choices).isEqualTo( - mEntry.systemGeneratedSmartReplies); + mEntry.getSmartReplies()); assertThat(repliesAndActions.smartActions.actions).isEqualTo( - mEntry.systemGeneratedSmartActions); + mEntry.getSmartActions()); } @Test public void areSuggestionsSimilar_trueForSimilar() { - CharSequence[] leftReplies = new CharSequence[] { "first reply", "second reply"}; - CharSequence[] rightReplies = new CharSequence[] { "first reply", "second reply"}; + List<CharSequence> leftReplies = createReplies("first reply", "second reply"); + List<CharSequence> rightReplies = createReplies("first reply", "second reply"); List<Notification.Action> leftActions = Arrays.asList( createAction("firstAction"), createAction("secondAction")); @@ -349,8 +362,8 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { @Test public void areSuggestionsSimilar_falseForDifferentReplies() { - CharSequence[] leftReplies = new CharSequence[] { "first reply"}; - CharSequence[] rightReplies = new CharSequence[] { "first reply", "second reply"}; + List<CharSequence> leftReplies = createReplies("first reply"); + List<CharSequence> rightReplies = createReplies("first reply", "second reply"); List<Notification.Action> leftActions = Arrays.asList( createAction("firstAction"), createAction("secondAction")); @@ -371,8 +384,8 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { @Test public void areSuggestionsSimilar_falseForDifferentActions() { - CharSequence[] leftReplies = new CharSequence[] { "first reply", "second reply"}; - CharSequence[] rightReplies = new CharSequence[] { "first reply", "second reply"}; + List<CharSequence> leftReplies = createReplies("first reply", "second reply"); + List<CharSequence> rightReplies = createReplies("first reply", "second reply"); List<Notification.Action> leftActions = Arrays.asList( createAction("firstAction"), createAction("secondAction")); @@ -441,11 +454,15 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { return createActionBuilder(actionTitle, intent).build(); } - private List<Notification.Action> createActions(String[] actionTitles) { - List<Notification.Action> actions = new ArrayList<>(); + private ArrayList<Notification.Action> createActions(String... actionTitles) { + ArrayList<Notification.Action> actions = new ArrayList<>(); for (String title : actionTitles) { actions.add(createAction(title)); } return actions; } + + private ArrayList<CharSequence> createReplies(CharSequence... replies) { + return new ArrayList<>(Arrays.asList(replies)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java index 8e3e2db5209e..9831ce3c07ce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java @@ -66,6 +66,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -470,7 +471,11 @@ public class SmartReplyViewTest extends SysuiTestCase { new Intent(TEST_ACTION), 0); RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build(); SmartReplyView.SmartReplies smartReplies = - new SmartReplyView.SmartReplies(choices, input, pendingIntent, fromAssistant); + new SmartReplyView.SmartReplies( + Arrays.asList(choices), + input, + pendingIntent, + fromAssistant); return mView.inflateRepliesFromRemoteInput(smartReplies, mLogger, mEntry, useDelayedOnClickListener); } @@ -555,7 +560,7 @@ public class SmartReplyViewTest extends SysuiTestCase { // Add smart replies Button previous = null; SmartReplyView.SmartReplies smartReplies = - new SmartReplyView.SmartReplies(choices, null, null, false); + new SmartReplyView.SmartReplies(Arrays.asList(choices), null, null, false); for (int i = 0; i < choices.length; ++i) { Button current = SmartReplyView.inflateReplyButton(mView, mContext, i, smartReplies, null /* SmartReplyController */, null /* NotificationEntry */, diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml index dc77981e6c95..0ff85fe39c99 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Сделать вырез в углу"</string> + <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"В правом углу"</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml index a02eaf7bdc26..2493da34af1f 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Увеличить вырез вдвое"</string> + <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Сверху и снизу"</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml index 1d1656d2862e..89ac1c3e1b11 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сделать вырез выше"</string> + <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сверху"</string> </resources> diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 1d936f263cb8..cdb062d1963c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -352,7 +352,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ @Override public List<AccessibilityWindowInfo> getWindows() { - ensureWindowsAvailableTimed(); + ensureWindowsAvailableTimed(Display.DEFAULT_DISPLAY); synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return null; @@ -362,8 +362,6 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ if (!permissionGranted) { return null; } - // TODO [Multi-Display] (b/134891479) : - // using correct display Id to replace DEFAULT_DISPLAY. List<AccessibilityWindowInfo> internalWindowList = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); if (internalWindowList == null) { @@ -387,7 +385,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ @Override public AccessibilityWindowInfo getWindow(int windowId) { - ensureWindowsAvailableTimed(); + int displayId = Display.INVALID_DISPLAY; + synchronized (mLock) { + if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) { + displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked( + mSystemSupport.getCurrentUserIdLocked(), windowId); + } + } + ensureWindowsAvailableTimed(displayId); synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return null; @@ -1308,28 +1313,28 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ /** * Request that the system make sure windows are available to interrogate. + * + * @param displayId The logical display id. */ - private void ensureWindowsAvailableTimed() { + private void ensureWindowsAvailableTimed(int displayId) { synchronized (mLock) { - // TODO [Multi-Display] (b/134891479) : - // using correct display Id to replace DEFAULT_DISPLAY. - if (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) != null) { + if (mA11yWindowManager.getWindowListLocked(displayId) != null) { return; } // If we have no registered callback, update the state we // we may have to register one but it didn't happen yet. - if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) { + if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { // Invokes client change to make sure tracking window enabled. mSystemSupport.onClientChangeLocked(false); } // We have no windows but do not care about them, done. - if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) { + if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { return; } // Wait for the windows with a timeout. final long startMillis = SystemClock.uptimeMillis(); - while (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) == null) { + while (mA11yWindowManager.getWindowListLocked(displayId) == null) { final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; if (remainMillis <= 0) { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index ddf5bbec7eb1..feb7329bdda6 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -580,17 +580,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // Make sure clients receiving this event will be able to get the // current state of the windows as the window manager may be delaying // the computation for performance reasons. - // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY. boolean shouldComputeWindows = false; + int displayId = Display.INVALID_DISPLAY; synchronized (mLock) { + final int windowId = event.getWindowId(); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED - && mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) { + && windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) { + displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked( + mCurrentUserId, windowId); + } + if (displayId != Display.INVALID_DISPLAY + && mA11yWindowManager.isTrackingWindowsLocked(displayId)) { shouldComputeWindows = true; } } if (shouldComputeWindows) { - WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class); - wm.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY); + final WindowManagerInternal wm = LocalServices.getService( + WindowManagerInternal.class); + wm.computeWindowsForAccessibility(displayId); } synchronized (mLock) { notifyAccessibilityServicesDelayedLocked(event, false); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index 82a593cdfd7f..0038a27db384 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -1463,6 +1463,20 @@ public class AccessibilityWindowManager { } /** + * Returns the display ID according to given userId and windowId. + * + * @param userId The userId + * @param windowId The windowId + * @return The display ID + */ + public int getDisplayIdByUserIdAndWindowIdLocked(int userId, int windowId) { + final IBinder windowToken = getWindowTokenForUserAndWindowIdLocked(userId, windowId); + final int displayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken); + + return displayId; + } + + /** * Gets current input focused window token from window manager, and returns its windowId. * * @param userId The userId diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 39866a72ab98..fea4e9047f83 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -19,6 +19,7 @@ package com.android.server.appwidget; import static android.content.Context.KEYGUARD_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.annotation.UserIdInt; @@ -856,13 +857,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku ArrayList<PendingHostUpdate> outUpdates = new ArrayList<>(N); LongSparseArray<PendingHostUpdate> updatesMap = new LongSparseArray<>(); for (int i = 0; i < N; i++) { - if (host.getPendingUpdatesForId(appWidgetIds[i], updatesMap)) { - // We key the updates based on request id, so that the values are sorted in the - // order they were received. - int M = updatesMap.size(); - for (int j = 0; j < M; j++) { - outUpdates.add(updatesMap.valueAt(j)); - } + updatesMap.clear(); + host.getPendingUpdatesForId(appWidgetIds[i], updatesMap); + // We key the updates based on request id, so that the values are sorted in the + // order they were received. + int m = updatesMap.size(); + for (int j = 0; j < m; j++) { + outUpdates.add(updatesMap.valueAt(j)); } } // Reset the update counter once all the updates have been calculated @@ -2102,6 +2103,40 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + private void scheduleNotifyAppWidgetRemovedLocked(Widget widget) { + long requestId = UPDATE_COUNTER.incrementAndGet(); + if (widget != null) { + widget.updateSequenceNos.clear(); + } + if (widget == null || widget.provider == null || widget.provider.zombie + || widget.host.callbacks == null || widget.host.zombie) { + return; + } + + SomeArgs args = SomeArgs.obtain(); + args.arg1 = widget.host; + args.arg2 = widget.host.callbacks; + args.arg3 = requestId; + args.argi1 = widget.appWidgetId; + + mCallbackHandler.obtainMessage( + CallbackHandler.MSG_NOTIFY_APP_WIDGET_REMOVED, + args).sendToTarget(); + } + + private void handleNotifyAppWidgetRemoved(Host host, IAppWidgetHost callbacks, int appWidgetId, + long requestId) { + try { + callbacks.appWidgetRemoved(appWidgetId); + host.lastWidgetUpdateSequenceNo = requestId; + } catch (RemoteException re) { + synchronized (mLock) { + Slog.e(TAG, "Widget host dead: " + host.id, re); + host.callbacks = null; + } + } + } + private void scheduleNotifyGroupHostsForProvidersChangedLocked(int userId) { final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); @@ -2870,8 +2905,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku */ void removeWidgetLocked(Widget widget) { mWidgets.remove(widget); - onWidgetRemovedLocked(widget); + scheduleNotifyAppWidgetRemovedLocked(widget); } private void onWidgetRemovedLocked(Widget widget) { @@ -3587,6 +3622,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2; public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3; public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4; + public static final int MSG_NOTIFY_APP_WIDGET_REMOVED = 5; public CallbackHandler(Looper looper) { super(looper, null, false); @@ -3619,6 +3655,16 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku handleNotifyProviderChanged(host, callbacks, appWidgetId, info, requestId); } break; + case MSG_NOTIFY_APP_WIDGET_REMOVED: { + SomeArgs args = (SomeArgs) message.obj; + Host host = (Host) args.arg1; + IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; + long requestId = (Long) args.arg3; + final int appWidgetId = args.argi1; + args.recycle(); + handleNotifyAppWidgetRemoved(host, callbacks, appWidgetId, requestId); + } break; + case MSG_NOTIFY_PROVIDERS_CHANGED: { SomeArgs args = (SomeArgs) message.obj; Host host = (Host) args.arg1; @@ -4017,14 +4063,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku /** * Adds all pending updates in {@param outUpdates} keys by the update time. */ - public boolean getPendingUpdatesForId(int appWidgetId, + public void getPendingUpdatesForId(int appWidgetId, LongSparseArray<PendingHostUpdate> outUpdates) { long updateSequenceNo = lastWidgetUpdateSequenceNo; int N = widgets.size(); for (int i = 0; i < N; i++) { Widget widget = widgets.get(i); if (widget.appWidgetId == appWidgetId) { - outUpdates.clear(); for (int j = widget.updateSequenceNos.size() - 1; j >= 0; j--) { long requestId = widget.updateSequenceNos.valueAt(j); if (requestId <= updateSequenceNo) { @@ -4046,10 +4091,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } outUpdates.put(requestId, update); } - return true; + return; } } - return false; + outUpdates.put(lastWidgetUpdateSequenceNo, + PendingHostUpdate.appWidgetRemoved(appWidgetId)); } @Override diff --git a/services/core/java/com/android/server/MountServiceIdler.java b/services/core/java/com/android/server/MountServiceIdler.java index 1891ba9b1742..79b1226a3f7e 100644 --- a/services/core/java/com/android/server/MountServiceIdler.java +++ b/services/core/java/com/android/server/MountServiceIdler.java @@ -27,6 +27,7 @@ import android.content.ComponentName; import android.content.Context; import android.os.RemoteException; import android.util.Slog; +import java.util.concurrent.TimeUnit; public class MountServiceIdler extends JobService { private static final String TAG = "MountServiceIdler"; @@ -48,7 +49,7 @@ public class MountServiceIdler extends JobService { mStarted = false; } } - // ... and try again tomorrow + // ... and try again right away or tomorrow scheduleIdlePass(MountServiceIdler.this); } }; @@ -98,24 +99,36 @@ public class MountServiceIdler extends JobService { public static void scheduleIdlePass(Context context) { JobScheduler tm = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - Calendar calendar = tomorrowMidnight(); - final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis(); + final long today3AM = MidnightInTime(0, 0).getTimeInMillis(); + final long today4AM = MidnightInTime(0, 1).getTimeInMillis(); + + long nextScheduleTime, maxScheduleTime; + if (System.currentTimeMillis() > today3AM && System.currentTimeMillis() < today4AM) { + nextScheduleTime = TimeUnit.SECONDS.toMillis(10); + maxScheduleTime = today4AM - System.currentTimeMillis(); + } else { + final long tomorrow3AM = MidnightInTime(1, 0).getTimeInMillis(); + final long twodays3AM = MidnightInTime(2, 0).getTimeInMillis(); + nextScheduleTime = tomorrow3AM - System.currentTimeMillis(); // 3AM tomorrow + maxScheduleTime = twodays3AM - System.currentTimeMillis(); // 3AM in two days + } JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService); builder.setRequiresDeviceIdle(true); builder.setRequiresCharging(true); - builder.setMinimumLatency(timeToMidnight); + builder.setMinimumLatency(nextScheduleTime); + builder.setOverrideDeadline(maxScheduleTime); tm.schedule(builder.build()); } - private static Calendar tomorrowMidnight() { + private static Calendar MidnightInTime(int nDays, int nHours) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.HOUR_OF_DAY, 3); + calendar.set(Calendar.HOUR_OF_DAY, 3 + nHours); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); - calendar.add(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DAY_OF_MONTH, nDays); return calendar; } } diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 3fbb21e1bb48..20a9b20dd385 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -204,7 +204,7 @@ public class PackageWatchdog { synchronized (mLock) { ObserverInternal internalObserver = mAllObservers.get(observer.getName()); if (internalObserver != null) { - internalObserver.mRegisteredObserver = observer; + internalObserver.registeredObserver = observer; } } } @@ -307,7 +307,7 @@ public class PackageWatchdog { // Find observer with least user impact for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) { ObserverInternal observer = mAllObservers.valueAt(oIndex); - PackageHealthObserver registeredObserver = observer.mRegisteredObserver; + PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null && observer.onPackageFailureLocked( versionedPackage.getPackageName())) { @@ -458,7 +458,7 @@ public class PackageWatchdog { synchronized (mLock) { for (int observerIdx = 0; observerIdx < mAllObservers.size(); observerIdx++) { ObserverInternal observer = mAllObservers.valueAt(observerIdx); - MonitoredPackage monitoredPackage = observer.mPackages.get(packageName); + MonitoredPackage monitoredPackage = observer.packages.get(packageName); if (monitoredPackage != null) { int oldState = monitoredPackage.getHealthCheckStateLocked(); @@ -487,7 +487,7 @@ public class PackageWatchdog { Slog.d(TAG, "Received supported packages " + supportedPackages); Iterator<ObserverInternal> oit = mAllObservers.values().iterator(); while (oit.hasNext()) { - Iterator<MonitoredPackage> pit = oit.next().mPackages.values().iterator(); + Iterator<MonitoredPackage> pit = oit.next().packages.values().iterator(); while (pit.hasNext()) { MonitoredPackage monitoredPackage = pit.next(); String packageName = monitoredPackage.getName(); @@ -520,7 +520,7 @@ public class PackageWatchdog { while (oit.hasNext()) { ObserverInternal observer = oit.next(); Iterator<MonitoredPackage> pit = - observer.mPackages.values().iterator(); + observer.packages.values().iterator(); while (pit.hasNext()) { MonitoredPackage monitoredPackage = pit.next(); String packageName = monitoredPackage.getName(); @@ -578,7 +578,7 @@ public class PackageWatchdog { private long getNextStateSyncMillisLocked() { long shortestDurationMs = Long.MAX_VALUE; for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) { - ArrayMap<String, MonitoredPackage> packages = mAllObservers.valueAt(oIndex).mPackages; + ArrayMap<String, MonitoredPackage> packages = mAllObservers.valueAt(oIndex).packages; for (int pIndex = 0; pIndex < packages.size(); pIndex++) { MonitoredPackage mp = packages.valueAt(pIndex); long duration = mp.getShortestScheduleDurationMsLocked(); @@ -612,8 +612,8 @@ public class PackageWatchdog { if (!failedPackages.isEmpty()) { onHealthCheckFailed(observer, failedPackages); } - if (observer.mPackages.isEmpty()) { - Slog.i(TAG, "Discarding observer " + observer.mName + ". All packages expired"); + if (observer.packages.isEmpty()) { + Slog.i(TAG, "Discarding observer " + observer.name + ". All packages expired"); it.remove(); } } @@ -623,7 +623,7 @@ public class PackageWatchdog { Set<MonitoredPackage> failedPackages) { mLongTaskHandler.post(() -> { synchronized (mLock) { - PackageHealthObserver registeredObserver = observer.mRegisteredObserver; + PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null) { Iterator<MonitoredPackage> it = failedPackages.iterator(); while (it.hasNext()) { @@ -677,7 +677,7 @@ public class PackageWatchdog { while (XmlUtils.nextElementWithin(parser, outerDepth)) { ObserverInternal observer = ObserverInternal.read(parser, this); if (observer != null) { - mAllObservers.put(observer.mName, observer); + mAllObservers.put(observer.name, observer); } } } catch (FileNotFoundException e) { @@ -803,18 +803,17 @@ public class PackageWatchdog { * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing * instances of this class. */ - //TODO(b/120598832): Remove 'm' from non-private fields private static class ObserverInternal { - public final String mName; + public final String name; //TODO(b/120598832): Add getter for mPackages @GuardedBy("mLock") - public final ArrayMap<String, MonitoredPackage> mPackages = new ArrayMap<>(); + public final ArrayMap<String, MonitoredPackage> packages = new ArrayMap<>(); @Nullable @GuardedBy("mLock") - public PackageHealthObserver mRegisteredObserver; + public PackageHealthObserver registeredObserver; ObserverInternal(String name, List<MonitoredPackage> packages) { - mName = name; + this.name = name; updatePackagesLocked(packages); } @@ -826,9 +825,9 @@ public class PackageWatchdog { public boolean writeLocked(XmlSerializer out) { try { out.startTag(null, TAG_OBSERVER); - out.attribute(null, ATTR_NAME, mName); - for (int i = 0; i < mPackages.size(); i++) { - MonitoredPackage p = mPackages.valueAt(i); + out.attribute(null, ATTR_NAME, name); + for (int i = 0; i < packages.size(); i++) { + MonitoredPackage p = packages.valueAt(i); p.writeLocked(out); } out.endTag(null, TAG_OBSERVER); @@ -843,7 +842,7 @@ public class PackageWatchdog { public void updatePackagesLocked(List<MonitoredPackage> packages) { for (int pIndex = 0; pIndex < packages.size(); pIndex++) { MonitoredPackage p = packages.get(pIndex); - mPackages.put(p.mName, p); + this.packages.put(p.mName, p); } } @@ -860,7 +859,7 @@ public class PackageWatchdog { @GuardedBy("mLock") private Set<MonitoredPackage> prunePackagesLocked(long elapsedMs) { Set<MonitoredPackage> failedPackages = new ArraySet<>(); - Iterator<MonitoredPackage> it = mPackages.values().iterator(); + Iterator<MonitoredPackage> it = packages.values().iterator(); while (it.hasNext()) { MonitoredPackage p = it.next(); int oldState = p.getHealthCheckStateLocked(); @@ -883,7 +882,7 @@ public class PackageWatchdog { */ @GuardedBy("mLock") public boolean onPackageFailureLocked(String packageName) { - MonitoredPackage p = mPackages.get(packageName); + MonitoredPackage p = packages.get(packageName); if (p != null) { return p.onFailureLocked(); } diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java index 1517887efec2..997178e1582b 100644 --- a/services/core/java/com/android/server/RecoverySystemService.java +++ b/services/core/java/com/android/server/RecoverySystemService.java @@ -25,15 +25,12 @@ import android.os.PowerManager; import android.os.RecoverySystem; import android.os.RemoteException; import android.os.SystemProperties; -import android.system.ErrnoException; -import android.system.Os; import android.util.Slog; import libcore.io.IoUtils; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -288,7 +285,6 @@ public final class RecoverySystemService extends SystemService { byte[] cmdUtf8 = command.getBytes("UTF-8"); dos.writeInt(cmdUtf8.length); dos.write(cmdUtf8, 0, cmdUtf8.length); - dos.flush(); } // Read the status from the socket. diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java index 95eb2c69024e..6666cf42ab5d 100644 --- a/services/core/java/com/android/server/am/MemoryStatUtil.java +++ b/services/core/java/com/android/server/am/MemoryStatUtil.java @@ -126,9 +126,9 @@ public final class MemoryStatUtil { /** * Reads RSS high-water mark of a process from procfs. Returns value of the VmHWM field in - * /proc/PID/status in bytes or 0 if not available. + * /proc/PID/status in kilobytes or 0 if not available. */ - public static long readRssHighWaterMarkFromProcfs(int pid) { + public static int readRssHighWaterMarkFromProcfs(int pid) { final String statusPath = String.format(Locale.US, PROC_STATUS_FILE_FMT, pid); return parseVmHWMFromProcfs(readFileContents(statusPath)); } @@ -236,17 +236,15 @@ public final class MemoryStatUtil { } /** - * Parses RSS high watermark out from the contents of the /proc/pid/status file in procfs. The - * returned value is in bytes. + * Parses RSS high-water mark out from the contents of the /proc/pid/status file in procfs. The + * returned value is in kilobytes. */ @VisibleForTesting - static long parseVmHWMFromProcfs(String procStatusContents) { + static int parseVmHWMFromProcfs(String procStatusContents) { if (procStatusContents == null || procStatusContents.isEmpty()) { return 0; } - // Convert value read from /proc/pid/status from kilobytes to bytes. - return tryParseLong(RSS_HIGH_WATERMARK_IN_KILOBYTES, procStatusContents) - * BYTES_IN_KILOBYTE; + return (int) tryParseLong(RSS_HIGH_WATERMARK_IN_KILOBYTES, procStatusContents); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index e53cbc1b2f5f..7f69a683b18a 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -65,7 +65,6 @@ import android.content.pm.PermissionInfo; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION; -import android.media.AudioAttributes; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; @@ -361,7 +360,7 @@ public class AppOpsService extends IAppOpsService.Stub { public int startNesting; public ArrayMap<String, Ops> pkgOps; - public SparseIntArray opModes; + private SparseIntArray opModes; // true indicates there is an interested observer, false there isn't but it has such an op public SparseBooleanArray foregroundOps; @@ -383,6 +382,64 @@ public class AppOpsService extends IAppOpsService.Stub { && (pendingState == UID_STATE_CACHED)); } + public int getOpModeCount() { + return opModes != null ? opModes.size() : 0; + } + + public int getOpCodeAt(int index) { + return opModes.keyAt(index); + } + + public boolean hasOpMode(int code) { + return opModes != null && opModes.indexOfKey(code) >= 0; + } + + public int getOpMode(int code) { + return opModes.get(code); + } + + public boolean putOpMode(int code, int mode) { + if (mode == AppOpsManager.opToDefaultMode(code)) { + return removeOpMode(code); + } + if (opModes == null) { + opModes = new SparseIntArray(); + } + int index = opModes.indexOfKey(code); + if (index < 0) { + opModes.put(code, mode); + return true; + } + if (opModes.valueAt(index) == mode) { + return false; + } + opModes.setValueAt(index, mode); + return true; + } + + public boolean removeOpMode(int code) { + if (opModes == null) { + return false; + } + int index = opModes.indexOfKey(code); + if (index < 0) { + return false; + } + opModes.removeAt(index); + if (opModes.size() == 0) { + opModes = null; + } + return true; + } + + @Nullable + public SparseIntArray cloneOpModes() { + if (opModes == null) { + return null; + } + return opModes.clone(); + } + int evalMode(int op, int mode) { if (mode == AppOpsManager.MODE_FOREGROUND) { return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op) @@ -410,14 +467,13 @@ public class AppOpsService extends IAppOpsService.Stub { public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) { SparseBooleanArray which = null; hasForegroundWatchers = false; - if (opModes != null) { - for (int i = opModes.size() - 1; i >= 0; i--) { - if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) { - if (which == null) { - which = new SparseBooleanArray(); - } - evalForegroundWatchers(opModes.keyAt(i), watchers, which); + for (int i = getOpModeCount() - 1; i >= 0; i--) { + int code = getOpCodeAt(i); + if (getOpMode(code) == AppOpsManager.MODE_FOREGROUND) { + if (which == null) { + which = new SparseBooleanArray(); } + evalForegroundWatchers(code, watchers, which); } } if (pkgOps != null) { @@ -1056,24 +1112,28 @@ public class AppOpsService extends IAppOpsService.Stub { return resOps; } - private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) { - if (uidOps == null) { + @Nullable + private ArrayList<AppOpsManager.OpEntry> collectOps(@NonNull UidState uidState, + @Nullable int[] ops) { + int opModeCount = uidState.getOpModeCount(); + if (opModeCount == 0) { return null; } ArrayList<AppOpsManager.OpEntry> resOps = null; if (ops == null) { resOps = new ArrayList<>(); - for (int j=0; j<uidOps.size(); j++) { - resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j))); + for (int i = 0; i < opModeCount; i++) { + int code = uidState.getOpCodeAt(i); + resOps.add(new OpEntry(code, uidState.getOpMode(code))); } } else { - for (int j=0; j<ops.length; j++) { - int index = uidOps.indexOfKey(ops[j]); - if (index >= 0) { + for (int i = 0; i < ops.length; i++) { + int code = ops[i]; + if (uidState.hasOpMode(code)) { if (resOps == null) { resOps = new ArrayList<>(); } - resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j))); + resOps.add(new OpEntry(code, uidState.getOpMode(code))); } } } @@ -1219,11 +1279,11 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidState == null) { return null; } - ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops); + ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState, ops); if (resOps == null) { return null; } - ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); + ArrayList<AppOpsManager.PackageOps> res = new ArrayList<>(); AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( null, uidState.uid, resOps); res.add(resPackage); @@ -1291,29 +1351,14 @@ public class AppOpsService extends IAppOpsService.Stub { return; } uidState = new UidState(uid); - uidState.opModes = new SparseIntArray(); - uidState.opModes.put(code, mode); + uidState.putOpMode(code, mode); mUidStates.put(uid, uidState); scheduleWriteLocked(); - } else if (uidState.opModes == null) { - if (mode != defaultMode) { - uidState.opModes = new SparseIntArray(); - uidState.opModes.put(code, mode); - scheduleWriteLocked(); - } } else { - if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) { - return; - } - if (mode == defaultMode) { - uidState.opModes.delete(code); - if (uidState.opModes.size() <= 0) { - uidState.opModes = null; - } - } else { - uidState.opModes.put(code, mode); + boolean changed = uidState.putOpMode(code, mode); + if (changed) { + scheduleWriteLocked(); } - scheduleWriteLocked(); } uidState.evalForegroundOps(mOpModeWatchers); } @@ -1552,16 +1597,13 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i = mUidStates.size() - 1; i >= 0; i--) { UidState uidState = mUidStates.valueAt(i); - SparseIntArray opModes = uidState.opModes; - if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { - final int uidOpCount = opModes.size(); - for (int j = uidOpCount - 1; j >= 0; j--) { - final int code = opModes.keyAt(j); + if (uidState.uid == reqUid || reqUid == -1) { + for (int opModeIndex = uidState.getOpModeCount() - 1; opModeIndex >= 0; + opModeIndex--) { + final int code = uidState.getOpCodeAt(opModeIndex); + if (AppOpsManager.opAllowsReset(code)) { - opModes.removeAt(j); - if (opModes.size() <= 0) { - uidState.opModes = null; - } + uidState.removeOpMode(code); for (String packageName : getPackagesForUid(uidState.uid)) { callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, mOpModeWatchers.get(code)); @@ -1811,9 +1853,8 @@ public class AppOpsService extends IAppOpsService.Stub { } code = AppOpsManager.opToSwitch(code); UidState uidState = getUidStateLocked(uid, false); - if (uidState != null && uidState.opModes != null - && uidState.opModes.indexOfKey(code) >= 0) { - final int rawMode = uidState.opModes.get(code); + if (uidState != null && uidState.hasOpMode(code)) { + final int rawMode = uidState.getOpMode(code); return raw ? rawMode : uidState.evalMode(code, rawMode); } Op op = getOpLocked(code, uid, packageName, false, false); @@ -1982,8 +2023,8 @@ public class AppOpsService extends IAppOpsService.Stub { final int switchCode = AppOpsManager.opToSwitch(code); // If there is a non-default per UID policy (we set UID op mode only if // non-default) it takes over, otherwise use the per package policy. - if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { - final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); + if (uidState.hasOpMode(switchCode)) { + final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode)); if (uidMode != AppOpsManager.MODE_ALLOWED) { if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " + switchCode + " (" + code + ") uid " + uid + " package " @@ -2284,8 +2325,8 @@ public class AppOpsService extends IAppOpsService.Stub { // If there is a non-default per UID policy (we set UID op mode only if // non-default) it takes over, otherwise use the per package policy. final int opCode = op.op; - if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { - final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); + if (uidState.hasOpMode(switchCode)) { + final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode)); if (uidMode != AppOpsManager.MODE_ALLOWED && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) { if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " @@ -2604,9 +2645,8 @@ public class AppOpsService extends IAppOpsService.Stub { || !callback.isWatchingUid(uidState.uid)) { continue; } - boolean doAllPackages = uidState.opModes != null - && uidState.opModes.indexOfKey(code) >= 0 - && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND; + boolean doAllPackages = uidState.hasOpMode(code) + && uidState.getOpMode(code) == AppOpsManager.MODE_FOREGROUND; if (uidState.pkgOps != null) { for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) { final Op op = uidState.pkgOps.valueAt(pkgi).get(code); @@ -2927,12 +2967,9 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidState == null) { continue; } - if (uidState.opModes != null) { - final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND); - if (idx >= 0) { - uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, - uidState.opModes.valueAt(idx)); - } + if (uidState.hasOpMode(AppOpsManager.OP_RUN_IN_BACKGROUND)) { + uidState.putOpMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.getOpMode( + AppOpsManager.OP_RUN_IN_BACKGROUND)); } if (uidState.pkgOps == null) { continue; @@ -2988,10 +3025,7 @@ public class AppOpsService extends IAppOpsService.Stub { final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); UidState uidState = getUidStateLocked(uid, true); - if (uidState.opModes == null) { - uidState.opModes = new SparseIntArray(); - } - uidState.opModes.put(code, mode); + uidState.putOpMode(code, mode); } else { Slog.w(TAG, "Unknown element under <uid-ops>: " + parser.getName()); @@ -3143,47 +3177,38 @@ public class AppOpsService extends IAppOpsService.Stub { out.startTag(null, "app-ops"); out.attribute(null, "v", String.valueOf(CURRENT_VERSION)); - SparseArray<SparseIntArray> uidStatesClone; + final SparseArray<SparseIntArray> uidOpModes = new SparseArray<>(); synchronized (this) { - uidStatesClone = new SparseArray<>(mUidStates.size()); - - final int uidStateCount = mUidStates.size(); - for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { - UidState uidState = mUidStates.valueAt(uidStateNum); - int uid = mUidStates.keyAt(uidStateNum); - - SparseIntArray opModes = uidState.opModes; - if (opModes != null && opModes.size() > 0) { - uidStatesClone.put(uid, new SparseIntArray(opModes.size())); - - final int opCount = opModes.size(); - for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { - uidStatesClone.get(uid).put( - opModes.keyAt(opCountNum), - opModes.valueAt(opCountNum)); - } + final int uidStatesSize = mUidStates.size(); + for (int i = 0; i < uidStatesSize; i++) { + final SparseIntArray opModes = mUidStates.valueAt(i).cloneOpModes(); + if (opModes != null) { + final int uid = mUidStates.keyAt(i); + uidOpModes.put(uid, opModes); } } } - final int uidStateCount = uidStatesClone.size(); - for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { - SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum); - if (opModes != null && opModes.size() > 0) { - out.startTag(null, "uid"); - out.attribute(null, "n", - Integer.toString(uidStatesClone.keyAt(uidStateNum))); - final int opCount = opModes.size(); - for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { - final int op = opModes.keyAt(opCountNum); - final int mode = opModes.valueAt(opCountNum); - out.startTag(null, "op"); - out.attribute(null, "n", Integer.toString(op)); - out.attribute(null, "m", Integer.toString(mode)); - out.endTag(null, "op"); - } - out.endTag(null, "uid"); + final int uidOpModesSize = uidOpModes.size(); + for (int uidOpModesIndex = 0; uidOpModesIndex < uidOpModesSize; uidOpModesIndex++) { + final int uid = uidOpModes.keyAt(uidOpModesIndex); + final SparseIntArray opModes = uidOpModes.valueAt(uidOpModesIndex); + + out.startTag(null, "uid"); + out.attribute(null, "n", Integer.toString(uid)); + + final int opModesSize = opModes.size(); + for (int opModesIndex = 0; opModesIndex < opModesSize; opModesIndex++) { + final int code = opModes.keyAt(opModesIndex); + final int mode = opModes.valueAt(opModesIndex); + + out.startTag(null, "op"); + out.attribute(null, "n", Integer.toString(code)); + out.attribute(null, "m", Integer.toString(mode)); + out.endTag(null, "op"); } + + out.endTag(null, "uid"); } if (allOps != null) { @@ -4128,21 +4153,22 @@ public class AppOpsService extends IAppOpsService.Stub { } for (int i=0; i<mUidStates.size(); i++) { UidState uidState = mUidStates.valueAt(i); - final SparseIntArray opModes = uidState.opModes; final ArrayMap<String, Ops> pkgOps = uidState.pkgOps; if (dumpWatchers || dumpHistory) { continue; } if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) { - boolean hasOp = dumpOp < 0 || (uidState.opModes != null - && uidState.opModes.indexOfKey(dumpOp) >= 0); + boolean hasOp = dumpOp < 0 || uidState.hasOpMode(dumpOp); boolean hasPackage = dumpPackage == null; boolean hasMode = dumpMode < 0; - if (!hasMode && opModes != null) { - for (int opi = 0; !hasMode && opi < opModes.size(); opi++) { - if (opModes.valueAt(opi) == dumpMode) { + if (!hasMode) { + int opModeCount = uidState.getOpModeCount(); + for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) { + int code = uidState.getOpCodeAt(opModeIndex); + if (uidState.getOpMode(code) == dumpMode) { hasMode = true; + break; } } } @@ -4209,20 +4235,18 @@ public class AppOpsService extends IAppOpsService.Stub { } needSep = true; - if (opModes != null) { - final int opModeCount = opModes.size(); - for (int j = 0; j < opModeCount; j++) { - final int code = opModes.keyAt(j); - final int mode = opModes.valueAt(j); - if (dumpOp >= 0 && dumpOp != code) { - continue; - } - if (dumpMode >= 0 && dumpMode != mode) { - continue; - } - pw.print(" "); pw.print(AppOpsManager.opToName(code)); - pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); + final int opModeCount = uidState.getOpModeCount(); + for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) { + final int code = uidState.getOpCodeAt(opModeIndex); + final int mode = uidState.getOpMode(code); + if (dumpOp >= 0 && dumpOp != code) { + continue; + } + if (dumpMode >= 0 && dumpMode != mode) { + continue; } + pw.print(" "); pw.print(AppOpsManager.opToName(code)); + pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); } if (pkgOps == null) { diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index ace0a7d03b85..5983785d4247 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -28,6 +28,7 @@ import android.app.AppOpsManager.UidState; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; +import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Debug; @@ -36,6 +37,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteCallback; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.provider.Settings; import android.util.ArraySet; import android.util.LongSparseArray; @@ -44,6 +46,7 @@ import android.util.TimeUtils; import android.util.Xml; import com.android.internal.annotations.GuardedBy; +import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.os.AtomicDirectory; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; @@ -272,6 +275,10 @@ final class HistoricalRegistry { void dump(String prefix, PrintWriter pw, int filterUid, String filterPackage, int filterOp) { + if (!isApiEnabled()) { + return; + } + synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { pw.println(); @@ -324,6 +331,11 @@ final class HistoricalRegistry { void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback) { + if (!isApiEnabled()) { + callback.sendResult(new Bundle()); + return; + } + synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { if (!isPersistenceInitializedMLocked()) { @@ -344,6 +356,11 @@ final class HistoricalRegistry { void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback) { + if (!isApiEnabled()) { + callback.sendResult(new Bundle()); + return; + } + final long currentTimeMillis = System.currentTimeMillis(); if (endTimeMillis == Long.MAX_VALUE) { endTimeMillis = currentTimeMillis; @@ -681,6 +698,12 @@ final class HistoricalRegistry { } } + private static boolean isApiEnabled() { + return Binder.getCallingUid() == Process.myUid() + || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, + SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false); + } + private static final class Persistence { private static final boolean DEBUG = false; diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index faf01f981e3e..7b3eae14c97a 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -2082,7 +2082,6 @@ public class Vpn { } out.write(0xFF); out.write(0xFF); - out.flush(); // Wait for End-of-File. InputStream in = mSockets[i].getInputStream(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index f71b3627135d..3d9e635c6dfc 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5469,8 +5469,16 @@ public class NotificationManagerService extends SystemService { } synchronized (mNotificationLock) { - // Look for the notification, searching both the posted and enqueued lists. - NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId); + // If the notification is currently enqueued, repost this runnable so it has a + // chance to notify listeners + if ((findNotificationByListLocked(mEnqueuedNotifications, mPkg, mTag, mId, mUserId)) + != null) { + mHandler.post(this); + return; + } + // Look for the notification in the posted list, since we already checked enqueued. + NotificationRecord r = + findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId); if (r != null) { // The notification was found, check if it should be removed. diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 3f2cadeb527d..3482e92a6fbd 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -443,7 +443,8 @@ public class StagingManager { try { rm.notifyStagedApkSession(originalSession.sessionId, apkSession.sessionId); } catch (RemoteException re) { - // Cannot happen, the rollback manager is in the same process. + Slog.e(TAG, "Failed to notifyStagedApkSession for session: " + + originalSession.sessionId, re); } } @@ -856,7 +857,8 @@ public class StagingManager { + session.sessionId); } } catch (RemoteException re) { - // Cannot happen, the rollback manager is in the same process. + Slog.e(TAG, "Failed to notifyStagedSession for session: " + + session.sessionId, re); } } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 9948a3ad47da..b3f1867fdb06 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -277,9 +277,6 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { try { fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY); if (fd == null || !fd.getFileDescriptor().valid()) { - Slog.wtf(TAG, - "ParcelFileDescriptor.open returned an invalid descriptor for " - + packageName + ":" + snapshotProfile + ". isNull=" + (fd == null)); postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); } else { postSuccess(packageName, fd, callback); diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index c76bbb05a359..e176480f685d 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -1237,15 +1237,17 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { LocalServices.getService( ActivityManagerInternal.class).getMemoryStateForProcesses(); for (ProcessMemoryState managedProcess : managedProcessList) { - final long rssHighWaterMarkInBytes = + final int rssHighWaterMarkInKilobytes = readRssHighWaterMarkFromProcfs(managedProcess.pid); - if (rssHighWaterMarkInBytes == 0) { + if (rssHighWaterMarkInKilobytes == 0) { continue; } StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); e.writeInt(managedProcess.uid); e.writeString(managedProcess.processName); - e.writeLong(rssHighWaterMarkInBytes); + // RSS high-water mark in bytes. + e.writeLong((long) rssHighWaterMarkInKilobytes * 1024L); + e.writeInt(rssHighWaterMarkInKilobytes); pulledData.add(e); } int[] pids = getPidsForCommands(MEMORY_INTERESTING_NATIVE_PROCESSES); @@ -1253,11 +1255,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { final int pid = pids[i]; final int uid = getUidForPid(pid); final String processName = readCmdlineFromProcfs(pid); - final long rssHighWaterMarkInBytes = readRssHighWaterMarkFromProcfs(pid); + final int rssHighWaterMarkInKilobytes = readRssHighWaterMarkFromProcfs(pid); + if (rssHighWaterMarkInKilobytes == 0) { + continue; + } StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); e.writeInt(uid); e.writeString(processName); - e.writeLong(rssHighWaterMarkInBytes); + // RSS high-water mark in bytes. + e.writeLong((long) rssHighWaterMarkInKilobytes * 1024L); + e.writeInt(rssHighWaterMarkInKilobytes); pulledData.add(e); } // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 12cb94db0a8e..61bf2cea0b86 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1853,9 +1853,14 @@ final class ActivityRecord extends ConfigurationContainer { final ActivityRecord next = getDisplay().topRunningActivity( true /* considerKeyguardState */); final boolean isVisible = visible || nowVisible; + // isNextNotYetVisible is to check if the next activity is invisible, or it has been + // requested to be invisible but its windows haven't reported as invisible. If so, it + // implied that the current finishing activity should be added into stopping list rather + // than destroy immediately. + final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible); final ActivityStack stack = getActivityStack(); final boolean notFocusedStack = stack != mRootActivityContainer.getTopDisplayFocusedStack(); - if (isVisible && next != null && !next.nowVisible) { + if (isVisible && isNextNotYetVisible) { addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); if (DEBUG_STATES) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5ec167e495e0..5d42d18a97ac 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1056,9 +1056,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // removing from parent. token.getParent().removeChild(token); } - if (prevDc.mLastFocus == mCurrentFocus) { - // The window has become the focus of this display, so it should not be notified - // that it lost focus from the previous display. + if (token.hasChild(prevDc.mLastFocus)) { + // If the reparent window token contains previous display's last focus window, means + // it will end up to gain window focus on the target display, so it should not be + // notified that it lost focus from the previous display. prevDc.mLastFocus = null; } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index bef6a37a1ebe..239bd004705f 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1746,6 +1746,11 @@ public class TaskStack extends WindowContainer<Task> implements if (toBounds.width() == fromBounds.width() && toBounds.height() == fromBounds.height()) { intendedAnimationType = BoundsAnimationController.BOUNDS; + } else if (!fromFullscreen && !toBounds.equals(fromBounds)) { + // intendedAnimationType may have been reset at the end of RecentsAnimation, + // force it to BOUNDS type if we know for certain we're animating to + // a different bounds, especially for expand and collapse of PiP window. + intendedAnimationType = BoundsAnimationController.BOUNDS; } } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 7274d1765329..97b20472b12d 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -109,8 +109,6 @@ cc_defaults { "libGLESv2", "libnetutils", "libhidlbase", - "libhidltransport", - "libhwbinder", "libutils", "libhwui", "libbpf_android", diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java index 356423ad0590..73dcb98abc8c 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java @@ -111,6 +111,8 @@ public class AbstractAccessibilityServiceConnectionTest { private static final String VIEW_TEXT = "test_view_text"; private static final int WINDOWID = 12; private static final int PIP_WINDOWID = 13; + private static final int WINDOWID_ONSECONDDISPLAY = 14; + private static final int SECONDARY_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1; private static final int SERVICE_ID = 42; private static final int A11Y_SERVICE_CAPABILITY = CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT | CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION @@ -135,6 +137,7 @@ public class AbstractAccessibilityServiceConnectionTest { private AbstractAccessibilityServiceConnection mServiceConnection; private MessageCapturingHandler mHandler = new MessageCapturingHandler(null); private final List<AccessibilityWindowInfo> mA11yWindowInfos = new ArrayList<>(); + private final List<AccessibilityWindowInfo> mA11yWindowInfosOnSecondDisplay = new ArrayList<>(); private Callable[] mFindA11yNodesFunctions; private Callable<Boolean> mPerformA11yAction; @@ -177,14 +180,22 @@ public class AbstractAccessibilityServiceConnectionTest { when(mMockPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(true); // Fake a11yWindowInfo and remote a11y connection for tests. - addA11yWindowInfo(mA11yWindowInfos, WINDOWID, false); - addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true); + addA11yWindowInfo(mA11yWindowInfos, WINDOWID, false, Display.DEFAULT_DISPLAY); + addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true, Display.DEFAULT_DISPLAY); + addA11yWindowInfo(mA11yWindowInfosOnSecondDisplay, WINDOWID_ONSECONDDISPLAY, false, + SECONDARY_DISPLAY_ID); when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY)) .thenReturn(mA11yWindowInfos); when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID)) .thenReturn(mA11yWindowInfos.get(0)); when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(PIP_WINDOWID)) .thenReturn(mA11yWindowInfos.get(1)); + when(mMockA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(USER_ID, + WINDOWID_ONSECONDDISPLAY)).thenReturn(SECONDARY_DISPLAY_ID); + when(mMockA11yWindowManager.getWindowListLocked(SECONDARY_DISPLAY_ID)) + .thenReturn(mA11yWindowInfosOnSecondDisplay); + when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID_ONSECONDDISPLAY)) + .thenReturn(mA11yWindowInfosOnSecondDisplay.get(0)); final RemoteAccessibilityConnection conn = getRemoteA11yConnection( WINDOWID, mMockIA11yInteractionConnection, PACKAGE_NAME1); final RemoteAccessibilityConnection connPip = getRemoteA11yConnection( @@ -327,6 +338,12 @@ public class AbstractAccessibilityServiceConnectionTest { } @Test + public void getWindow_onNonDefaultDisplay() { + assertThat(mServiceConnection.getWindow(WINDOWID_ONSECONDDISPLAY), + is(mA11yWindowInfosOnSecondDisplay.get(0))); + } + + @Test public void accessAccessibilityNodeInfo_whenCantGetInfo_returnNullOrFalse() throws Exception { when(mMockSecurityPolicy.canGetAccessibilityNodeInfoLocked( @@ -674,9 +691,10 @@ public class AbstractAccessibilityServiceConnectionTest { } private AccessibilityWindowInfo addA11yWindowInfo(List<AccessibilityWindowInfo> infos, - int windowId, boolean isPip) { + int windowId, boolean isPip, int displayId) { final AccessibilityWindowInfo info = AccessibilityWindowInfo.obtain(); info.setId(windowId); + info.setDisplayId(displayId); info.setPictureInPicture(isPip); infos.add(info); return info; diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java index 6678a7833f9a..5ab44a8c2c3b 100644 --- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java +++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java @@ -302,7 +302,7 @@ public class MemoryStatUtilTest { @Test public void testParseVmHWMFromProcfs_parsesCorrectValue() { - assertEquals(137668, parseVmHWMFromProcfs(PROC_STATUS_CONTENTS) / BYTES_IN_KILOBYTE); + assertEquals(137668, parseVmHWMFromProcfs(PROC_STATUS_CONTENTS)); } @Test diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java index 66d2baba2909..70650de2a4b7 100644 --- a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java +++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java @@ -89,13 +89,11 @@ public class AppOpsUpgradeTest { final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2); for(int i = 0; i < uidStates.size(); i++) { final AppOpsService.UidState uidState = uidStates.valueAt(i); - if (uidState.opModes != null) { - final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1); - final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2); - assertEquals(uidMode1, uidMode2); - if (uidMode1 != defaultModeOp1) { - numberOfNonDefaultOps++; - } + final int uidMode1 = uidState.hasOpMode(op1) ? uidState.getOpMode(op1) : defaultModeOp1; + final int uidMode2 = uidState.hasOpMode(op2) ? uidState.getOpMode(op2) : defaultModeOp2; + assertEquals(uidMode1, uidMode2); + if (uidMode1 != defaultModeOp1) { + numberOfNonDefaultOps++; } if (uidState.pkgOps == null) { continue; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index d11995a82229..fdd1a59e0d41 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -1064,6 +1064,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag() + throws Exception { + final StatusBarNotification sbn = generateNotificationRecord(null).sbn; + sbn.getNotification().flags = + Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); + waitForIdle(); + verify(mListeners, times(1)).notifyPostedLocked(any(), any()); + verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any()); + } + + @Test public void testUserInitiatedClearAll_noLeak() throws Exception { final NotificationRecord n = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 7b064908565c..8444ab2ebeb8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1060,6 +1060,7 @@ public class ActivityRecordTests extends ActivityTestsBase { // simulates finishing in non-focused stack in split-screen. final ActivityStack stack = new StackBuilder(mRootActivityContainer).build(); stack.getChildAt(0).getChildAt(0).nowVisible = true; + stack.getChildAt(0).getChildAt(0).visible = true; topActivity.completeFinishing("test"); diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp index a4906d7b4cd3..13b7b5ca01c8 100644 --- a/startop/apps/test/Android.bp +++ b/startop/apps/test/Android.bp @@ -21,6 +21,7 @@ android_app { "src/LayoutInflationActivity.java", "src/ComplexLayoutInflationActivity.java", "src/FrameLayoutInflationActivity.java", + "src/SystemServerBenchmarkActivity.java", "src/TextViewInflationActivity.java", ], platform_apis: true, diff --git a/startop/apps/test/AndroidManifest.xml b/startop/apps/test/AndroidManifest.xml index 467d8f72e468..15785d4d44b9 100644 --- a/startop/apps/test/AndroidManifest.xml +++ b/startop/apps/test/AndroidManifest.xml @@ -71,6 +71,19 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + + <activity + android:label="SystemServer Benchmark" + android:name=".SystemServerBenchmarkActivity" + android:exported="true" > + + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/startop/apps/test/res/layout/system_server_benchmark_page.xml b/startop/apps/test/res/layout/system_server_benchmark_page.xml new file mode 100644 index 000000000000..337fe65ff9e2 --- /dev/null +++ b/startop/apps/test/res/layout/system_server_benchmark_page.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <GridLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:columnCount="3" + android:id="@+id/benchmark_list"> + + <TextView android:text="Benchmark"/> + <TextView android:text="Mean (ms)"/> + <TextView android:text="Stdev (ms)"/> + + </GridLayout> +</ScrollView> diff --git a/startop/apps/test/src/SystemServerBenchmarkActivity.java b/startop/apps/test/src/SystemServerBenchmarkActivity.java new file mode 100644 index 000000000000..61d43226c41e --- /dev/null +++ b/startop/apps/test/src/SystemServerBenchmarkActivity.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.startop.test; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Trace; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridLayout; +import android.widget.TextView; + +import java.util.Arrays; + +class Benchmark { + // Time limit to run benchmarks in seconds + public static final int TIME_LIMIT = 5; + + public Benchmark(ViewGroup parent, CharSequence name, Runnable thunk) { + Context context = parent.getContext(); + Button button = new Button(context); + TextView mean = new TextView(context); + TextView stdev = new TextView(context); + + button.setText(name); + mean.setText(""); + stdev.setText(""); + + button.setOnClickListener((_button) -> { + mean.setText("Running..."); + stdev.setText(""); + + new AsyncTask() { + double resultMean = 0; + double resultStdev = 0; + + @Override + protected Object doInBackground(Object... _args) { + long startTime = System.nanoTime(); + int count = 0; + + // Run benchmark + while (true) { + long elapsed = -System.nanoTime(); + thunk.run(); + elapsed += System.nanoTime(); + + count++; + double elapsedVariance = (double) elapsed - resultMean; + resultMean += elapsedVariance / count; + resultStdev += elapsedVariance * ((double) elapsed - resultMean); + + if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) { + break; + } + } + resultStdev = Math.sqrt(resultStdev / (count - 1)); + + return null; + } + + @Override + protected void onPostExecute(Object _result) { + mean.setText(String.format("%.3f", resultMean / 1e6)); + stdev.setText(String.format("%.3f", resultStdev / 1e6)); + } + }.execute(new Object()); + }); + + parent.addView(button); + parent.addView(mean); + parent.addView(stdev); + } +} + +public class SystemServerBenchmarkActivity extends Activity { + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.system_server_benchmark_page); + + GridLayout benchmarkList = findViewById(R.id.benchmark_list); + + new Benchmark(benchmarkList, "Empty", () -> { + }); + + PackageManager pm = getPackageManager(); + new Benchmark(benchmarkList, "getInstalledApplications", () -> { + pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY); + }); + + new Benchmark(benchmarkList, "getInstalledPackages", () -> { + pm.getInstalledPackages(PackageManager.GET_ACTIVITIES); + }); + + new Benchmark(benchmarkList, "getPackageInfo", () -> { + try { + pm.getPackageInfo("com.android.startop.test", 0); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + }); + + new Benchmark(benchmarkList, "getApplicationInfo", () -> { + try { + pm.getApplicationInfo("com.android.startop.test", 0); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + }); + + try { + ApplicationInfo app = pm.getApplicationInfo("com.android.startop.test", 0); + new Benchmark(benchmarkList, "getResourcesForApplication", () -> { + try { + pm.getResourcesForApplication(app); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + }); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + + ComponentName component = new ComponentName(this, this.getClass()); + new Benchmark(benchmarkList, "getActivityInfo", () -> { + try { + pm.getActivityInfo(component, PackageManager.GET_META_DATA); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + }); + + } +} diff --git a/startop/scripts/iorap/compiler_ri.py b/startop/scripts/iorap/compiler_ri.py index 17b58c19ef28..90fc8a8123c5 100755 --- a/startop/scripts/iorap/compiler_ri.py +++ b/startop/scripts/iorap/compiler_ri.py @@ -139,7 +139,9 @@ def build_protobuf(page_runs, inode2filename, filters=[]): continue file_id = file_id_map.get(filename) - if not file_id: + # file_id could 0, which satisfies "if file_id" and causes duplicate + # filename for file id 0. + if file_id is None: file_id = file_id_counter file_id_map[filename] = file_id_counter file_id_counter = file_id_counter + 1 diff --git a/tests/net/Android.bp b/tests/net/Android.bp index 502aa97bfc68..e91abb6c4a44 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -20,8 +20,6 @@ java_defaults { "libdl_android", "libhidl-gen-utils", "libhidlbase", - "libhidltransport", - "libhwbinder", "libjsoncpp", "liblog", "liblzma", |