diff options
395 files changed, 5373 insertions, 8183 deletions
diff --git a/Android.bp b/Android.bp index 685c69df6823..acf86a0cfa2d 100644 --- a/Android.bp +++ b/Android.bp @@ -67,6 +67,7 @@ filegroup { name: "framework-non-updatable-sources", srcs: [ // Java/AIDL sources under frameworks/base + ":framework-annotations", ":framework-blobstore-sources", ":framework-core-sources", ":framework-drm-sources", @@ -388,47 +389,6 @@ platform_compat_config { } filegroup { - name: "framework-annotations", - srcs: [ - "core/java/android/annotation/AnyThread.java", - "core/java/android/annotation/AppIdInt.java", - "core/java/android/annotation/BytesLong.java", - "core/java/android/annotation/CallbackExecutor.java", - "core/java/android/annotation/CallSuper.java", - "core/java/android/annotation/CheckResult.java", - "core/java/android/annotation/CurrentTimeMillisLong.java", - "core/java/android/annotation/CurrentTimeSecondsLong.java", - "core/java/android/annotation/DrawableRes.java", - "core/java/android/annotation/DurationMillisLong.java", - "core/java/android/annotation/Hide.java", - "core/java/android/annotation/IntDef.java", - "core/java/android/annotation/IntRange.java", - "core/java/android/annotation/LongDef.java", - "core/java/android/annotation/MainThread.java", - "core/java/android/annotation/NonNull.java", - "core/java/android/annotation/Nullable.java", - "core/java/android/annotation/RequiresNoPermission.java", - "core/java/android/annotation/RequiresPermission.java", - "core/java/android/annotation/SdkConstant.java", - "core/java/android/annotation/StringDef.java", - "core/java/android/annotation/SystemApi.java", - "core/java/android/annotation/SystemService.java", - "core/java/android/annotation/TestApi.java", - "core/java/android/annotation/UserIdInt.java", - "core/java/android/annotation/WorkerThread.java", - "core/java/com/android/internal/annotations/GuardedBy.java", - "core/java/com/android/internal/annotations/Immutable.java", - "core/java/com/android/internal/annotations/VisibleForTesting.java", - ], -} - -java_library { - name: "framework-annotations-lib", - srcs: [":framework-annotations"], - sdk_version: "core_current", -} - -filegroup { name: "framework-ike-shared-srcs", visibility: ["//packages/modules/IPsec"], srcs: [ diff --git a/core/api/current.txt b/core/api/current.txt index 7ed8b6c17574..989ca3427453 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -586,7 +586,6 @@ package android { field public static final int dropDownWidth = 16843362; // 0x1010262 field public static final int duplicateParentState = 16842985; // 0x10100e9 field public static final int duration = 16843160; // 0x1010198 - field public static final int edgeEffectType; field public static final int editTextBackground = 16843602; // 0x1010352 field public static final int editTextColor = 16843601; // 0x1010351 field public static final int editTextPreferenceStyle = 16842898; // 0x1010092 @@ -11921,6 +11920,7 @@ package android.content.pm { method public int getGwpAsanMode(); method public int getMemtagMode(); method public int getNativeHeapZeroInitialized(); + method public int getRequestRawExternalStorageAccess(); method public boolean isProfileable(); method public boolean isProfileableByShell(); method public boolean isResourceOverlay(); @@ -11976,6 +11976,9 @@ package android.content.pm { field public static final int MEMTAG_DEFAULT = -1; // 0xffffffff field public static final int MEMTAG_OFF = 0; // 0x0 field public static final int MEMTAG_SYNC = 2; // 0x2 + field public static final int RAW_EXTERNAL_STORAGE_ACCESS_DEFAULT = 0; // 0x0 + field public static final int RAW_EXTERNAL_STORAGE_ACCESS_NOT_REQUESTED = 2; // 0x2 + field public static final int RAW_EXTERNAL_STORAGE_ACCESS_REQUESTED = 1; // 0x1 field public static final int ZEROINIT_DEFAULT = -1; // 0xffffffff field public static final int ZEROINIT_DISABLED = 0; // 0x0 field public static final int ZEROINIT_ENABLED = 1; // 0x1 @@ -53791,7 +53794,6 @@ package android.widget { method public int getCheckedItemPosition(); method public android.util.SparseBooleanArray getCheckedItemPositions(); method public int getChoiceMode(); - method public int getEdgeEffectType(); method public int getListPaddingBottom(); method public int getListPaddingLeft(); method public int getListPaddingRight(); @@ -53833,7 +53835,6 @@ package android.widget { method public void setChoiceMode(int); method public void setDrawSelectorOnTop(boolean); method public void setEdgeEffectColor(@ColorInt int); - method public void setEdgeEffectType(int); method public void setFastScrollAlwaysVisible(boolean); method public void setFastScrollEnabled(boolean); method public void setFastScrollStyle(int); @@ -54524,7 +54525,6 @@ package android.widget { method @ColorInt public int getColor(); method public float getDistance(); method public int getMaxHeight(); - method public int getType(); method public boolean isFinished(); method public void onAbsorb(int); method public void onPull(float); @@ -54534,10 +54534,7 @@ package android.widget { method public void setBlendMode(@Nullable android.graphics.BlendMode); method public void setColor(@ColorInt int); method public void setSize(int, int); - method public void setType(int); field public static final android.graphics.BlendMode DEFAULT_BLEND_MODE; - field public static final int TYPE_GLOW = 0; // 0x0 - field public static final int TYPE_STRETCH = 1; // 0x1 } public class EditText extends android.widget.TextView { @@ -54842,7 +54839,6 @@ package android.widget { method public boolean executeKeyEvent(android.view.KeyEvent); method public void fling(int); method public boolean fullScroll(int); - method public int getEdgeEffectType(); method @ColorInt public int getLeftEdgeEffectColor(); method public int getMaxScrollAmount(); method @ColorInt public int getRightEdgeEffectColor(); @@ -54850,7 +54846,6 @@ package android.widget { method public boolean isSmoothScrollingEnabled(); method public boolean pageScroll(int); method public void setEdgeEffectColor(@ColorInt int); - method public void setEdgeEffectType(int); method public void setFillViewport(boolean); method public void setLeftEdgeEffectColor(@ColorInt int); method public void setRightEdgeEffectColor(@ColorInt int); @@ -55736,7 +55731,6 @@ package android.widget { method public void fling(int); method public boolean fullScroll(int); method @ColorInt public int getBottomEdgeEffectColor(); - method public int getEdgeEffectType(); method public int getMaxScrollAmount(); method @ColorInt public int getTopEdgeEffectColor(); method public boolean isFillViewport(); @@ -55745,7 +55739,6 @@ package android.widget { method public void scrollToDescendant(@NonNull android.view.View); method public void setBottomEdgeEffectColor(@ColorInt int); method public void setEdgeEffectColor(@ColorInt int); - method public void setEdgeEffectType(int); method public void setFillViewport(boolean); method public void setSmoothScrollingEnabled(boolean); method public void setTopEdgeEffectColor(@ColorInt int); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index c7960dd406ed..990f43de5ec5 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -2520,7 +2520,6 @@ package android.content.om { package android.content.pm { public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { - method @Nullable public Boolean hasRequestRawExternalStorageAccess(); method public boolean isEncryptionAware(); method public boolean isInstantApp(); method public boolean isOem(); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 35767b3acb8c..1330234f6521 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1810,6 +1810,7 @@ package android.os { public class VintfObject { method public static String[] getHalNamesAndVersions(); + method @NonNull public static String getPlatformSepolicyVersion(); method public static String getSepolicyVersion(); method public static Long getTargetFrameworkCompatibilityMatrixVersion(); method public static java.util.Map<java.lang.String,java.lang.String[]> getVndkSnapshots(); diff --git a/core/java/Android.bp b/core/java/Android.bp index c8a8d36a1b20..793d0ef164fa 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -46,44 +46,6 @@ filegroup { "android/accounts/AccountsException.java", "android/accounts/AuthenticatorException.java", "android/accounts/OperationCanceledException.java", - "android/annotation/AnimatorRes.java", - "android/annotation/AnimRes.java", - "android/annotation/AnyRes.java", - "android/annotation/ArrayRes.java", - "android/annotation/AttrRes.java", - "android/annotation/BoolRes.java", - "android/annotation/BroadcastBehavior.java", - "android/annotation/CallbackExecutor.java", - "android/annotation/CallSuper.java", - "android/annotation/CheckResult.java", - "android/annotation/ColorInt.java", - "android/annotation/ColorRes.java", - "android/annotation/DimenRes.java", - "android/annotation/DrawableRes.java", - "android/annotation/FontRes.java", - "android/annotation/FractionRes.java", - "android/annotation/IntDef.java", - "android/annotation/IntegerRes.java", - "android/annotation/IntRange.java", - "android/annotation/LayoutRes.java", - "android/annotation/NonNull.java", - "android/annotation/Nullable.java", - "android/annotation/PluralsRes.java", - "android/annotation/RawRes.java", - "android/annotation/RequiresNoPermission.java", - "android/annotation/RequiresPermission.java", - "android/annotation/SdkConstant.java", - "android/annotation/Size.java", - "android/annotation/StringDef.java", - "android/annotation/StringRes.java", - "android/annotation/StyleableRes.java", - "android/annotation/StyleRes.java", - "android/annotation/SuppressLint.java", - "android/annotation/SystemApi.java", - "android/annotation/SystemService.java", - "android/annotation/TestApi.java", - "android/annotation/UserIdInt.java", - "android/annotation/XmlRes.java", "android/app/Application.java", "android/app/IApplicationThread.aidl", "android/app/IServiceConnection.aidl", @@ -124,7 +86,6 @@ filegroup { "android/util/AndroidException.java", "android/view/DisplayAdjustments.java", "android/view/ViewDebug.java", - "com/android/internal/annotations/VisibleForTesting.java", ], visibility: ["//frameworks/base/test-mock"], } diff --git a/core/java/android/annotation/AnimRes.java b/core/java/android/annotation/AnimRes.java deleted file mode 100644 index 56f8acf82313..000000000000 --- a/core/java/android/annotation/AnimRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an anim resource reference (e.g. {@link android.R.anim#fade_in}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface AnimRes { -} diff --git a/core/java/android/annotation/AnimatorRes.java b/core/java/android/annotation/AnimatorRes.java deleted file mode 100644 index cd4c189b7531..000000000000 --- a/core/java/android/annotation/AnimatorRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an animator resource reference (e.g. {@link android.R.animator#fade_in}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface AnimatorRes { -} diff --git a/core/java/android/annotation/AnyRes.java b/core/java/android/annotation/AnyRes.java deleted file mode 100644 index 44411a04a8e7..000000000000 --- a/core/java/android/annotation/AnyRes.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a resource reference of any type. If the specific type is known, use - * one of the more specific annotations instead, such as {@link StringRes} or - * {@link DrawableRes}. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface AnyRes { -} diff --git a/core/java/android/annotation/AnyThread.java b/core/java/android/annotation/AnyThread.java deleted file mode 100644 index ee36a42b3fc6..000000000000 --- a/core/java/android/annotation/AnyThread.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated method can be called from any thread (e.g. it is - * "thread safe".) If the annotated element is a class, then all methods in the - * class can be called from any thread. - * <p> - * The main purpose of this method is to indicate that you believe a method can - * be called from any thread; static tools can then check that nothing you call - * from within this method or class have more strict threading requirements. - * <p> - * Example: - * - * <pre> - * <code> - * @AnyThread - * public void deliverResult(D data) { ... } - * </code> - * </pre> - * - * @memberDoc This method is safe to call from any thread. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface AnyThread { -} diff --git a/core/java/android/annotation/AppIdInt.java b/core/java/android/annotation/AppIdInt.java deleted file mode 100644 index 29838dd5bd7c..000000000000 --- a/core/java/android/annotation/AppIdInt.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated element is a multi-user application ID. This is - * <em>not</em> the same as a UID. - * - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface AppIdInt { -} diff --git a/core/java/android/annotation/ArrayRes.java b/core/java/android/annotation/ArrayRes.java deleted file mode 100644 index 1407af1d1422..000000000000 --- a/core/java/android/annotation/ArrayRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an array resource reference (e.g. {@link android.R.array#phoneTypes}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface ArrayRes { -} diff --git a/core/java/android/annotation/AttrRes.java b/core/java/android/annotation/AttrRes.java deleted file mode 100644 index 285b80ce45ca..000000000000 --- a/core/java/android/annotation/AttrRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an attribute reference (e.g. {@link android.R.attr#action}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface AttrRes { -} diff --git a/core/java/android/annotation/BinderThread.java b/core/java/android/annotation/BinderThread.java deleted file mode 100644 index ca5e14c2adb9..000000000000 --- a/core/java/android/annotation/BinderThread.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated method should only be called on the binder thread. - * If the annotated element is a class, then all methods in the class should be called - * on the binder thread. - * <p> - * Example: - * <pre><code> - * @BinderThread - * public BeamShareData createBeamShareData() { ... } - * </code></pre> - * - * {@hide} - */ -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface BinderThread { -}
\ No newline at end of file diff --git a/core/java/android/annotation/BoolRes.java b/core/java/android/annotation/BoolRes.java deleted file mode 100644 index f50785b1e1cf..000000000000 --- a/core/java/android/annotation/BoolRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a boolean resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface BoolRes { -} diff --git a/core/java/android/annotation/BroadcastBehavior.java b/core/java/android/annotation/BroadcastBehavior.java deleted file mode 100644 index 70d82cb5151b..000000000000 --- a/core/java/android/annotation/BroadcastBehavior.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import android.content.Intent; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Description of how the annotated broadcast action behaves. - * - * @hide - */ -@Target({ ElementType.FIELD }) -@Retention(RetentionPolicy.SOURCE) -public @interface BroadcastBehavior { - /** - * This broadcast will only be delivered to an explicit target. - * - * @see Intent#setPackage(String) - * @see Intent#setComponent(android.content.ComponentName) - */ - boolean explicitOnly() default false; - - /** - * This broadcast will only be delivered to registered receivers. - * - * @see Intent#FLAG_RECEIVER_REGISTERED_ONLY - */ - boolean registeredOnly() default false; - - /** - * This broadcast will include all {@code AndroidManifest.xml} receivers - * regardless of process state. - * - * @see Intent#FLAG_RECEIVER_INCLUDE_BACKGROUND - */ - boolean includeBackground() default false; - - /** - * This broadcast is protected and can only be sent by the OS. - */ - boolean protectedBroadcast() default false; -} diff --git a/core/java/android/annotation/BytesLong.java b/core/java/android/annotation/BytesLong.java deleted file mode 100644 index f5e1a9c5f7fd..000000000000 --- a/core/java/android/annotation/BytesLong.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative number of bytes. - * @paramDoc Value is a non-negative number of bytes. - * @returnDoc Value is a non-negative number of bytes. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface BytesLong { -} diff --git a/core/java/android/annotation/CallSuper.java b/core/java/android/annotation/CallSuper.java deleted file mode 100644 index c16b51161cac..000000000000 --- a/core/java/android/annotation/CallSuper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that any overriding methods should invoke this method as well. - * <p> - * Example: - * - * <pre> - * <code> - * @CallSuper - * public abstract void onFocusLost(); - * </code> - * </pre> - * - * @memberDoc If you override this method you <em>must</em> call through to the - * superclass implementation. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD}) -public @interface CallSuper { -} diff --git a/core/java/android/annotation/CallbackExecutor.java b/core/java/android/annotation/CallbackExecutor.java deleted file mode 100644 index 4258f730eb16..000000000000 --- a/core/java/android/annotation/CallbackExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.concurrent.Executor; - -/** - * @paramDoc Callback and listener events are dispatched through this - * {@link Executor}, providing an easy way to control which thread is - * used. To dispatch events through the main thread of your - * application, you can use - * {@link android.content.Context#getMainExecutor() Context.getMainExecutor()}. - * To dispatch events through a shared thread pool, you can use - * {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR AsyncTask#THREAD_POOL_EXECUTOR}. - * @hide - */ -@Retention(SOURCE) -@Target(PARAMETER) -public @interface CallbackExecutor { -} diff --git a/core/java/android/annotation/CheckResult.java b/core/java/android/annotation/CheckResult.java deleted file mode 100644 index 97d031a760a6..000000000000 --- a/core/java/android/annotation/CheckResult.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated method returns a result that it typically is - * an error to ignore. This is usually used for methods that have no side effect, - * so calling it without actually looking at the result usually means the developer - * has misunderstood what the method does. - * <p> - * Example: - * <pre>{@code - * public @CheckResult String trim(String s) { return s.trim(); } - * ... - * s.trim(); // this is probably an error - * s = s.trim(); // ok - * }</pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({METHOD}) -public @interface CheckResult { - /** Defines the name of the suggested method to use instead, if applicable (using - * the same signature format as javadoc.) If there is more than one possibility, - * list them all separated by commas. - * <p> - * For example, ProcessBuilder has a method named {@code redirectErrorStream()} - * which sounds like it might redirect the error stream. It does not. It's just - * a getter which returns whether the process builder will redirect the error stream, - * and to actually set it, you must call {@code redirectErrorStream(boolean)}. - * In that case, the method should be defined like this: - * <pre> - * @CheckResult(suggest="#redirectErrorStream(boolean)") - * public boolean redirectErrorStream() { ... } - * </pre> - */ - String suggest() default ""; -}
\ No newline at end of file diff --git a/core/java/android/annotation/ColorInt.java b/core/java/android/annotation/ColorInt.java deleted file mode 100644 index 4671b1b9f887..000000000000 --- a/core/java/android/annotation/ColorInt.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element represents a packed color - * int, {@code AARRGGBB}. If applied to an int array, every element - * in the array represents a color integer. - * <p> - * Example: - * <pre>{@code - * public abstract void setTextColor(@ColorInt int color); - * }</pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({PARAMETER,METHOD,LOCAL_VARIABLE,FIELD}) -public @interface ColorInt { -}
\ No newline at end of file diff --git a/core/java/android/annotation/ColorLong.java b/core/java/android/annotation/ColorLong.java deleted file mode 100644 index 9b19c76802c9..000000000000 --- a/core/java/android/annotation/ColorLong.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * <p>Denotes that the annotated element represents a packed color - * long. If applied to a long array, every element in the array - * represents a color long. For more information on how colors - * are packed in a long, please refer to the documentation of - * the {@link android.graphics.Color} class.</p> - * - * <p>Example:</p> - * - * <pre>{@code - * public void setFillColor(@ColorLong long color); - * }</pre> - * - * @see android.graphics.Color - * - * @hide - */ -@Retention(SOURCE) -@Target({PARAMETER,METHOD,LOCAL_VARIABLE,FIELD}) -public @interface ColorLong { -} diff --git a/core/java/android/annotation/ColorRes.java b/core/java/android/annotation/ColorRes.java deleted file mode 100644 index 061faa05c738..000000000000 --- a/core/java/android/annotation/ColorRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a color resource reference (e.g. {@link android.R.color#black}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface ColorRes { -} diff --git a/core/java/android/annotation/Condemned.java b/core/java/android/annotation/Condemned.java deleted file mode 100644 index 186409b3e204..000000000000 --- a/core/java/android/annotation/Condemned.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * A program element annotated @Condemned is one that programmers are - * blocked from using, typically because it's about to be completely destroyed. - * <p> - * This is a stronger version of @Deprecated, and it's typically used to - * mark APIs that only existed temporarily in a preview SDK, and which only - * continue to exist temporarily to support binary compatibility. - * - * @hide - */ -@Retention(SOURCE) -@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) -public @interface Condemned { -} diff --git a/core/java/android/annotation/CurrentTimeMillisLong.java b/core/java/android/annotation/CurrentTimeMillisLong.java deleted file mode 100644 index 355bb5a2f960..000000000000 --- a/core/java/android/annotation/CurrentTimeMillisLong.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative timestamp measured as the number of - * milliseconds since 1970-01-01T00:00:00Z. - * @paramDoc Value is a non-negative timestamp measured as the number of - * milliseconds since 1970-01-01T00:00:00Z. - * @returnDoc Value is a non-negative timestamp measured as the number of - * milliseconds since 1970-01-01T00:00:00Z. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface CurrentTimeMillisLong { -} diff --git a/core/java/android/annotation/CurrentTimeSecondsLong.java b/core/java/android/annotation/CurrentTimeSecondsLong.java deleted file mode 100644 index 2b4ffd77ad34..000000000000 --- a/core/java/android/annotation/CurrentTimeSecondsLong.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative timestamp measured as the number of - * seconds since 1970-01-01T00:00:00Z. - * @paramDoc Value is a non-negative timestamp measured as the number of - * seconds since 1970-01-01T00:00:00Z. - * @returnDoc Value is a non-negative timestamp measured as the number of - * seconds since 1970-01-01T00:00:00Z. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface CurrentTimeSecondsLong { -} diff --git a/core/java/android/annotation/DimenRes.java b/core/java/android/annotation/DimenRes.java deleted file mode 100644 index 02ae00c6868c..000000000000 --- a/core/java/android/annotation/DimenRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a dimension resource reference (e.g. {@link android.R.dimen#app_icon_size}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface DimenRes { -} diff --git a/core/java/android/annotation/Dimension.java b/core/java/android/annotation/Dimension.java deleted file mode 100644 index 5f705ad52d9b..000000000000 --- a/core/java/android/annotation/Dimension.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that a numeric parameter, field or method return value is expected - * to represent a dimension. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE}) -public @interface Dimension { - @Unit - int unit() default PX; - - int DP = 0; - int PX = 1; - int SP = 2; - - @IntDef({PX, DP, SP}) - @Retention(SOURCE) - @interface Unit {} -} diff --git a/core/java/android/annotation/DisplayContext.java b/core/java/android/annotation/DisplayContext.java deleted file mode 100644 index e6b464ac237a..000000000000 --- a/core/java/android/annotation/DisplayContext.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.app.Activity; -import android.app.WallpaperManager; -import android.content.Context; -import android.os.Bundle; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.WindowManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes a {@link Context} that is tied to a {@link Display} and can be used to obtain one - * via {@link Context#getDisplay}, but <b>may not</b> be able to obtain {@link WindowManager}, - * {@link LayoutInflater} or {@link WallpaperManager} via {@link Context#getSystemService(String)}. - * If the UI services mentioned above are required, please use contexts which are marked as - * {@link UiContext}. - * <p> - * {@link Activity}, and the result of {@link Context#createWindowContext(int, Bundle)} or - * {@link Context#createDisplayContext(Display)} can be - * used where a {@link DisplayContext} is required. - * <p> - * This is a marker annotation and has no specific attributes. - * - * @see Context#getDisplay() - * @see Context#getSystemService(String) - * @see Context#getSystemService(Class) - * @see Context#createDisplayContext(Display) - * @see Context#createWindowContext(int, Bundle) - * @see UiContext - * @hide - */ -@Retention(SOURCE) -@Target({TYPE, METHOD, PARAMETER, FIELD}) -public @interface DisplayContext { -} diff --git a/core/java/android/annotation/DrawableRes.java b/core/java/android/annotation/DrawableRes.java deleted file mode 100644 index ebefa1d78ab1..000000000000 --- a/core/java/android/annotation/DrawableRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a drawable resource reference (e.g. {@link android.R.attr#alertDialogIcon}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface DrawableRes { -} diff --git a/core/java/android/annotation/DurationMillisLong.java b/core/java/android/annotation/DurationMillisLong.java deleted file mode 100644 index ce77532a6c6e..000000000000 --- a/core/java/android/annotation/DurationMillisLong.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative duration in milliseconds. - * @paramDoc Value is a non-negative duration in milliseconds. - * @returnDoc Value is a non-negative duration in milliseconds. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface DurationMillisLong { -} diff --git a/core/java/android/annotation/ElapsedRealtimeLong.java b/core/java/android/annotation/ElapsedRealtimeLong.java deleted file mode 100644 index f77ff72062a6..000000000000 --- a/core/java/android/annotation/ElapsedRealtimeLong.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.os.SystemClock; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative timestamp in the - * {@link SystemClock#elapsedRealtime()} time base. - * @paramDoc Value is a non-negative timestamp in the - * {@link SystemClock#elapsedRealtime()} time base. - * @returnDoc Value is a non-negative timestamp in the - * {@link SystemClock#elapsedRealtime()} time base. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface ElapsedRealtimeLong { -} diff --git a/core/java/android/annotation/FloatRange.java b/core/java/android/annotation/FloatRange.java deleted file mode 100644 index 05b51680b1b0..000000000000 --- a/core/java/android/annotation/FloatRange.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element should be a float or double in the given range - * <p> - * Example: - * <pre><code> - * @FloatRange(from=0.0,to=1.0) - * public float getAlpha() { - * ... - * } - * </code></pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE}) -public @interface FloatRange { - /** Smallest value. Whether it is inclusive or not is determined - * by {@link #fromInclusive} */ - double from() default Double.NEGATIVE_INFINITY; - /** Largest value. Whether it is inclusive or not is determined - * by {@link #toInclusive} */ - double to() default Double.POSITIVE_INFINITY; - - /** Whether the from value is included in the range */ - boolean fromInclusive() default true; - - /** Whether the to value is included in the range */ - boolean toInclusive() default true; -}
\ No newline at end of file diff --git a/core/java/android/annotation/FontRes.java b/core/java/android/annotation/FontRes.java deleted file mode 100644 index dbacb5876dce..000000000000 --- a/core/java/android/annotation/FontRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a Font resource reference (e.g. R.font.myfont). - * - * @hide - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface FontRes { -} diff --git a/core/java/android/annotation/FractionRes.java b/core/java/android/annotation/FractionRes.java deleted file mode 100644 index fd84d3e85fdf..000000000000 --- a/core/java/android/annotation/FractionRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a fraction resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface FractionRes { -} diff --git a/core/java/android/annotation/HalfFloat.java b/core/java/android/annotation/HalfFloat.java deleted file mode 100644 index 256008c5e31f..000000000000 --- a/core/java/android/annotation/HalfFloat.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * <p>Denotes that the annotated element represents a half-precision floating point - * value. Such values are stored in short data types and can be manipulated with - * the {@link android.util.Half} class. If applied to an array of short, every - * element in the array represents a half-precision float.</p> - * - * <p>Example:</p> - * - * <pre>{@code - * public abstract void setPosition(@HalfFloat short x, @HalfFloat short y, @HalfFloat short z); - * }</pre> - * - * @see android.util.Half - * @see android.util.Half#toHalf(float) - * @see android.util.Half#toFloat(short) - * - * @hide - */ -@Retention(SOURCE) -@Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD}) -public @interface HalfFloat { -} diff --git a/core/java/android/annotation/Hide.java b/core/java/android/annotation/Hide.java deleted file mode 100644 index c8e5a4a97ae7..000000000000 --- a/core/java/android/annotation/Hide.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates that an API is hidden by default, in a similar fashion to the - * <pre>@hide</pre> javadoc tag. - * - * <p>Note that, in order for this to work, metalava has to be invoked with - * the flag {@code --hide-annotation android.annotation.Hide}. - * @hide - */ -@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) -@Retention(RetentionPolicy.CLASS) -public @interface Hide { -} diff --git a/core/java/android/annotation/IdRes.java b/core/java/android/annotation/IdRes.java deleted file mode 100644 index b286965c99d9..000000000000 --- a/core/java/android/annotation/IdRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an id resource reference (e.g. {@link android.R.id#copy}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface IdRes { -} diff --git a/core/java/android/annotation/IntDef.java b/core/java/android/annotation/IntDef.java deleted file mode 100644 index f84a67655dc3..000000000000 --- a/core/java/android/annotation/IntDef.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element of integer type, represents - * a logical type and that its value should be one of the explicitly - * named constants. If the {@link #flag()} attribute is set to true, - * multiple constants can be combined. - * <p> - * <pre><code> - * @Retention(SOURCE) - * @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) - * public @interface NavigationMode {} - * public static final int NAVIGATION_MODE_STANDARD = 0; - * public static final int NAVIGATION_MODE_LIST = 1; - * public static final int NAVIGATION_MODE_TABS = 2; - * ... - * public abstract void setNavigationMode(@NavigationMode int mode); - * @NavigationMode - * public abstract int getNavigationMode(); - * </code></pre> - * For a flag, set the flag attribute: - * <pre><code> - * @IntDef( - * flag = true, - * value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) - * </code></pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({ANNOTATION_TYPE}) -public @interface IntDef { - /** Defines the constant prefix for this element */ - String[] prefix() default {}; - /** Defines the constant suffix for this element */ - String[] suffix() default {}; - - /** Defines the allowed constants for this element */ - int[] value() default {}; - - /** Defines whether the constants can be used as a flag, or just as an enum (the default) */ - boolean flag() default false; -} diff --git a/core/java/android/annotation/IntRange.java b/core/java/android/annotation/IntRange.java deleted file mode 100644 index c043e2db6a98..000000000000 --- a/core/java/android/annotation/IntRange.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element should be an int or long in the given range - * <p> - * Example: - * <pre><code> - * @IntRange(from=0,to=255) - * public int getAlpha() { - * ... - * } - * </code></pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE}) -public @interface IntRange { - /** Smallest value, inclusive */ - long from() default Long.MIN_VALUE; - /** Largest value, inclusive */ - long to() default Long.MAX_VALUE; -}
\ No newline at end of file diff --git a/core/java/android/annotation/IntegerRes.java b/core/java/android/annotation/IntegerRes.java deleted file mode 100644 index 5313f4adf46e..000000000000 --- a/core/java/android/annotation/IntegerRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an integer resource reference (e.g. {@link android.R.integer#config_shortAnimTime}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface IntegerRes { -} diff --git a/core/java/android/annotation/InterpolatorRes.java b/core/java/android/annotation/InterpolatorRes.java deleted file mode 100644 index 8877a5f9a4f1..000000000000 --- a/core/java/android/annotation/InterpolatorRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an interpolator resource reference (e.g. {@link android.R.interpolator#cycle}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface InterpolatorRes { -} diff --git a/core/java/android/annotation/LayoutRes.java b/core/java/android/annotation/LayoutRes.java deleted file mode 100644 index 15ba86f98159..000000000000 --- a/core/java/android/annotation/LayoutRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a layout resource reference (e.g. {@link android.R.layout#list_content}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface LayoutRes { -} diff --git a/core/java/android/annotation/LongDef.java b/core/java/android/annotation/LongDef.java deleted file mode 100644 index 8723eef86328..000000000000 --- a/core/java/android/annotation/LongDef.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated long element represents - * a logical type and that its value should be one of the explicitly - * named constants. If the {@link #flag()} attribute is set to true, - * multiple constants can be combined. - * <p> - * <pre><code> - * @Retention(SOURCE) - * @LongDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) - * public @interface NavigationMode {} - * public static final long NAVIGATION_MODE_STANDARD = 0; - * public static final long NAVIGATION_MODE_LIST = 1; - * public static final long NAVIGATION_MODE_TABS = 2; - * ... - * public abstract void setNavigationMode(@NavigationMode long mode); - * @NavigationMode - * public abstract long getNavigationMode(); - * </code></pre> - * For a flag, set the flag attribute: - * <pre><code> - * @LongDef( - * flag = true, - * value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) - * </code></pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({ANNOTATION_TYPE}) -public @interface LongDef { - /** Defines the constant prefix for this element */ - String[] prefix() default ""; - - /** Defines the allowed constants for this element */ - long[] value() default {}; - - /** Defines whether the constants can be used as a flag, or just as an enum (the default) */ - boolean flag() default false; -} diff --git a/core/java/android/annotation/MainThread.java b/core/java/android/annotation/MainThread.java deleted file mode 100644 index a070246e5ef3..000000000000 --- a/core/java/android/annotation/MainThread.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated method should only be called on the main thread. - * If the annotated element is a class, then all methods in the class should be - * called on the main thread. - * <p> - * Example: - * - * <pre> - * <code> - * @MainThread - * public void deliverResult(D data) { ... } - * </code> - * </pre> - * - * @memberDoc This method must be called from the main thread of your app. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface MainThread { -} diff --git a/core/java/android/annotation/MenuRes.java b/core/java/android/annotation/MenuRes.java deleted file mode 100644 index b6dcc4604cfb..000000000000 --- a/core/java/android/annotation/MenuRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a menu resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface MenuRes { -} diff --git a/core/java/android/annotation/NavigationRes.java b/core/java/android/annotation/NavigationRes.java deleted file mode 100644 index 3af5ecff84a6..000000000000 --- a/core/java/android/annotation/NavigationRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a navigation resource reference (e.g. {@code R.navigation.flow}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface NavigationRes { -} diff --git a/core/java/android/annotation/NonNull.java b/core/java/android/annotation/NonNull.java deleted file mode 100644 index 20472bacf6ad..000000000000 --- a/core/java/android/annotation/NonNull.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that a parameter, field or method return value can never be null. - * <p> - * This is a marker annotation and it has no specific attributes. - * - * @paramDoc This value cannot be {@code null}. - * @returnDoc This value cannot be {@code null}. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface NonNull { -} diff --git a/core/java/android/annotation/NonUiContext.java b/core/java/android/annotation/NonUiContext.java deleted file mode 100644 index c119ca20ba11..000000000000 --- a/core/java/android/annotation/NonUiContext.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.app.WallpaperManager; -import android.content.Context; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.WindowManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes a {@link Context} that <b>can not</b> be used to obtain a {@link Display} via - * {@link Context#getDisplay} nor to obtain a {@link WindowManager}, {@link LayoutInflater} or - * {@link WallpaperManager} via {@link Context#getSystemService(String)}. - * <p> - * This is a marker annotation and has no specific attributes. - * - * @see Context#getDisplay() - * @see Context#getSystemService(String) - * @see Context#getSystemService(Class) - * @hide - */ -@Retention(SOURCE) -@Target({TYPE, METHOD, PARAMETER, FIELD}) -public @interface NonUiContext { -} diff --git a/core/java/android/annotation/Nullable.java b/core/java/android/annotation/Nullable.java deleted file mode 100644 index b8473e750c95..000000000000 --- a/core/java/android/annotation/Nullable.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that a parameter, field or method return value can be null. - * <p> - * When decorating a method call parameter, this denotes that the parameter can - * legitimately be null and the method will gracefully deal with it. Typically - * used on optional parameters. - * <p> - * When decorating a method, this denotes the method might legitimately return - * null. - * <p> - * This is a marker annotation and it has no specific attributes. - * - * @paramDoc This value may be {@code null}. - * @returnDoc This value may be {@code null}. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface Nullable { -} diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS deleted file mode 100644 index e1ef54460b56..000000000000 --- a/core/java/android/annotation/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -tnorbye@google.com -aurimas@google.com -per-file UnsupportedAppUsage.java = mathewi@google.com, satayev@google.com, andreionea@google.com diff --git a/core/java/android/annotation/PluralsRes.java b/core/java/android/annotation/PluralsRes.java deleted file mode 100644 index 31ac729aaa47..000000000000 --- a/core/java/android/annotation/PluralsRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a plurals resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface PluralsRes { -} diff --git a/core/java/android/annotation/Px.java b/core/java/android/annotation/Px.java deleted file mode 100644 index cec7f80405d3..000000000000 --- a/core/java/android/annotation/Px.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that a numeric parameter, field or method return value is expected - * to represent a pixel dimension. - * - * @memberDoc This units of this value are pixels. - * @paramDoc This units of this value are pixels. - * @returnDoc This units of this value are pixels. - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -@Dimension(unit = Dimension.PX) -public @interface Px { -} diff --git a/core/java/android/annotation/RawRes.java b/core/java/android/annotation/RawRes.java deleted file mode 100644 index 39970b36fd95..000000000000 --- a/core/java/android/annotation/RawRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a raw resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface RawRes { -} diff --git a/core/java/android/annotation/RequiresFeature.java b/core/java/android/annotation/RequiresFeature.java deleted file mode 100644 index 08861d42be39..000000000000 --- a/core/java/android/annotation/RequiresFeature.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.content.pm.PackageManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated element requires one or more device features. This - * is used to auto-generate documentation. - * - * @hide - */ -@Retention(SOURCE) -@Target({TYPE,FIELD,METHOD,CONSTRUCTOR}) -public @interface RequiresFeature { - /** - * The name of the device feature that is required. - */ - String value(); - - /** - * Defines the name of the method that should be called to check whether the feature is - * available, using the same signature format as javadoc. The feature checking method can have - * multiple parameters, but the feature name parameter must be of type String and must also be - * the first String-type parameter. - * <p> - * By default, the enforcement is {@link PackageManager#hasSystemFeature(String)}. - */ - String enforcement() default("android.content.pm.PackageManager#hasSystemFeature"); -} diff --git a/core/java/android/annotation/RequiresNoPermission.java b/core/java/android/annotation/RequiresNoPermission.java deleted file mode 100644 index cdbf36ec20dd..000000000000 --- a/core/java/android/annotation/RequiresNoPermission.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated element requires no permissions. - * <p> - * This explicit annotation helps distinguish which of three states that an - * element may exist in: - * <ul> - * <li>Annotated with {@link RequiresPermission}, indicating that an element - * requires (or may require) one or more permissions. - * <li>Annotated with {@link RequiresNoPermission}, indicating that an element - * requires no permissions. - * <li>Neither annotation, indicating that no explicit declaration about - * permissions has been made for that element. - * </ul> - * - * @see RequiresPermission - * @hide - */ -@Retention(CLASS) -@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER}) -public @interface RequiresNoPermission { -} diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java deleted file mode 100644 index 0379d303ab92..000000000000 --- a/core/java/android/annotation/RequiresPermission.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated element requires (or may require) one or more permissions. - * <p/> - * Example of requiring a single permission: - * <pre>{@code - * {@literal @}RequiresPermission(Manifest.permission.SET_WALLPAPER) - * public abstract void setWallpaper(Bitmap bitmap) throws IOException; - * - * {@literal @}RequiresPermission(ACCESS_COARSE_LOCATION) - * public abstract Location getLastKnownLocation(String provider); - * }</pre> - * Example of requiring at least one permission from a set: - * <pre>{@code - * {@literal @}RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) - * public abstract Location getLastKnownLocation(String provider); - * }</pre> - * Example of requiring multiple permissions: - * <pre>{@code - * {@literal @}RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) - * public abstract Location getLastKnownLocation(String provider); - * }</pre> - * Example of requiring separate read and write permissions for a content provider: - * <pre>{@code - * {@literal @}RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS)) - * {@literal @}RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS)) - * public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks"); - * }</pre> - * <p> - * When specified on a parameter, the annotation indicates that the method requires - * a permission which depends on the value of the parameter. For example, consider - * {@link android.app.Activity#startActivity(android.content.Intent) - * Activity#startActivity(Intent)}: - * <pre>{@code - * public void startActivity(@RequiresPermission Intent intent) { ... } - * }</pre> - * Notice how there are no actual permission names listed in the annotation. The actual - * permissions required will depend on the particular intent passed in. For example, - * the code may look like this: - * <pre>{@code - * Intent intent = new Intent(Intent.ACTION_CALL); - * startActivity(intent); - * }</pre> - * and the actual permission requirement for this particular intent is described on - * the Intent name itself: - * <pre>{@code - * {@literal @}RequiresPermission(Manifest.permission.CALL_PHONE) - * public static final String ACTION_CALL = "android.intent.action.CALL"; - * }</pre> - * - * @see RequiresNoPermission - * @hide - */ -@Retention(CLASS) -@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER}) -public @interface RequiresPermission { - /** - * The name of the permission that is required, if precisely one permission - * is required. If more than one permission is required, specify either - * {@link #allOf()} or {@link #anyOf()} instead. - * <p> - * If specified, {@link #anyOf()} and {@link #allOf()} must both be null. - */ - String value() default ""; - - /** - * Specifies a list of permission names that are all required. - * <p> - * If specified, {@link #anyOf()} and {@link #value()} must both be null. - */ - String[] allOf() default {}; - - /** - * Specifies a list of permission names where at least one is required - * <p> - * If specified, {@link #allOf()} and {@link #value()} must both be null. - */ - String[] anyOf() default {}; - - /** - * If true, the permission may not be required in all cases (e.g. it may only be - * enforced on certain platforms, or for certain call parameters, etc. - */ - boolean conditional() default false; - - /** - * Specifies that the given permission is required for read operations. - * <p> - * When specified on a parameter, the annotation indicates that the method requires - * a permission which depends on the value of the parameter (and typically - * the corresponding field passed in will be one of a set of constants which have - * been annotated with a <code>@RequiresPermission</code> annotation.) - */ - @Target({FIELD, METHOD, PARAMETER}) - @interface Read { - RequiresPermission value() default @RequiresPermission; - } - - /** - * Specifies that the given permission is required for write operations. - * <p> - * When specified on a parameter, the annotation indicates that the method requires - * a permission which depends on the value of the parameter (and typically - * the corresponding field passed in will be one of a set of constants which have - * been annotated with a <code>@RequiresPermission</code> annotation.) - */ - @Target({FIELD, METHOD, PARAMETER}) - @interface Write { - RequiresPermission value() default @RequiresPermission; - } -} diff --git a/core/java/android/annotation/SdkConstant.java b/core/java/android/annotation/SdkConstant.java deleted file mode 100644 index 0a5318609847..000000000000 --- a/core/java/android/annotation/SdkConstant.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Indicates a constant field value should be exported to be used in the SDK tools. - * @hide - */ -@Target({ ElementType.FIELD }) -@Retention(RetentionPolicy.SOURCE) -public @interface SdkConstant { - public static enum SdkConstantType { - ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY, FEATURE; - } - - SdkConstantType value(); -} diff --git a/core/java/android/annotation/Size.java b/core/java/android/annotation/Size.java deleted file mode 100644 index 7c3e70f658e9..000000000000 --- a/core/java/android/annotation/Size.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element should have a given size or length. - * Note that "-1" means "unset". Typically used with a parameter or - * return value of type array or collection. - * <p> - * Example: - * <pre>{@code - * public void getLocationInWindow(@Size(2) int[] location) { - * ... - * } - * }</pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD}) -public @interface Size { - /** An exact size (or -1 if not specified) */ - long value() default -1; - /** A minimum size, inclusive */ - long min() default Long.MIN_VALUE; - /** A maximum size, inclusive */ - long max() default Long.MAX_VALUE; - /** The size must be a multiple of this factor */ - long multiple() default 1; -}
\ No newline at end of file diff --git a/core/java/android/annotation/StringDef.java b/core/java/android/annotation/StringDef.java deleted file mode 100644 index a37535b9c98e..000000000000 --- a/core/java/android/annotation/StringDef.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated String element, represents a logical - * type and that its value should be one of the explicitly named constants. - * <p> - * Example: - * <pre><code> - * @Retention(SOURCE) - * @StringDef({ - * POWER_SERVICE, - * WINDOW_SERVICE, - * LAYOUT_INFLATER_SERVICE - * }) - * public @interface ServiceName {} - * public static final String POWER_SERVICE = "power"; - * public static final String WINDOW_SERVICE = "window"; - * public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; - * ... - * public abstract Object getSystemService(@ServiceName String name); - * </code></pre> - * - * @hide - */ -@Retention(SOURCE) -@Target({ANNOTATION_TYPE}) -public @interface StringDef { - /** Defines the constant prefix for this element */ - String[] prefix() default {}; - /** Defines the constant suffix for this element */ - String[] suffix() default {}; - - /** Defines the allowed constants for this element */ - String[] value() default {}; -} diff --git a/core/java/android/annotation/StringRes.java b/core/java/android/annotation/StringRes.java deleted file mode 100644 index 190b68a9960b..000000000000 --- a/core/java/android/annotation/StringRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a String resource reference (e.g. {@link android.R.string#ok}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface StringRes { -} diff --git a/core/java/android/annotation/StyleRes.java b/core/java/android/annotation/StyleRes.java deleted file mode 100644 index 4453b8d89153..000000000000 --- a/core/java/android/annotation/StyleRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that a integer parameter, field or method return value is expected - * to be a style resource reference (e.g. {@link android.R.style#TextAppearance}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface StyleRes { -} diff --git a/core/java/android/annotation/StyleableRes.java b/core/java/android/annotation/StyleableRes.java deleted file mode 100644 index 3c1895e6dce9..000000000000 --- a/core/java/android/annotation/StyleableRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that a integer parameter, field or method return value is expected - * to be a styleable resource reference (e.g. {@link android.R.styleable#TextView_text}). - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface StyleableRes { -} diff --git a/core/java/android/annotation/SuppressAutoDoc.java b/core/java/android/annotation/SuppressAutoDoc.java deleted file mode 100644 index e34e03bcee29..000000000000 --- a/core/java/android/annotation/SuppressAutoDoc.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that any automatically generated documentation should be suppressed - * for the annotated method, parameter, or field. - * - * @hide - */ -@Retention(SOURCE) -@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -public @interface SuppressAutoDoc { -} diff --git a/core/java/android/annotation/SuppressLint.java b/core/java/android/annotation/SuppressLint.java deleted file mode 100644 index 2d3456b0ea46..000000000000 --- a/core/java/android/annotation/SuppressLint.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** Indicates that Lint should ignore the specified warnings for the annotated element. */ -@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -@Retention(RetentionPolicy.CLASS) -public @interface SuppressLint { - /** - * The set of warnings (identified by the lint issue id) that should be - * ignored by lint. It is not an error to specify an unrecognized name. - */ - String[] value(); -} diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java deleted file mode 100644 index a468439c8e74..000000000000 --- a/core/java/android/annotation/SystemApi.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates an API is exposed for use by bundled system applications. - * <p> - * These APIs are not guaranteed to remain consistent release-to-release, - * and are not for use by apps linking against the Android SDK. - * </p><p> - * This annotation should only appear on API that is already marked <pre>@hide</pre>. - * </p> - * - * @hide - */ -@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface SystemApi { - enum Client { - /** - * Specifies that the intended clients of a SystemApi are privileged apps. - * This is the default value for {@link #client}. - */ - PRIVILEGED_APPS, - - /** - * Specifies that the intended clients of a SystemApi are used by classes in - * <pre>BOOTCLASSPATH</pre> in mainline modules. Mainline modules can also expose - * this type of system APIs too when they're used only by the non-updatable - * platform code. - */ - MODULE_LIBRARIES, - - /** - * Specifies that the system API is available only in the system server process. - * Use this to expose APIs from code loaded by the system server process <em>but</em> - * not in <pre>BOOTCLASSPATH</pre>. - */ - SYSTEM_SERVER - } - - /** - * The intended client of this SystemAPI. - */ - Client client() default android.annotation.SystemApi.Client.PRIVILEGED_APPS; - - /** - * Container for {@link SystemApi} that allows it to be applied repeatedly to types. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(TYPE) - @interface Container { - SystemApi[] value(); - } -} diff --git a/core/java/android/annotation/SystemService.java b/core/java/android/annotation/SystemService.java deleted file mode 100644 index c05c1bab06d2..000000000000 --- a/core/java/android/annotation/SystemService.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Description of a system service available through - * {@link android.content.Context#getSystemService(Class)}. This is used to auto-generate - * documentation explaining how to obtain a reference to the service. - * - * @hide - */ -@Retention(SOURCE) -@Target(TYPE) -public @interface SystemService { - /** - * The string name of the system service that can be passed to - * {@link android.content.Context#getSystemService(String)}. - * - * @see android.content.Context#getSystemServiceName(Class) - */ - String value(); -} diff --git a/core/java/android/annotation/TargetApi.java b/core/java/android/annotation/TargetApi.java deleted file mode 100644 index 975318e4de67..000000000000 --- a/core/java/android/annotation/TargetApi.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** Indicates that Lint should treat this type as targeting a given API level, no matter what the - project target is. */ -@Target({TYPE, METHOD, CONSTRUCTOR, FIELD}) -@Retention(RetentionPolicy.CLASS) -public @interface TargetApi { - /** - * This sets the target api level for the type.. - */ - int value(); -} diff --git a/core/java/android/annotation/TestApi.java b/core/java/android/annotation/TestApi.java deleted file mode 100644 index 0e9ed3751246..000000000000 --- a/core/java/android/annotation/TestApi.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates an API is exposed for use by CTS. - * <p> - * These APIs are not guaranteed to remain consistent release-to-release, - * and are not for use by apps linking against the Android SDK. - * </p> - * - * @hide - */ -@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) -@Retention(RetentionPolicy.SOURCE) -public @interface TestApi { -} diff --git a/core/java/android/annotation/TransitionRes.java b/core/java/android/annotation/TransitionRes.java deleted file mode 100644 index 06bac74984a5..000000000000 --- a/core/java/android/annotation/TransitionRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a transition resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface TransitionRes { -} diff --git a/core/java/android/annotation/UiContext.java b/core/java/android/annotation/UiContext.java deleted file mode 100644 index 47becc08c2f3..000000000000 --- a/core/java/android/annotation/UiContext.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.app.Activity; -import android.app.WallpaperManager; -import android.content.Context; -import android.os.Bundle; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.WindowManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes a {@link Context} that can be used to create UI, meaning that it can provide a - * {@link Display} via {@link Context#getDisplay} and can be used to obtain a {@link WindowManager}, - * {@link LayoutInflater} or {@link WallpaperManager} via {@link Context#getSystemService(String)}. - * A {@link Context} which is marked as {@link UiContext} implies that the {@link Context} is also - * a {@link DisplayContext}. - * <p> - * This kind of {@link Context} is usually an {@link Activity} or - * created via {@link Context#createWindowContext(int, Bundle)}. - * </p> - * This is a marker annotation and has no specific attributes. - * - * @see Context#getDisplay() - * @see Context#getSystemService(String) - * @see Context#getSystemService(Class) - * @see Context#createWindowContext(int, Bundle) - * @see DisplayContext - * @hide - */ -@Retention(SOURCE) -@Target({TYPE, METHOD, PARAMETER, FIELD}) -public @interface UiContext { -} diff --git a/core/java/android/annotation/UiThread.java b/core/java/android/annotation/UiThread.java deleted file mode 100644 index 6d7eedc7d2e2..000000000000 --- a/core/java/android/annotation/UiThread.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.os.Looper; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated method or constructor should only be called on the - * UI thread. If the annotated element is a class, then all methods in the class - * should be called on the UI thread. - * <p> - * Example: - * - * <pre> - * <code> - * @UiThread - * public abstract void setText(@NonNull String text) { ... } - * </code> - * </pre> - * - * @memberDoc This method must be called on the thread that originally created - * this UI element. This is typically the - * {@linkplain Looper#getMainLooper() main thread} of your app. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface UiThread { -} diff --git a/core/java/android/annotation/UptimeMillisLong.java b/core/java/android/annotation/UptimeMillisLong.java deleted file mode 100644 index 8946eea0249c..000000000000 --- a/core/java/android/annotation/UptimeMillisLong.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.os.SystemClock; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * @memberDoc Value is a non-negative timestamp in the - * {@link SystemClock#uptimeMillis()} time base. - * @paramDoc Value is a non-negative timestamp in the - * {@link SystemClock#uptimeMillis()} time base. - * @returnDoc Value is a non-negative timestamp in the - * {@link SystemClock#uptimeMillis()} time base. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface UptimeMillisLong { -} diff --git a/core/java/android/annotation/UserHandleAware.java b/core/java/android/annotation/UserHandleAware.java deleted file mode 100644 index 7d3d20b31b2a..000000000000 --- a/core/java/android/annotation/UserHandleAware.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Indicates an API that uses {@code context.getUser} or {@code context.getUserId} - * to operate across users (as the user associated with the context) - * <p> - * To create a {@link android.content.Context} associated with a different user, - * use {@link android.content.Context#createContextAsUser} or - * {@link android.content.Context#createPackageContextAsUser} - * <p> - * Example: - * <pre>{@code - * {@literal @}UserHandleAware - * public abstract PackageInfo getPackageInfo({@literal @}NonNull String packageName, - * {@literal @}PackageInfoFlags int flags) throws NameNotFoundException; - * }</pre> - * - * @memberDoc This method uses {@linkplain android.content.Context#getUser} - * or {@linkplain android.content.Context#getUserId} to execute across users. - * @hide - */ -@Retention(SOURCE) -@Target({TYPE, METHOD, CONSTRUCTOR, PACKAGE}) -public @interface UserHandleAware { -} diff --git a/core/java/android/annotation/UserIdInt.java b/core/java/android/annotation/UserIdInt.java deleted file mode 100644 index 7b9ce25e3f1a..000000000000 --- a/core/java/android/annotation/UserIdInt.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Denotes that the annotated element is a multi-user user ID. This is - * <em>not</em> the same as a UID. - * - * @hide - */ -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface UserIdInt { -} diff --git a/core/java/android/annotation/Widget.java b/core/java/android/annotation/Widget.java deleted file mode 100644 index 6756cd73c5fe..000000000000 --- a/core/java/android/annotation/Widget.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.annotation; - -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Indicates a class is a widget usable by application developers to create UI. - * <p> - * This must be used in cases where: - * <ul> - * <li>The widget is not in the package <code>android.widget</code></li> - * <li>The widget extends <code>android.view.ViewGroup</code></li> - * </ul> - * @hide - */ -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.SOURCE) -public @interface Widget { -} diff --git a/core/java/android/annotation/WorkerThread.java b/core/java/android/annotation/WorkerThread.java deleted file mode 100644 index 8c2a4d381ab1..000000000000 --- a/core/java/android/annotation/WorkerThread.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated method should only be called on a worker thread. - * If the annotated element is a class, then all methods in the class should be - * called on a worker thread. - * <p> - * Example: - * - * <pre> - * <code> - * @WorkerThread - * protected abstract FilterResults performFiltering(CharSequence constraint); - * </code> - * </pre> - * - * @memberDoc This method may take several seconds to complete, so it should - * only be called from a worker thread. - * @hide - */ -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface WorkerThread { -} diff --git a/core/java/android/annotation/XmlRes.java b/core/java/android/annotation/XmlRes.java deleted file mode 100644 index 5fb8a4a47127..000000000000 --- a/core/java/android/annotation/XmlRes.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an XML resource reference. - * - * {@hide} - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface XmlRes { -} diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b3e656d30752..ff210e1c0ea6 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5613,7 +5613,7 @@ public final class ActivityThread extends ClientTransactionHandler } /** Performs the activity relaunch locally vs. requesting from system-server. */ - private void handleRelaunchActivityLocally(IBinder token) { + public void handleRelaunchActivityLocally(IBinder token) { final ActivityClientRecord r = mActivities.get(token); if (r == null) { Log.w(TAG, "Activity to relaunch no longer exists"); @@ -5977,20 +5977,6 @@ public final class ActivityThread extends ClientTransactionHandler // Update all affected Resources objects to use new ResourcesImpl mResourcesManager.applyNewResourceDirsLocked(ai, oldResDirs); } - - ApplicationPackageManager.configurationChanged(); - - // Trigger a regular Configuration change event, only with a different assetsSeq number - // so that we actually call through to all components. - // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to - // store configurations per-process. - final Configuration config = mConfigurationController.getConfiguration(); - Configuration newConfig = new Configuration(); - newConfig.assetsSeq = (config != null ? config.assetsSeq : 0) + 1; - mConfigurationController.handleConfigurationChanged(newConfig, null /* compat */); - - // Preserve windows to avoid black flickers when overlays change. - relaunchAllActivities(true /* preserveWindows */, "handleApplicationInfoChanged"); } /** diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index efeef1b07c0e..75a38c2380b9 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -4723,8 +4723,8 @@ public class AppOpsManager { } /** - * Flag for querying app op history: get only aggregate information and no - * discrete accesses. + * Flag for querying app op history: get only aggregate information (counts of events) and no + * discret accesses information - specific accesses with timestamp. * * @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer) * @@ -4735,8 +4735,8 @@ public class AppOpsManager { public static final int HISTORY_FLAG_AGGREGATE = 1 << 0; /** - * Flag for querying app op history: get only discrete information and no - * aggregate accesses. + * Flag for querying app op history: get only discrete access information (only specific + * accesses with timestamps) and no aggregate information (counts over time). * * @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer) * @@ -4747,7 +4747,7 @@ public class AppOpsManager { public static final int HISTORY_FLAG_DISCRETE = 1 << 1; /** - * Flag for querying app op history: get all types of historical accesses. + * Flag for querying app op history: get all types of historical access information. * * @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer) * diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index dba62b9d3b63..5a70f925fc02 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -881,7 +881,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int required, @NonNull List<Certificate> trustedInstallers, + @Checksum.TypeMask int required, @NonNull List<Certificate> trustedInstallers, @NonNull OnChecksumsReadyListener onChecksumsReadyListener) throws CertificateEncodingException, NameNotFoundException { Objects.requireNonNull(packageName); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 7dc662abe0c1..609c014feb5b 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -5513,6 +5513,10 @@ public class DevicePolicyManager { * This method requires the caller to be the device owner. * <p> * This proxy is only a recommendation and it is possible that some apps will ignore it. + * <p> + * Note: The device owner won't be able to set a global HTTP proxy if there are unaffiliated + * secondary users or profiles on the device. It's recommended that affiliation ids are set for + * new users as soon as possible after provisioning via {@link #setAffiliationIds}. * * @see ProxyInfo * @param admin Which {@link DeviceAdminReceiver} this request is associated with. @@ -12791,6 +12795,11 @@ public class DevicePolicyManager { * <p>In this mode, the DNS subsystem will attempt a TLS handshake to the network-supplied * resolver prior to attempting name resolution in cleartext. * + * <p>Note: The device owner won't be able to set the global private DNS mode if there are + * unaffiliated secondary users or profiles on the device. It's recommended that affiliation + * ids are set for new users as soon as possible after provisioning via + * {@link #setAffiliationIds}. + * * @param admin which {@link DeviceAdminReceiver} this request is associated with. * * @return {@code PRIVATE_DNS_SET_NO_ERROR} if the mode was set successfully, or @@ -12826,6 +12835,11 @@ public class DevicePolicyManager { * the ability to resolve hostnames as system traffic to the resolver may not go through the * VPN. * + * <p>Note: The device owner won't be able to set the global private DNS mode if there are + * unaffiliated secondary users or profiles on the device. It's recommended that affiliation + * ids are set for new users as soon as possible after provisioning via + * {@link #setAffiliationIds}. + * * @param admin which {@link DeviceAdminReceiver} this request is associated with. * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858). * diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java index de3eeee281ac..2dbbfdf660aa 100644 --- a/core/java/android/app/people/PeopleSpaceTile.java +++ b/core/java/android/app/people/PeopleSpaceTile.java @@ -43,6 +43,12 @@ import java.util.List; */ public class PeopleSpaceTile implements Parcelable { + public static final int SHOW_CONVERSATIONS = 1 << 0; + public static final int BLOCK_CONVERSATIONS = 1 << 1; + public static final int SHOW_IMPORTANT_CONVERSATIONS = 1 << 2; + public static final int SHOW_STARRED_CONTACTS = 1 << 3; + public static final int SHOW_CONTACTS = 1 << 4; + private String mId; private CharSequence mUserName; private Icon mUserIcon; @@ -61,6 +67,11 @@ public class PeopleSpaceTile implements Parcelable { private Intent mIntent; private long mNotificationTimestamp; private List<ConversationStatus> mStatuses; + private boolean mCanBypassDnd; + private boolean mIsPackageSuspended; + private boolean mIsUserQuieted; + private int mNotificationPolicyState; + private float mContactAffinity; private PeopleSpaceTile(Builder b) { mId = b.mId; @@ -81,6 +92,11 @@ public class PeopleSpaceTile implements Parcelable { mIntent = b.mIntent; mNotificationTimestamp = b.mNotificationTimestamp; mStatuses = b.mStatuses; + mCanBypassDnd = b.mCanBypassDnd; + mIsPackageSuspended = b.mIsPackageSuspended; + mIsUserQuieted = b.mIsUserQuieted; + mNotificationPolicyState = b.mNotificationPolicyState; + mContactAffinity = b.mContactAffinity; } public String getId() { @@ -173,6 +189,41 @@ public class PeopleSpaceTile implements Parcelable { return mStatuses; } + /** + * Whether the app associated with the conversation can bypass DND. + */ + public boolean canBypassDnd() { + return mCanBypassDnd; + } + + /** + * Whether the app associated with the conversation is suspended. + */ + public boolean isPackageSuspended() { + return mIsPackageSuspended; + } + + /** + * Whether the user associated with the conversation is quieted. + */ + public boolean isUserQuieted() { + return mIsUserQuieted; + } + + /** + * Returns the state of notifications for the conversation. + */ + public int getNotificationPolicyState() { + return mNotificationPolicyState; + } + + /** + * Returns the contact affinity (whether the contact is starred). + */ + public float getContactAffinity() { + return mContactAffinity; + } + /** Converts a {@link PeopleSpaceTile} into a {@link PeopleSpaceTile.Builder}. */ public Builder toBuilder() { Builder builder = @@ -192,6 +243,11 @@ public class PeopleSpaceTile implements Parcelable { builder.setIntent(mIntent); builder.setNotificationTimestamp(mNotificationTimestamp); builder.setStatuses(mStatuses); + builder.setCanBypassDnd(mCanBypassDnd); + builder.setIsPackageSuspended(mIsPackageSuspended); + builder.setIsUserQuieted(mIsUserQuieted); + builder.setNotificationPolicyState(mNotificationPolicyState); + builder.setContactAffinity(mContactAffinity); return builder; } @@ -215,6 +271,11 @@ public class PeopleSpaceTile implements Parcelable { private Intent mIntent; private long mNotificationTimestamp; private List<ConversationStatus> mStatuses; + private boolean mCanBypassDnd; + private boolean mIsPackageSuspended; + private boolean mIsUserQuieted; + private int mNotificationPolicyState; + private float mContactAffinity; /** Builder for use only if a shortcut is not available for the tile. */ public Builder(String id, CharSequence userName, Icon userIcon, Intent intent) { @@ -223,6 +284,7 @@ public class PeopleSpaceTile implements Parcelable { mUserIcon = userIcon; mIntent = intent; mPackageName = intent == null ? null : intent.getPackage(); + mNotificationPolicyState = SHOW_CONVERSATIONS; } public Builder(ShortcutInfo info, LauncherApps launcherApps) { @@ -232,6 +294,7 @@ public class PeopleSpaceTile implements Parcelable { mUserHandle = info.getUserHandle(); mPackageName = info.getPackage(); mContactUri = getContactUri(info); + mNotificationPolicyState = SHOW_CONVERSATIONS; } public Builder(ConversationChannel channel, LauncherApps launcherApps) { @@ -246,6 +309,9 @@ public class PeopleSpaceTile implements Parcelable { mLastInteractionTimestamp = channel.getLastEventTimestamp(); mIsImportantConversation = channel.getParentNotificationChannel() != null && channel.getParentNotificationChannel().isImportantConversation(); + mCanBypassDnd = channel.getParentNotificationChannel() != null + && channel.getParentNotificationChannel().canBypassDnd(); + mNotificationPolicyState = SHOW_CONVERSATIONS; } /** Returns the Contact's Uri if present. */ @@ -366,6 +432,36 @@ public class PeopleSpaceTile implements Parcelable { return this; } + /** Sets whether the conversation channel can bypass DND. */ + public Builder setCanBypassDnd(boolean canBypassDnd) { + mCanBypassDnd = canBypassDnd; + return this; + } + + /** Sets whether the package is suspended. */ + public Builder setIsPackageSuspended(boolean isPackageSuspended) { + mIsPackageSuspended = isPackageSuspended; + return this; + } + + /** Sets whether the user has been quieted. */ + public Builder setIsUserQuieted(boolean isUserQuieted) { + mIsUserQuieted = isUserQuieted; + return this; + } + + /** Sets the state of blocked notifications for the conversation. */ + public Builder setNotificationPolicyState(int notificationPolicyState) { + mNotificationPolicyState = notificationPolicyState; + return this; + } + + /** Sets the contact's affinity. */ + public Builder setContactAffinity(float contactAffinity) { + mContactAffinity = contactAffinity; + return this; + } + /** Builds a {@link PeopleSpaceTile}. */ @NonNull public PeopleSpaceTile build() { @@ -393,6 +489,11 @@ public class PeopleSpaceTile implements Parcelable { mNotificationTimestamp = in.readLong(); mStatuses = new ArrayList<>(); in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader()); + mCanBypassDnd = in.readBoolean(); + mIsPackageSuspended = in.readBoolean(); + mIsUserQuieted = in.readBoolean(); + mNotificationPolicyState = in.readInt(); + mContactAffinity = in.readFloat(); } @Override @@ -420,6 +521,11 @@ public class PeopleSpaceTile implements Parcelable { dest.writeParcelable(mIntent, flags); dest.writeLong(mNotificationTimestamp); dest.writeParcelableList(mStatuses, flags); + dest.writeBoolean(mCanBypassDnd); + dest.writeBoolean(mIsPackageSuspended); + dest.writeBoolean(mIsUserQuieted); + dest.writeInt(mNotificationPolicyState); + dest.writeFloat(mContactAffinity); } public static final @android.annotation.NonNull @@ -427,7 +533,6 @@ public class PeopleSpaceTile implements Parcelable { public PeopleSpaceTile createFromParcel(Parcel source) { return new PeopleSpaceTile(source); } - public PeopleSpaceTile[] newArray(int size) { return new PeopleSpaceTile[size]; } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 114ad874d0c4..7e1df1b0e59c 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1885,9 +1885,9 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * in {@link android.provider.MediaStore.MediaColumns}.</p> * * @param uri The URI whose file is to be opened. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode Access mode for the file. May be "r" for read-only access, + * "rw" for read and write access, or "rwt" for read and write access + * that truncates any existing file. * * @return Returns a new ParcelFileDescriptor which you can use to access * the file. @@ -1948,9 +1948,10 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * in {@link android.provider.MediaStore.MediaColumns}.</p> * * @param uri The URI whose file is to be opened. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode Access mode for the file. May be "r" for read-only access, + * "w" for write-only access, "rw" for read and write access, or + * "rwt" for read and write access that truncates any existing + * file. * @param signal A signal to cancel the operation in progress, or * {@code null} if none. For example, if you are downloading a * file from the network to service a "rw" mode request, you @@ -2010,9 +2011,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> * * @param uri The URI whose file is to be opened. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode Access mode for the file. May be "r" for read-only access, + * "w" for write-only access (erasing whatever data is currently in + * the file), "wa" for write-only access to append to any existing data, + * "rw" for read and write access on any existing data, and "rwt" for read + * and write access that truncates any existing file. * * @return Returns a new AssetFileDescriptor which you can use to access * the file. @@ -2065,9 +2068,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> * * @param uri The URI whose file is to be opened. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode Access mode for the file. May be "r" for read-only access, + * "w" for write-only access (erasing whatever data is currently in + * the file), "wa" for write-only access to append to any existing data, + * "rw" for read and write access on any existing data, and "rwt" for read + * and write access that truncates any existing file. * @param signal A signal to cancel the operation in progress, or * {@code null} if none. For example, if you are downloading a * file from the network to service a "rw" mode request, you @@ -2098,9 +2103,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * by looking up a column named "_data" at the given URI. * * @param uri The URI to be opened. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode The file mode. May be "r" for read-only access, + * "w" for write-only access (erasing whatever data is currently in + * the file), "wa" for write-only access to append to any existing data, + * "rw" for read and write access on any existing data, and "rwt" for read + * and write access that truncates any existing file. * * @return Returns a new ParcelFileDescriptor that can be used by the * client to access the file. diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 1132991a57f8..aec39da973f0 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -63,9 +63,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; -import android.system.ErrnoException; import android.system.Int64Ref; -import android.system.Os; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -78,10 +76,8 @@ import com.android.internal.util.MimeIconUtils; import dalvik.system.CloseGuard; import java.io.File; -import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -868,20 +864,6 @@ public abstract class ContentResolver implements ContentInterface { return wrap((ContentInterface) wrapped); } - /** - * Offer to locally truncate the given file when opened using the write-only - * mode. This is typically used to preserve legacy compatibility behavior. - */ - private static void maybeTruncate(FileDescriptor fd, String mode) throws FileNotFoundException { - if ("w".equals(mode)) { - try { - Os.ftruncate(fd, 0); - } catch (ErrnoException e) { - throw new FileNotFoundException("Failed to truncate: " + e.getMessage()); - } - } - } - /** @hide */ @SuppressWarnings("HiddenAbstractMethod") @UnsupportedAppUsage @@ -1543,20 +1525,8 @@ public abstract class ContentResolver implements ContentInterface { } /** - * Open a stream on to the content associated with a content URI. If there - * is no data associated with the URI, FileNotFoundException is thrown. - * - * <h5>Accepts the following URI schemes:</h5> - * <ul> - * <li>content ({@link #SCHEME_CONTENT})</li> - * <li>file ({@link #SCHEME_FILE})</li> - * </ul> - * - * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information - * on these schemes. - * - * <p>This method behaves like {@link FileOutputStream} and automatically - * truncates any existing contents. + * Synonym for {@link #openOutputStream(Uri, String) + * openOutputStream(uri, "w")}. * * @param uri The desired URI. * @return an OutputStream or {@code null} if the provider recently crashed. @@ -1564,16 +1534,7 @@ public abstract class ContentResolver implements ContentInterface { */ public final @Nullable OutputStream openOutputStream(@NonNull Uri uri) throws FileNotFoundException { - AssetFileDescriptor fd = openAssetFileDescriptor(uri, "w", null); - if (fd == null) return null; - try { - final FileOutputStream res = fd.createOutputStream(); - // Unconditionally truncate to mirror FileOutputStream behavior - maybeTruncate(res.getFD(), "w"); - return res; - } catch (IOException e) { - throw new FileNotFoundException("Unable to create stream"); - } + return openOutputStream(uri, "w"); } /** @@ -1590,9 +1551,7 @@ public abstract class ContentResolver implements ContentInterface { * on these schemes. * * @param uri The desired URI. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode May be "w", "wa", "rw", or "rwt". * @return an OutputStream or {@code null} if the provider recently crashed. * @throws FileNotFoundException if the provided URI could not be opened. * @see #openAssetFileDescriptor(Uri, String) @@ -1600,14 +1559,8 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null); - if (fd == null) return null; try { - final FileOutputStream res = fd.createOutputStream(); - // Preserve legacy behavior by offering to truncate - if (mTargetSdkVersion < Build.VERSION_CODES.Q) { - maybeTruncate(res.getFD(), mode); - } - return res; + return fd != null ? fd.createOutputStream() : null; } catch (IOException e) { throw new FileNotFoundException("Unable to create stream"); } @@ -1654,9 +1607,8 @@ public abstract class ContentResolver implements ContentInterface { * provider, use {@link ParcelFileDescriptor#closeWithError(String)}. * * @param uri The desired URI to open. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode The file mode to use, as per {@link ContentProvider#openFile + * ContentProvider.openFile}. * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the * provider recently crashed. You own this descriptor and are responsible for closing it * when done. @@ -1698,9 +1650,8 @@ public abstract class ContentResolver implements ContentInterface { * provider, use {@link ParcelFileDescriptor#closeWithError(String)}. * * @param uri The desired URI to open. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode The file mode to use, as per {@link ContentProvider#openFile + * ContentProvider.openFile}. * @param cancellationSignal A signal to cancel the operation in progress, * or null if none. If the operation is canceled, then * {@link OperationCanceledException} will be thrown. @@ -1793,9 +1744,8 @@ public abstract class ContentResolver implements ContentInterface { * from any built-in data conversion that a provider implements. * * @param uri The desired URI to open. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile + * ContentProvider.openAssetFile}. * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the * provider recently crashed. You own this descriptor and are responsible for closing it * when done. @@ -1848,9 +1798,8 @@ public abstract class ContentResolver implements ContentInterface { * from any built-in data conversion that a provider implements. * * @param uri The desired URI to open. - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". See - * {@link ParcelFileDescriptor#parseMode} for more details. + * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile + * ContentProvider.openAssetFile}. * @param cancellationSignal A signal to cancel the operation in progress, or null if * none. If the operation is canceled, then * {@link OperationCanceledException} will be thrown. @@ -1886,10 +1835,6 @@ public abstract class ContentResolver implements ContentInterface { } else if (SCHEME_FILE.equals(scheme)) { ParcelFileDescriptor pfd = ParcelFileDescriptor.open( new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode)); - // Preserve legacy behavior by offering to truncate - if (mTargetSdkVersion < Build.VERSION_CODES.Q) { - maybeTruncate(pfd.getFileDescriptor(), mode); - } return new AssetFileDescriptor(pfd, 0, -1); } else { if ("r".equals(mode)) { @@ -1947,11 +1892,6 @@ public abstract class ContentResolver implements ContentInterface { // ParcelFileDescriptorInner do that when it is closed. stableProvider = null; - // Preserve legacy behavior by offering to truncate - if (mTargetSdkVersion < Build.VERSION_CODES.Q) { - maybeTruncate(pfd.getFileDescriptor(), mode); - } - return new AssetFileDescriptor(pfd, fd.getStartOffset(), fd.getDeclaredLength()); diff --git a/core/java/android/content/pm/ApkChecksum.java b/core/java/android/content/pm/ApkChecksum.java index eca48eca9e4b..d550f411f6f7 100644 --- a/core/java/android/content/pm/ApkChecksum.java +++ b/core/java/android/content/pm/ApkChecksum.java @@ -118,7 +118,7 @@ public final class ApkChecksum implements Parcelable { - // Code below generated by codegen v1.0.15. + // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -235,8 +235,8 @@ public final class ApkChecksum implements Parcelable { }; @DataClass.Generated( - time = 1601589269293L, - codegenVersion = "1.0.15", + time = 1619810171079L, + codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/ApkChecksum.java", inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mInstallerPackageName\nprivate final @android.annotation.Nullable byte[] mInstallerCertificate\npublic @android.content.pm.Checksum.Type int getType()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getInstallerCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getInstallerCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)") @Deprecated diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index e302f9e404fb..a3e0473e39cc 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -2141,22 +2141,57 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } /** + * Use default value for + * {@link android.R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess}. + */ + public static final int RAW_EXTERNAL_STORAGE_ACCESS_DEFAULT = 0; + + /** + * Raw external storage was requested by this app. + */ + public static final int RAW_EXTERNAL_STORAGE_ACCESS_REQUESTED = 1; + + /** + * Raw external storage was not requested by this app. + */ + public static final int RAW_EXTERNAL_STORAGE_ACCESS_NOT_REQUESTED = 2; + + /** + * These constants need to match the value of + * {@link android.R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess}. + * in application manifest. + * @hide + */ + @IntDef(prefix = {"RAW_EXTERNAL_STORAGE_"}, value = { + RAW_EXTERNAL_STORAGE_ACCESS_DEFAULT, + RAW_EXTERNAL_STORAGE_ACCESS_REQUESTED, + RAW_EXTERNAL_STORAGE_ACCESS_NOT_REQUESTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RawExternalStorage {} + + /** * @return * <ul> - * <li>{@code true} if this app requested raw external storage access - * <li>{@code false} if this app requests to disable raw external storage access. - * <li>{@code null} if the app didn't specify + * <li>{@link ApplicationInfo#RAW_EXTERNAL_STORAGE_ACCESS_DEFAULT} if app didn't specify * {@link android.R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess} - * in its manifest file. - * </ul> - * - * @hide + * attribute in the manifest. + * <li>{@link ApplicationInfo#RAW_EXTERNAL_STORAGE_ACCESS_REQUESTED} if this app requested raw + * external storage access. + * <li>{@link ApplicationInfo#RAW_EXTERNAL_STORAGE_ACCESS_NOT_REQUESTED} if this app requests to + * disable raw external storage access + * </ul + * <p> + * Note that this doesn't give any hints on whether the app gets raw external storage access or + * not. Also, apps may get raw external storage access by default in some cases, see + * {@link android.R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess}. */ - @SuppressWarnings("AutoBoxing") - @SystemApi - @Nullable - public Boolean hasRequestRawExternalStorageAccess() { - return requestRawExternalStorageAccess; + public @RawExternalStorage int getRequestRawExternalStorageAccess() { + if (requestRawExternalStorageAccess == null) { + return RAW_EXTERNAL_STORAGE_ACCESS_DEFAULT; + } + return requestRawExternalStorageAccess ? RAW_EXTERNAL_STORAGE_ACCESS_REQUESTED + : RAW_EXTERNAL_STORAGE_ACCESS_NOT_REQUESTED; } /** diff --git a/core/java/android/content/pm/Checksum.java b/core/java/android/content/pm/Checksum.java index 4f4898af278b..ff17496c7457 100644 --- a/core/java/android/content/pm/Checksum.java +++ b/core/java/android/content/pm/Checksum.java @@ -113,7 +113,7 @@ public final class Checksum implements Parcelable { public static final int TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512 = 0x00000040; /** @hide */ - @IntDef(flag = true, prefix = {"TYPE_"}, value = { + @IntDef(prefix = {"TYPE_"}, value = { TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, TYPE_WHOLE_MD5, TYPE_WHOLE_SHA1, @@ -125,6 +125,19 @@ public final class Checksum implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface Type {} + /** @hide */ + @IntDef(flag = true, prefix = {"TYPE_"}, value = { + TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, + TYPE_WHOLE_MD5, + TYPE_WHOLE_SHA1, + TYPE_WHOLE_SHA256, + TYPE_WHOLE_SHA512, + TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256, + TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TypeMask {} + /** * Serialize checksum to the stream in binary format. * @hide @@ -163,7 +176,7 @@ public final class Checksum implements Parcelable { - // Code below generated by codegen v1.0.22. + // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -263,8 +276,8 @@ public final class Checksum implements Parcelable { }; @DataClass.Generated( - time = 1611601571576L, - codegenVersion = "1.0.22", + time = 1619810358402L, + codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/Checksum.java", inputSignatures = "public static final int TYPE_WHOLE_MERKLE_ROOT_4K_SHA256\npublic static final @java.lang.Deprecated int TYPE_WHOLE_MD5\npublic static final @java.lang.Deprecated int TYPE_WHOLE_SHA1\npublic static final @java.lang.Deprecated int TYPE_WHOLE_SHA256\npublic static final @java.lang.Deprecated int TYPE_WHOLE_SHA512\npublic static final int TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256\npublic static final int TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512\nprivate final @android.content.pm.Checksum.Type int mType\nprivate final @android.annotation.NonNull byte[] mValue\npublic static void writeToStream(java.io.DataOutputStream,android.content.pm.Checksum)\npublic static @android.annotation.NonNull android.content.pm.Checksum readFromStream(java.io.DataInputStream)\nclass Checksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstDefs=false)") @Deprecated diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 07d8478da553..a1d419e82174 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -8711,7 +8711,7 @@ public abstract class PackageManager { * @throws NameNotFoundException if a package with the given name cannot be found on the system. */ public void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int required, @NonNull List<Certificate> trustedInstallers, + @Checksum.TypeMask int required, @NonNull List<Certificate> trustedInstallers, @NonNull OnChecksumsReadyListener onChecksumsReadyListener) throws CertificateEncodingException, NameNotFoundException { throw new UnsupportedOperationException("requestChecksums not implemented in subclass"); diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 22d75ef93137..725576fda389 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -3069,6 +3069,13 @@ public class ParsingPackageUtils { /** * @hide */ + public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) { + sCompatibilityModeEnabled = compatibilityModeEnabled; + } + + /** + * @hide + */ public static void readConfigUseRoundIcon(Resources r) { if (r != null) { sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon); diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java index bcf41cce7e7c..449e3aeb6be6 100644 --- a/core/java/android/os/AggregateBatteryConsumer.java +++ b/core/java/android/os/AggregateBatteryConsumer.java @@ -25,17 +25,22 @@ import android.annotation.NonNull; */ public final class AggregateBatteryConsumer extends BatteryConsumer implements Parcelable { + private final double mConsumedPowerMah; + public AggregateBatteryConsumer(@NonNull Builder builder) { super(builder.mPowerComponentsBuilder.build()); + mConsumedPowerMah = builder.mConsumedPowerMah; } private AggregateBatteryConsumer(@NonNull Parcel source) { super(new PowerComponents(source)); + mConsumedPowerMah = source.readDouble(); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); + dest.writeDouble(mConsumedPowerMah); } @Override @@ -55,15 +60,30 @@ public final class AggregateBatteryConsumer extends BatteryConsumer implements P } }; + @Override + public double getConsumedPower() { + return mConsumedPowerMah; + } + /** * Builder for DeviceBatteryConsumer. */ public static final class Builder extends BaseBuilder<AggregateBatteryConsumer.Builder> { + private double mConsumedPowerMah; + public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) { super(customPowerComponentNames, includePowerModels); } /** + * Sets the total power included in this aggregate. + */ + public Builder setConsumedPower(double consumedPowerMah) { + mConsumedPowerMah = consumedPowerMah; + return this; + } + + /** * Creates a read-only object out of the Builder values. */ @NonNull diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 9ec6938de271..eec6810fa8bc 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -3234,6 +3234,11 @@ public abstract class BatteryStats implements Parcelable { public abstract int getMaxLearnedBatteryCapacity() ; /** + * @return The latest learned battery capacity in uAh. + */ + public abstract int getLearnedBatteryCapacity(); + + /** * Return the array of discharge step durations. */ public abstract LevelStepTracker getDischargeLevelStepTracker(); @@ -3925,7 +3930,9 @@ public abstract class BatteryStats implements Parcelable { getStartClockTime(), whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000, getEstimatedBatteryCapacity(), - getMinLearnedBatteryCapacity(), getMaxLearnedBatteryCapacity(), + getLearnedBatteryCapacity(), + getMinLearnedBatteryCapacity(), + getMaxLearnedBatteryCapacity(), screenDozeTime / 1000); @@ -4688,22 +4695,31 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + final int lastLearnedBatteryCapacity = getLearnedBatteryCapacity(); + if (lastLearnedBatteryCapacity > 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Last learned battery capacity: "); + sb.append(BatteryStatsHelper.makemAh(lastLearnedBatteryCapacity / 1000)); + sb.append(" mAh"); + pw.println(sb.toString()); + } final int minLearnedBatteryCapacity = getMinLearnedBatteryCapacity(); if (minLearnedBatteryCapacity > 0) { sb.setLength(0); sb.append(prefix); - sb.append(" Min learned battery capacity: "); - sb.append(BatteryStatsHelper.makemAh(minLearnedBatteryCapacity / 1000)); - sb.append(" mAh"); + sb.append(" Min learned battery capacity: "); + sb.append(BatteryStatsHelper.makemAh(minLearnedBatteryCapacity / 1000)); + sb.append(" mAh"); pw.println(sb.toString()); } final int maxLearnedBatteryCapacity = getMaxLearnedBatteryCapacity(); if (maxLearnedBatteryCapacity > 0) { sb.setLength(0); sb.append(prefix); - sb.append(" Max learned battery capacity: "); - sb.append(BatteryStatsHelper.makemAh(maxLearnedBatteryCapacity / 1000)); - sb.append(" mAh"); + sb.append(" Max learned battery capacity: "); + sb.append(BatteryStatsHelper.makemAh(maxLearnedBatteryCapacity / 1000)); + sb.append(" mAh"); pw.println(sb.toString()); } diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index e3af4834c341..6bc861f87e48 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -71,7 +71,6 @@ public final class BatteryUsageStats implements Parcelable { public static final int AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT = 2; - private final double mConsumedPower; private final int mDischargePercentage; private final long mStatsStartTimestampMs; private final double mDischargedPowerLowerBound; @@ -80,7 +79,6 @@ public final class BatteryUsageStats implements Parcelable { private final long mChargeTimeRemainingMs; private final String[] mCustomPowerComponentNames; private final List<UidBatteryConsumer> mUidBatteryConsumers; - private final List<SystemBatteryConsumer> mSystemBatteryConsumers; private final List<UserBatteryConsumer> mUserBatteryConsumers; private final AggregateBatteryConsumer[] mAggregateBatteryConsumers; private final Parcel mHistoryBuffer; @@ -97,14 +95,7 @@ public final class BatteryUsageStats implements Parcelable { mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs; mCustomPowerComponentNames = builder.mCustomPowerComponentNames; - mAggregateBatteryConsumers = - new AggregateBatteryConsumer[AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT]; - for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) { - mAggregateBatteryConsumers[i] = builder.mAggregateBatteryConsumersBuilders[i].build(); - } - - double totalPower = 0; - + double totalPowerMah = 0; final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size(); mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount); for (int i = 0; i < uidBatteryConsumerCount; i++) { @@ -112,30 +103,28 @@ public final class BatteryUsageStats implements Parcelable { builder.mUidBatteryConsumerBuilders.valueAt(i); if (!uidBatteryConsumerBuilder.isExcludedFromBatteryUsageStats()) { final UidBatteryConsumer consumer = uidBatteryConsumerBuilder.build(); - totalPower += consumer.getConsumedPower(); + totalPowerMah += consumer.getConsumedPower(); mUidBatteryConsumers.add(consumer); } } - final int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size(); - mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount); - for (int i = 0; i < systemBatteryConsumerCount; i++) { - final SystemBatteryConsumer consumer = - builder.mSystemBatteryConsumerBuilders.valueAt(i).build(); - totalPower += consumer.getConsumedPower() - consumer.getPowerConsumedByApps(); - mSystemBatteryConsumers.add(consumer); - } - final int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size(); mUserBatteryConsumers = new ArrayList<>(userBatteryConsumerCount); for (int i = 0; i < userBatteryConsumerCount; i++) { final UserBatteryConsumer consumer = builder.mUserBatteryConsumerBuilders.valueAt(i).build(); - totalPower += consumer.getConsumedPower(); + totalPowerMah += consumer.getConsumedPower(); mUserBatteryConsumers.add(consumer); } - mConsumedPower = totalPower; + builder.getAggregateBatteryConsumerBuilder(AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) + .setConsumedPower(totalPowerMah); + + mAggregateBatteryConsumers = + new AggregateBatteryConsumer[AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT]; + for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) { + mAggregateBatteryConsumers[i] = builder.mAggregateBatteryConsumersBuilders[i].build(); + } } /** @@ -147,6 +136,15 @@ public final class BatteryUsageStats implements Parcelable { } /** + * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully + * charged), in mAh + */ + public double getConsumedPower() { + return mAggregateBatteryConsumers[AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE] + .getConsumedPower(); + } + + /** * Portion of battery charge drained since BatteryStats reset (e.g. due to being fully * charged), as percentage of the full charge in the range [0:100] */ @@ -182,14 +180,6 @@ public final class BatteryUsageStats implements Parcelable { } /** - * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully - * charged), in mAh - */ - public double getConsumedPower() { - return mConsumedPower; - } - - /** * Returns a battery consumer for the specified battery consumer type. */ public BatteryConsumer getAggregateBatteryConsumer( @@ -203,11 +193,6 @@ public final class BatteryUsageStats implements Parcelable { } @NonNull - public List<SystemBatteryConsumer> getSystemBatteryConsumers() { - return mSystemBatteryConsumers; - } - - @NonNull public List<UserBatteryConsumer> getUserBatteryConsumers() { return mUserBatteryConsumers; } @@ -232,7 +217,6 @@ public final class BatteryUsageStats implements Parcelable { private BatteryUsageStats(@NonNull Parcel source) { mStatsStartTimestampMs = source.readLong(); - mConsumedPower = source.readDouble(); mDischargePercentage = source.readInt(); mDischargedPowerLowerBound = source.readDouble(); mDischargedPowerUpperBound = source.readDouble(); @@ -254,14 +238,6 @@ public final class BatteryUsageStats implements Parcelable { consumer.setCustomPowerComponentNames(mCustomPowerComponentNames); mUidBatteryConsumers.add(consumer); } - int sysCount = source.readInt(); - mSystemBatteryConsumers = new ArrayList<>(sysCount); - for (int i = 0; i < sysCount; i++) { - final SystemBatteryConsumer consumer = - SystemBatteryConsumer.CREATOR.createFromParcel(source); - consumer.setCustomPowerComponentNames(mCustomPowerComponentNames); - mSystemBatteryConsumers.add(consumer); - } int userCount = source.readInt(); mUserBatteryConsumers = new ArrayList<>(userCount); for (int i = 0; i < userCount; i++) { @@ -298,7 +274,6 @@ public final class BatteryUsageStats implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeLong(mStatsStartTimestampMs); - dest.writeDouble(mConsumedPower); dest.writeInt(mDischargePercentage); dest.writeDouble(mDischargedPowerLowerBound); dest.writeDouble(mDischargedPowerUpperBound); @@ -312,10 +287,6 @@ public final class BatteryUsageStats implements Parcelable { for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) { mUidBatteryConsumers.get(i).writeToParcel(dest, flags); } - dest.writeInt(mSystemBatteryConsumers.size()); - for (int i = mSystemBatteryConsumers.size() - 1; i >= 0; i--) { - mSystemBatteryConsumers.get(i).writeToParcel(dest, flags); - } dest.writeInt(mUserBatteryConsumers.size()); for (int i = mUserBatteryConsumers.size() - 1; i >= 0; i--) { mUserBatteryConsumers.get(i).writeToParcel(dest, flags); @@ -367,8 +338,6 @@ public final class BatteryUsageStats implements Parcelable { new AggregateBatteryConsumer.Builder[AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT]; private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders = new SparseArray<>(); - private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders = - new SparseArray<>(); private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders = new SparseArray<>(); private Parcel mHistoryBuffer; @@ -483,22 +452,6 @@ public final class BatteryUsageStats implements Parcelable { } /** - * Creates or returns a SystemBatteryConsumer, which represents battery attribution - * data for a specific drain type. - */ - @NonNull - public SystemBatteryConsumer.Builder getOrCreateSystemBatteryConsumerBuilder( - @SystemBatteryConsumer.DrainType int drainType) { - SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType); - if (builder == null) { - builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentNames, - mIncludePowerModels, drainType); - mSystemBatteryConsumerBuilders.put(drainType, builder); - } - return builder; - } - - /** * Creates or returns a UserBatteryConsumer, which represents battery attribution * data for an individual {@link UserHandle}. */ diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index a06a8577a56a..f3e0ce9cd19e 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1470,7 +1470,7 @@ public final class FileUtils { return MediaStore.getOriginalMediaFormatFileDescriptor(context, ParcelFileDescriptor.dup(fd)); } catch (Exception e) { - Log.w(TAG, "Failed to convert to modern format file descriptor", e); + Log.d(TAG, "Failed to convert to modern format file descriptor", e); return null; } } diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 0c9ad1b17a7e..c0847872a45a 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -31,7 +31,6 @@ import static android.system.OsConstants.S_ISLNK; import static android.system.OsConstants.S_ISREG; import static android.system.OsConstants.S_IWOTH; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -64,8 +63,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InterruptedIOException; import java.io.UncheckedIOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.net.DatagramSocket; import java.net.Socket; import java.nio.ByteOrder; @@ -113,20 +110,6 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { private final CloseGuard mGuard = CloseGuard.get(); - /** @hide */ - @IntDef(prefix = {"MODE_"}, value = { - MODE_WORLD_READABLE, - MODE_WORLD_WRITEABLE, - MODE_READ_ONLY, - MODE_WRITE_ONLY, - MODE_READ_WRITE, - MODE_CREATE, - MODE_TRUNCATE, - MODE_APPEND, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface Mode { } - /** * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and * this file doesn't already exist, then create the file with permissions @@ -244,8 +227,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { * be opened with the requested mode. * @see #parseMode(String) */ - public static ParcelFileDescriptor open(File file, @Mode int mode) - throws FileNotFoundException { + public static ParcelFileDescriptor open(File file, int mode) throws FileNotFoundException { final FileDescriptor fd = openInternal(file, mode); if (fd == null) return null; @@ -277,7 +259,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { // We can't accept a generic Executor here, since we need to use // MessageQueue.addOnFileDescriptorEventListener() @SuppressLint("ExecutorRegistration") - public static ParcelFileDescriptor open(File file, @Mode int mode, Handler handler, + public static ParcelFileDescriptor open(File file, int mode, Handler handler, final OnCloseListener listener) throws IOException { if (handler == null) { throw new IllegalArgumentException("Handler must not be null"); @@ -348,8 +330,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { return pfd; } - private static FileDescriptor openInternal(File file, @Mode int mode) - throws FileNotFoundException { + private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException { final int flags = FileUtils.translateModePfdToPosix(mode) | ifAtLeastQ(O_CLOEXEC); int realMode = S_IRWXU | S_IRWXG; @@ -642,36 +623,15 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { } /** - * Converts a string representing a file mode, such as "rw", into a bitmask - * suitable for use with {@link #open}. + * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use + * with {@link #open}. * <p> - * The argument must define at least one of the following base access modes: - * <ul> - * <li>"r" indicates the file should be opened in read-only mode, equivalent - * to {@link OsConstants#O_RDONLY}. - * <li>"w" indicates the file should be opened in write-only mode, - * equivalent to {@link OsConstants#O_WRONLY}. - * <li>"rw" indicates the file should be opened in read-write mode, - * equivalent to {@link OsConstants#O_RDWR}. - * </ul> - * In addition to a base access mode, the following additional modes may - * requested: - * <ul> - * <li>"a" indicates the file should be opened in append mode, equivalent to - * {@link OsConstants#O_APPEND}. Before each write, the file offset is - * positioned at the end of the file. - * <li>"t" indicates the file should be opened in truncate mode, equivalent - * to {@link OsConstants#O_TRUNC}. If the file already exists and is a - * regular file and is opened for writing, it will be truncated to length 0. - * </ul> - * - * @param mode The string representation of the file mode. Can be "r", "w", - * "wt", "wa", "rw" or "rwt". + * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" + * or "rwt". * @return A bitmask representing the given file mode. - * @throws IllegalArgumentException if the given string does not match a - * known file mode. + * @throws IllegalArgumentException if the given string does not match a known file mode. */ - public static @Mode int parseMode(String mode) { + public static int parseMode(String mode) { return FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode)); } diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java deleted file mode 100644 index 7618339260bd..000000000000 --- a/core/java/android/os/SystemBatteryConsumer.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.util.Slog; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; - - -/** - * Contains power consumption data attributed to a system-wide drain type. - * - * {@hide} - */ -public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable { - private static final String TAG = "SystemBatteryConsumer"; - - // **************** - // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto) - // so the constant values must never change. - // **************** - @IntDef(prefix = {"DRAIN_TYPE_"}, value = { - DRAIN_TYPE_AMBIENT_DISPLAY, - // Reserved: APP - DRAIN_TYPE_BLUETOOTH, - DRAIN_TYPE_CAMERA, - DRAIN_TYPE_MOBILE_RADIO, - DRAIN_TYPE_FLASHLIGHT, - DRAIN_TYPE_IDLE, - DRAIN_TYPE_MEMORY, - // Reserved: OVERCOUNTED, - DRAIN_TYPE_PHONE, - DRAIN_TYPE_SCREEN, - // Reserved: UNACCOUNTED, - // Reserved: USER, - DRAIN_TYPE_WIFI, - DRAIN_TYPE_CUSTOM, - }) - @Retention(RetentionPolicy.SOURCE) - public static @interface DrainType { - } - - public static final int DRAIN_TYPE_AMBIENT_DISPLAY = 0; - public static final int DRAIN_TYPE_BLUETOOTH = 2; - public static final int DRAIN_TYPE_CAMERA = 3; - public static final int DRAIN_TYPE_MOBILE_RADIO = 4; - public static final int DRAIN_TYPE_FLASHLIGHT = 5; - public static final int DRAIN_TYPE_IDLE = 6; - public static final int DRAIN_TYPE_MEMORY = 7; - public static final int DRAIN_TYPE_PHONE = 9; - public static final int DRAIN_TYPE_SCREEN = 10; - public static final int DRAIN_TYPE_WIFI = 13; - public static final int DRAIN_TYPE_CUSTOM = 14; - - @DrainType - private final int mDrainType; - - private final double mPowerConsumedByAppsMah; - - @DrainType - public int getDrainType() { - return mDrainType; - } - - private SystemBatteryConsumer(@NonNull SystemBatteryConsumer.Builder builder) { - super(builder.mPowerComponentsBuilder.build()); - mDrainType = builder.mDrainType; - mPowerConsumedByAppsMah = builder.mPowerConsumedByAppsMah; - if (mPowerConsumedByAppsMah > getConsumedPower()) { - Slog.wtf(TAG, - "Power attributed to apps exceeds total: drain type = " + mDrainType - + " total consumed power = " + getConsumedPower() - + " power consumed by apps = " + mPowerConsumedByAppsMah); - } - } - - private SystemBatteryConsumer(Parcel in) { - super(new PowerComponents(in)); - mDrainType = in.readInt(); - mPowerConsumedByAppsMah = in.readDouble(); - } - - public double getPowerConsumedByApps() { - return mPowerConsumedByAppsMah; - } - - /** - * Returns the amount of time this consumer was operating. - */ - public long getUsageDurationMillis() { - return mPowerComponents.getMaxComponentUsageDurationMillis(); - } - - /** - * Writes the contents into a Parcel. - */ - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(mDrainType); - dest.writeDouble(mPowerConsumedByAppsMah); - } - - public static final Creator<SystemBatteryConsumer> CREATOR = - new Creator<SystemBatteryConsumer>() { - @Override - public SystemBatteryConsumer createFromParcel(Parcel in) { - return new SystemBatteryConsumer(in); - } - - @Override - public SystemBatteryConsumer[] newArray(int size) { - return new SystemBatteryConsumer[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - /** - * Builder for SystemBatteryConsumer. - */ - public static final class Builder extends BaseBuilder<Builder> { - @DrainType - private final int mDrainType; - private double mPowerConsumedByAppsMah; - private List<UidBatteryConsumer.Builder> mUidBatteryConsumers; - - Builder(@NonNull String[] customPowerComponentNames, - boolean includePowerModels, @DrainType int drainType) { - super(customPowerComponentNames, includePowerModels); - mDrainType = drainType; - } - - /** - * Sets the amount of power used by this system component that is attributed to apps. - * It should not exceed the total consumed power. - */ - public Builder setPowerConsumedByApps(double powerConsumedByAppsMah) { - mPowerConsumedByAppsMah = powerConsumedByAppsMah; - return this; - } - - /** - * Add a UidBatteryConsumer to this SystemBatteryConsumer. For example, - * the UidBatteryConsumer with the UID == {@link Process#BLUETOOTH_UID} should - * be added to the SystemBatteryConsumer with the drain type == {@link - * #DRAIN_TYPE_BLUETOOTH}. - * <p> - * Calculated power and duration components of the added battery consumers - * are aggregated at the time the SystemBatteryConsumer is built by the {@link #build()} - * method. - * </p> - */ - public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) { - if (mUidBatteryConsumers == null) { - mUidBatteryConsumers = new ArrayList<>(); - } - mUidBatteryConsumers.add(uidBatteryConsumerBuilder); - } - - /** - * Creates a read-only object out of the Builder values. - */ - @NonNull - public SystemBatteryConsumer build() { - if (mUidBatteryConsumers != null) { - for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) { - UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i); - mPowerComponentsBuilder.addPowerAndDuration( - uidBatteryConsumer.mPowerComponentsBuilder); - } - } - return new SystemBatteryConsumer(this); - } - } -} diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 7af8f71aa4aa..bf0b655fe574 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.NonNull; import android.annotation.TestApi; import android.util.Slog; @@ -112,6 +113,15 @@ public class VintfObject { public static native String getSepolicyVersion(); /** + * @return the PLATFORM_SEPOLICY_VERSION build flag available in framework + * compatibility matrix. + * + * @hide + */ + @TestApi + public static native @NonNull String getPlatformSepolicyVersion(); + + /** * @return a list of VNDK snapshots supported by the framework, as * specified in framework manifest. For example, * [("27", ["libjpeg.so", "libbase.so"]), diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java index f6d525c10cc9..3cffeb0578d4 100644 --- a/core/java/android/view/FrameMetrics.java +++ b/core/java/android/view/FrameMetrics.java @@ -16,6 +16,8 @@ package android.view; +import static android.graphics.FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED; + import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; @@ -172,8 +174,6 @@ public final class FrameMetrics { **/ public static final int DEADLINE = 13; - private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0; - /** * Identifiers for metrics available for each frame. * @@ -343,7 +343,7 @@ public final class FrameMetrics { } if (id == FIRST_DRAW_FRAME) { - return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0; + return (mTimingData[Index.FLAGS] & FLAG_WINDOW_VISIBILITY_CHANGED) != 0 ? 1 : 0; } else if (id == INTENDED_VSYNC_TIMESTAMP) { return mTimingData[Index.INTENDED_VSYNC]; } else if (id == VSYNC_TIMESTAMP) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 0958f3fbd771..a06f193255b2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2764,7 +2764,9 @@ public final class ViewRootImpl implements ViewParent, // to resume them mDirty.set(0, 0, mWidth, mHeight); } - mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED; + } + if (mFirst || viewVisibilityChanged) { + mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED; } relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); final boolean freeformResizing = (relayoutResult diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index 541b4941c62e..7726086a4787 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -315,6 +315,8 @@ public final class UiTranslationManager { private static class UiTranslationStateRemoteCallback extends IRemoteCallback.Stub { private final Executor mExecutor; private final UiTranslationStateCallback mCallback; + private ULocale mSourceLocale; + private ULocale mTargetLocale; UiTranslationStateRemoteCallback(Executor executor, UiTranslationStateCallback callback) { @@ -331,10 +333,12 @@ public final class UiTranslationManager { int state = bundle.getInt(EXTRA_STATE); switch (state) { case STATE_UI_TRANSLATION_STARTED: + mSourceLocale = (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE); + mTargetLocale = (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE); + mCallback.onStarted(mSourceLocale, mTargetLocale); + break; case STATE_UI_TRANSLATION_RESUMED: - mCallback.onStarted( - (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE), - (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE)); + mCallback.onStarted(mSourceLocale, mTargetLocale); break; case STATE_UI_TRANSLATION_PAUSED: mCallback.onPaused(); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index eb16cef15248..b3f848b4cf22 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -6614,27 +6614,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** - * Returns the {@link EdgeEffect#getType()} for the edge effects. - * @return the {@link EdgeEffect#getType()} for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - @EdgeEffect.EdgeEffectType - public int getEdgeEffectType() { - return mEdgeGlowTop.getType(); - } - - /** - * Sets the {@link EdgeEffect#setType(int)} for the edge effects. - * @param type The edge effect type to use for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) { - mEdgeGlowTop.setType(type); - mEdgeGlowBottom.setType(type); - invalidate(); - } - - /** * Sets the recycler listener to be notified whenever a View is set aside in * the recycler for later reuse. This listener can be used to free resources * associated to the View. diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java index 4d2d9e86f1a6..c11344ebaece 100644 --- a/core/java/android/widget/EdgeEffect.java +++ b/core/java/android/widget/EdgeEffect.java @@ -62,9 +62,7 @@ import java.lang.annotation.RetentionPolicy; */ public class EdgeEffect { /** - * This sets the default value for {@link #setType(int)} to {@link #TYPE_STRETCH} instead - * of {@link #TYPE_GLOW}. The type can still be overridden by the theme, view attribute, - * or by calling {@link #setType(int)}. + * This sets the edge effect to use stretch instead of glow. * * @hide */ @@ -73,34 +71,19 @@ public class EdgeEffect { public static final long USE_STRETCH_EDGE_EFFECT_BY_DEFAULT = 171228096L; /** - * This sets the default value for {@link #setType(int)} to {@link #TYPE_STRETCH} instead - * of {@link #TYPE_GLOW} for views that instantiate with - * {@link #EdgeEffect(Context, AttributeSet)}, indicating use of S+ EdgeEffect support. The - * type can still be overridden by the theme, view attribute, or by calling - * {@link #setType(int)}. - * - * @hide - */ - @ChangeId - @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) - public static final long USE_STRETCH_EDGE_EFFECT_FOR_SUPPORTED = 178807038L; - - /** * The default blend mode used by {@link EdgeEffect}. */ public static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_ATOP; /** - * Use a color edge glow for the edge effect. From XML, use - * <code>android:edgeEffectType="glow"</code>. + * Use a color edge glow for the edge effect. */ - public static final int TYPE_GLOW = 0; + private static final int TYPE_GLOW = 0; /** - * Use a stretch for the edge effect. From XML, use - * <code>android:edgeEffectType="stretch"</code>. + * Use a stretch for the edge effect. */ - public static final int TYPE_STRETCH = 1; + private static final int TYPE_STRETCH = 1; /** * The velocity threshold before the spring animation is considered settled. @@ -221,7 +204,7 @@ public class EdgeEffect { * @param context Context used to provide theming and resource information for the EdgeEffect */ public EdgeEffect(Context context) { - this(context, null, Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_BY_DEFAULT)); + this(context, null); } /** @@ -230,20 +213,12 @@ public class EdgeEffect { * @param attrs The attributes of the XML tag that is inflating the view */ public EdgeEffect(@NonNull Context context, @Nullable AttributeSet attrs) { - this(context, attrs, - Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_BY_DEFAULT) - || Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_FOR_SUPPORTED)); - } - - private EdgeEffect(@NonNull Context context, @Nullable AttributeSet attrs, - boolean defaultStretch) { final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.EdgeEffect); final int themeColor = a.getColor( com.android.internal.R.styleable.EdgeEffect_colorEdgeEffect, 0xff666666); - mEdgeEffectType = a.getInt( - com.android.internal.R.styleable.EdgeEffect_edgeEffectType, - defaultStretch ? TYPE_STRETCH : TYPE_GLOW); + mEdgeEffectType = Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_BY_DEFAULT) + ? TYPE_STRETCH : TYPE_GLOW; a.recycle(); mPaint.setAntiAlias(true); @@ -467,7 +442,6 @@ public class EdgeEffect { if (mEdgeEffectType == TYPE_STRETCH) { mState = STATE_RECEDE; mVelocity = velocity * ON_ABSORB_VELOCITY_ADJUSTMENT; - mDistance = 0; mStartTime = AnimationUtils.currentAnimationTimeMillis(); } else { mState = STATE_ABSORB; @@ -506,17 +480,6 @@ public class EdgeEffect { } /** - * Sets the edge effect type to use. The default without a theme attribute set is - * {@link EdgeEffect#TYPE_GLOW}. - * - * @param type The edge effect type to use. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public void setType(@EdgeEffectType int type) { - mEdgeEffectType = type; - } - - /** * Set or clear the blend mode. A blend mode defines how source pixels * (generated by a drawing command) are composited with the destination pixels * (content of the render target). @@ -542,16 +505,6 @@ public class EdgeEffect { } /** - * Return the edge effect type to use. - * - * @return The edge effect type to use. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public @EdgeEffectType int getType() { - return mEdgeEffectType; - } - - /** * Returns the blend mode. A blend mode defines how source pixels * (generated by a drawing command) are composited with the destination pixels * (content of the render target). @@ -568,7 +521,7 @@ public class EdgeEffect { * Draw into the provided canvas. Assumes that the canvas has been rotated * accordingly and the size has been set. The effect will be drawn the full * width of X=0 to X=width, beginning from Y=0 and extending to some factor < - * 1.f of height. The {@link #TYPE_STRETCH} effect will only be visible on a + * 1.f of height. The effect will only be visible on a * hardware canvas, e.g. {@link RenderNode#beginRecording()}. * * @param canvas Canvas to draw into @@ -686,7 +639,7 @@ public class EdgeEffect { * @return The maximum height of the edge effect */ public int getMaxHeight() { - return (int) (mBounds.height() * MAX_GLOW_SCALE + 0.5f); + return (int) mHeight; } private void update() { diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index e41893e37103..018cba7f95e5 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -308,27 +308,6 @@ public class HorizontalScrollView extends FrameLayout { } /** - * Returns the {@link EdgeEffect#getType()} for the edge effects. - * @return the {@link EdgeEffect#getType()} for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - @EdgeEffect.EdgeEffectType - public int getEdgeEffectType() { - return mEdgeGlowLeft.getType(); - } - - /** - * Sets the {@link EdgeEffect#setType(int)} for the edge effects. - * @param type The edge effect type to use for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) { - mEdgeGlowRight.setType(type); - mEdgeGlowLeft.setType(type); - invalidate(); - } - - /** * @return The maximum amount this scroll view will scroll in response to * an arrow event. */ diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 3610eb47edbc..693b13bbf224 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -340,27 +340,6 @@ public class ScrollView extends FrameLayout { } /** - * Returns the {@link EdgeEffect#getType()} for the edge effects. - * @return the {@link EdgeEffect#getType()} for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - @EdgeEffect.EdgeEffectType - public int getEdgeEffectType() { - return mEdgeGlowTop.getType(); - } - - /** - * Sets the {@link EdgeEffect#setType(int)} for the edge effects. - * @param type The edge effect type to use for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) { - mEdgeGlowTop.setType(type); - mEdgeGlowBottom.setType(type); - invalidate(); - } - - /** * @return The maximum amount this scroll view will scroll in response to * an arrow event. */ @@ -368,7 +347,6 @@ public class ScrollView extends FrameLayout { return (int) (MAX_SCROLL_FACTOR * (mBottom - mTop)); } - private void initScrollView() { mScroller = new OverScroller(getContext()); setFocusable(true); diff --git a/core/java/com/android/internal/annotations/CompositeRWLock.java b/core/java/com/android/internal/annotations/CompositeRWLock.java deleted file mode 100644 index b6ddfc4d2cc4..000000000000 --- a/core/java/com/android/internal/annotations/CompositeRWLock.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.annotations; - -import static java.lang.annotation.ElementType.FIELD; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies a list of locks which are required for read/write operations on a data field. - * - * <p> - * To annotate methods accessing the data field with the annotation {@link CompositeRWLock}, - * use {@link GuardedBy#value} to annotate method w/ write and/or read access to the data field, - * use {@link GuardedBy#anyOf} to annotate method w/ read only access to the data field. - * </p> - * - * <p> - * When its {@link #value()} consists of multiple locks: - * <ul> - * <li>To write to the protected data, acquire <b>all</b> of the locks - * in the order of the appearance in the {@link #value}.</li> - * <li>To read from the protected data, acquire any of the locks in the {@link #value}.</li> - * </ul> - * </p> - */ -@Target({FIELD}) -@Retention(RetentionPolicy.CLASS) -public @interface CompositeRWLock { - String[] value() default {}; -} diff --git a/core/java/com/android/internal/annotations/GuardedBy.java b/core/java/com/android/internal/annotations/GuardedBy.java deleted file mode 100644 index c05c4abd10e4..000000000000 --- a/core/java/com/android/internal/annotations/GuardedBy.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.annotations; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation type used to mark a method or field that can only be accessed when - * holding the referenced locks. - */ -@Target({FIELD, METHOD}) -@Retention(RetentionPolicy.CLASS) -public @interface GuardedBy { - /** - * Specifies a list of locks to be held in order to access the field/method - * annotated with this; when used in conjunction with the {@link CompositeRWLock}, locks - * should be acquired in the order of the appearance in the {@link #value} here. - * - * <p> - * If specified, {@link #anyOf()} must be null. - * </p> - * - * @see CompositeRWLock - */ - String[] value() default {}; - - /** - * Specifies a list of locks where at least one of them must be held in order to access - * the field/method annotated with this; it should be <em>only</em> used in the conjunction - * with the {@link CompositeRWLock}. - * - * <p> - * If specified, {@link #allOf()} must be null. - * </p> - * - * @see CompositeRWLock - */ - String[] anyOf() default {}; -} diff --git a/core/java/com/android/internal/annotations/Immutable.java b/core/java/com/android/internal/annotations/Immutable.java deleted file mode 100644 index b424275f7a86..000000000000 --- a/core/java/com/android/internal/annotations/Immutable.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation type used to mark a class which is immutable. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface Immutable { -} diff --git a/core/java/com/android/internal/annotations/VisibleForNative.java b/core/java/com/android/internal/annotations/VisibleForNative.java deleted file mode 100644 index e6a3fc67b7d3..000000000000 --- a/core/java/com/android/internal/annotations/VisibleForNative.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes that the class, method or field has its visibility relaxed so - * that native code can access it. - */ -@Retention(RetentionPolicy.CLASS) -public @interface VisibleForNative { -} diff --git a/core/java/com/android/internal/annotations/VisibleForTesting.java b/core/java/com/android/internal/annotations/VisibleForTesting.java deleted file mode 100644 index 99512ac68d5d..000000000000 --- a/core/java/com/android/internal/annotations/VisibleForTesting.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes that the class, method or field has its visibility relaxed so - * that unit tests can access it. - * <p/> - * The <code>visibility</code> argument can be used to specific what the original - * visibility should have been if it had not been made public or package-private for testing. - * The default is to consider the element private. - */ -@Retention(RetentionPolicy.CLASS) -public @interface VisibleForTesting { - /** - * Intended visibility if the element had not been made public or package-private for - * testing. - */ - enum Visibility { - /** The element should be considered protected. */ - PROTECTED, - /** The element should be considered package-private. */ - PACKAGE, - /** The element should be considered private. */ - PRIVATE - } - - /** - * Intended visibility if the element had not been made public or package-private for testing. - * If not specified, one should assume the element originally intended to be private. - */ - Visibility visibility() default Visibility.PRIVATE; -} diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java index 100bf34203e7..0307268a28b5 100644 --- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java +++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; @@ -55,11 +54,6 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator { .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, powerMah, powerModel); - - builder.getOrCreateSystemBatteryConsumerBuilder( - SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, powerMah, powerModel) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN, durationMs); } /** diff --git a/core/java/com/android/internal/os/BatteryChargeCalculator.java b/core/java/com/android/internal/os/BatteryChargeCalculator.java index dc72f3267390..16f92efb922c 100644 --- a/core/java/com/android/internal/os/BatteryChargeCalculator.java +++ b/core/java/com/android/internal/os/BatteryChargeCalculator.java @@ -28,20 +28,28 @@ import java.util.List; * Estimates the battery discharge amounts. */ public class BatteryChargeCalculator extends PowerCalculator { - private final double mBatteryCapacity; - - public BatteryChargeCalculator(PowerProfile powerProfile) { - mBatteryCapacity = powerProfile.getBatteryCapacity(); - } @Override public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { builder.setDischargePercentage( - batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)) - .setDischargedPowerRange( - batteryStats.getLowDischargeAmountSinceCharge() * mBatteryCapacity / 100, - batteryStats.getHighDischargeAmountSinceCharge() * mBatteryCapacity / 100); + batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)); + + int batteryCapacityMah = batteryStats.getLearnedBatteryCapacity() / 1000; + if (batteryCapacityMah <= 0) { + batteryCapacityMah = batteryStats.getMinLearnedBatteryCapacity() / 1000; + if (batteryCapacityMah <= 0) { + batteryCapacityMah = batteryStats.getEstimatedBatteryCapacity(); + } + } + final double dischargedPowerLowerBoundMah = + batteryStats.getLowDischargeAmountSinceCharge() * batteryCapacityMah / 100.0; + final double dischargedPowerUpperBoundMah = + batteryStats.getHighDischargeAmountSinceCharge() * batteryCapacityMah / 100.0; + builder.setDischargePercentage( + batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)) + .setDischargedPowerRange(dischargedPowerLowerBoundMah, + dischargedPowerUpperBoundMah); final long batteryTimeRemainingMs = batteryStats.computeBatteryTimeRemaining(rawRealtimeUs); if (batteryTimeRemainingMs != -1) { @@ -52,6 +60,11 @@ public class BatteryChargeCalculator extends PowerCalculator { if (chargeTimeRemainingMs != -1) { builder.setChargeTimeRemainingMs(chargeTimeRemainingMs / 1000); } + + builder.getAggregateBatteryConsumerBuilder( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) + .setConsumedPower( + (dischargedPowerLowerBoundMah + dischargedPowerUpperBoundMah) / 2); } @Override diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 02a290850b6f..db67bab25e78 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -161,7 +161,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - static final int VERSION = 198; + static final int VERSION = 199; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -1056,6 +1056,7 @@ public class BatteryStatsImpl extends BatteryStats { private int mBatteryVoltageMv = -1; private int mEstimatedBatteryCapacityMah = -1; + private int mLastLearnedBatteryCapacityUah = -1; private int mMinLearnedBatteryCapacityUah = -1; private int mMaxLearnedBatteryCapacityUah = -1; @@ -1142,6 +1143,11 @@ public class BatteryStatsImpl extends BatteryStats { } @Override + public int getLearnedBatteryCapacity() { + return mLastLearnedBatteryCapacityUah; + } + + @Override public int getMinLearnedBatteryCapacity() { return mMinLearnedBatteryCapacityUah; } @@ -11199,6 +11205,7 @@ public class BatteryStatsImpl extends BatteryStats { } else { mEstimatedBatteryCapacityMah = -1; } + mLastLearnedBatteryCapacityUah = -1; mMinLearnedBatteryCapacityUah = -1; mMaxLearnedBatteryCapacityUah = -1; mInteractiveTimer.reset(false, elapsedRealtimeUs); @@ -13799,6 +13806,7 @@ public class BatteryStatsImpl extends BatteryStats { mRecordingHistory = DEBUG; } + mLastLearnedBatteryCapacityUah = chargeFullUah; if (mMinLearnedBatteryCapacityUah == -1) { mMinLearnedBatteryCapacityUah = chargeFullUah; } else { @@ -15066,6 +15074,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeCurrentLevel = in.readInt(); mCurrentBatteryLevel = in.readInt(); mEstimatedBatteryCapacityMah = in.readInt(); + mLastLearnedBatteryCapacityUah = in.readInt(); mMinLearnedBatteryCapacityUah = in.readInt(); mMaxLearnedBatteryCapacityUah = in.readInt(); mLowDischargeAmountSinceCharge = in.readInt(); @@ -15570,6 +15579,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mDischargeCurrentLevel); out.writeInt(mCurrentBatteryLevel); out.writeInt(mEstimatedBatteryCapacityMah); + out.writeInt(mLastLearnedBatteryCapacityUah); out.writeInt(mMinLearnedBatteryCapacityUah); out.writeInt(mMaxLearnedBatteryCapacityUah); out.writeInt(getLowDischargeAmountSinceCharge()); @@ -16071,6 +16081,7 @@ public class BatteryStatsImpl extends BatteryStats { mRealtimeStartUs = in.readLong(); mOnBattery = in.readInt() != 0; mEstimatedBatteryCapacityMah = in.readInt(); + mLastLearnedBatteryCapacityUah = in.readInt(); mMinLearnedBatteryCapacityUah = in.readInt(); mMaxLearnedBatteryCapacityUah = in.readInt(); mOnBatteryInternal = false; // we are no longer really running. @@ -16310,6 +16321,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mRealtimeStartUs); out.writeInt(mOnBattery ? 1 : 0); out.writeInt(mEstimatedBatteryCapacityMah); + out.writeInt(mLastLearnedBatteryCapacityUah); out.writeInt(mMinLearnedBatteryCapacityUah); out.writeInt(mMaxLearnedBatteryCapacityUah); mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime); diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index babcea14d0ea..498955983ef2 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -54,7 +54,7 @@ public class BatteryUsageStatsProvider { mPowerCalculators = new ArrayList<>(); // Power calculators are applied in the order of registration - mPowerCalculators.add(new BatteryChargeCalculator(mPowerProfile)); + mPowerCalculators.add(new BatteryChargeCalculator()); mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java index 36f871b28655..6e99bbbf2331 100644 --- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java +++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java @@ -21,7 +21,6 @@ import android.os.BatteryStats.ControllerActivityCounter; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.Log; @@ -58,19 +57,11 @@ public class BluetoothPowerCalculator extends PowerCalculator { final PowerAndDuration total = new PowerAndDuration(); - SystemBatteryConsumer.Builder systemBatteryConsumerBuilder = - builder.getOrCreateSystemBatteryConsumerBuilder( - SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH); - final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, total, query); - if (app.getUid() == Process.BLUETOOTH_UID) { - app.excludeFromBatteryUsageStats(); - systemBatteryConsumerBuilder.addUidBatteryConsumer(app); - } } final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC(); @@ -87,12 +78,6 @@ public class BluetoothPowerCalculator extends PowerCalculator { Log.d(TAG, "Bluetooth active: time=" + (systemComponentDurationMs) + " power=" + formatCharge(systemPowerMah)); } - systemBatteryConsumerBuilder - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, - systemComponentDurationMs) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, - Math.max(systemPowerMah, total.powerMah), powerModel) - .setPowerConsumedByApps(total.powerMah); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java index 9af11fe7614a..9b51a8ef6410 100644 --- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java +++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.util.SparseArray; @@ -47,15 +46,6 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { final double[] customMeasuredPowerMah = calculateMeasuredEnergiesMah( batteryStats.getCustomConsumerMeasuredBatteryConsumptionUC()); if (customMeasuredPowerMah != null) { - final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder = - builder.getOrCreateSystemBatteryConsumerBuilder( - SystemBatteryConsumer.DRAIN_TYPE_CUSTOM); - for (int i = 0; i < customMeasuredPowerMah.length; i++) { - systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i, - customMeasuredPowerMah[i]); - } - final AggregateBatteryConsumer.Builder deviceBatteryConsumerBuilder = builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); diff --git a/core/java/com/android/internal/os/IdlePowerCalculator.java b/core/java/com/android/internal/os/IdlePowerCalculator.java index cf68ab9a2066..d33a88deb9d7 100644 --- a/core/java/com/android/internal/os/IdlePowerCalculator.java +++ b/core/java/com/android/internal/os/IdlePowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UserHandle; import android.util.Log; import android.util.SparseArray; @@ -53,9 +52,6 @@ public class IdlePowerCalculator extends PowerCalculator { calculatePowerAndDuration(batteryStats, rawRealtimeUs, rawUptimeUs, BatteryStats.STATS_SINCE_CHARGED); if (mPowerMah != 0) { - builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_IDLE) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_IDLE, mPowerMah) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_IDLE, mDurationMs); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_IDLE, mPowerMah) diff --git a/core/java/com/android/internal/os/MemoryPowerCalculator.java b/core/java/com/android/internal/os/MemoryPowerCalculator.java index 950d1ecec3b3..09fd85e42225 100644 --- a/core/java/com/android/internal/os/MemoryPowerCalculator.java +++ b/core/java/com/android/internal/os/MemoryPowerCalculator.java @@ -4,7 +4,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UserHandle; import android.util.LongSparseArray; import android.util.SparseArray; @@ -31,9 +30,6 @@ public class MemoryPowerCalculator extends PowerCalculator { BatteryStats.STATS_SINCE_CHARGED); final double powerMah = calculatePower(batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); - builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_MEMORY) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MEMORY, durationMs) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MEMORY, powerMah); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MEMORY, durationMs) diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index a1bab6eb21f6..eb5993dc2d61 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -19,7 +19,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.telephony.CellSignalStrength; @@ -105,15 +104,6 @@ public class MobileRadioPowerCalculator extends PowerCalculator { calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC); if (total.remainingPowerMah != 0 || total.totalAppPowerMah != 0) { - builder.getOrCreateSystemBatteryConsumerBuilder( - SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, - total.durationMs) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, - total.remainingPowerMah + total.totalAppPowerMah, - powerModel) - .setPowerConsumedByApps(total.totalAppPowerMah); - builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java index f8997cbbd9c9..8dd463c0d5e1 100644 --- a/core/java/com/android/internal/os/PhonePowerCalculator.java +++ b/core/java/com/android/internal/os/PhonePowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; @@ -44,9 +43,6 @@ public class PhonePowerCalculator extends PowerCalculator { BatteryStats.STATS_SINCE_CHARGED) / 1000; final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs); if (phoneOnPower != 0) { - builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_PHONE) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower) diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java index 44bed2a54a10..1b3bc234fc0f 100644 --- a/core/java/com/android/internal/os/ScreenPowerCalculator.java +++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.text.format.DateUtils; @@ -109,13 +108,6 @@ public class ScreenPowerCalculator extends PowerCalculator { BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, totalAppPower, powerModel) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN, totalAppDuration); - - builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_SCREEN) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN, - totalPowerAndDuration.durationMs) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, - Math.max(totalPowerAndDuration.powerMah, totalAppPower), powerModel) - .setPowerConsumedByApps(totalAppPower); } /** diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java index 2dfc4ee69e14..776a70545df4 100644 --- a/core/java/com/android/internal/os/WifiPowerCalculator.java +++ b/core/java/com/android/internal/os/WifiPowerCalculator.java @@ -20,7 +20,6 @@ import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.Log; @@ -79,10 +78,6 @@ public class WifiPowerCalculator extends PowerCalculator { public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { - final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder = - builder.getOrCreateSystemBatteryConsumerBuilder( - SystemBatteryConsumer.DRAIN_TYPE_WIFI); - long totalAppDurationMs = 0; double totalAppPowerMah = 0; final PowerDurationAndTraffic powerDurationAndTraffic = new PowerDurationAndTraffic(); @@ -104,11 +99,6 @@ public class WifiPowerCalculator extends PowerCalculator { powerDurationAndTraffic.durationMs); app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI, powerDurationAndTraffic.powerMah, powerModel); - - if (app.getUid() == Process.WIFI_UID) { - systemBatteryConsumerBuilder.addUidBatteryConsumer(app); - app.excludeFromBatteryUsageStats(); - } } final long consumptionUC = batteryStats.getWifiMeasuredBatteryConsumptionUC(); @@ -117,13 +107,6 @@ public class WifiPowerCalculator extends PowerCalculator { BatteryStats.STATS_SINCE_CHARGED, batteryStats.hasWifiActivityReporting(), totalAppDurationMs, totalAppPowerMah, consumptionUC); - systemBatteryConsumerBuilder - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI, - powerDurationAndTraffic.durationMs) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI, - totalAppPowerMah + powerDurationAndTraffic.powerMah, powerModel) - .setPowerConsumedByApps(totalAppPowerMah); - builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI, diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java index 9ed5eb1d144e..be15a9bba107 100644 --- a/core/java/com/android/internal/widget/RecyclerView.java +++ b/core/java/com/android/internal/widget/RecyclerView.java @@ -16,16 +16,10 @@ package com.android.internal.widget; -import static android.widget.EdgeEffect.TYPE_GLOW; -import static android.widget.EdgeEffect.TYPE_STRETCH; -import static android.widget.EdgeEffect.USE_STRETCH_EDGE_EFFECT_BY_DEFAULT; -import static android.widget.EdgeEffect.USE_STRETCH_EDGE_EFFECT_FOR_SUPPORTED; - import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.compat.Compatibility; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; @@ -466,8 +460,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro private final int[] mScrollConsumed = new int[2]; private final int[] mNestedOffsets = new int[2]; - private int mEdgeEffectType; - /** * These are views that had their a11y importance changed during a layout. We defer these events * until the end of the layout because a11y service may make sync calls back to the RV while @@ -595,12 +587,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); } - boolean defaultToStretch = Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_BY_DEFAULT) - || Compatibility.isChangeEnabled(USE_STRETCH_EDGE_EFFECT_FOR_SUPPORTED); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.EdgeEffect); - mEdgeEffectType = a.getInt(com.android.internal.R.styleable.EdgeEffect_edgeEffectType, - defaultToStretch ? TYPE_STRETCH : TYPE_GLOW); a.recycle(); // Re-set whether nested scrolling is enabled so that it is set on all API levels @@ -626,28 +614,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } /** - * Returns the {@link EdgeEffect#getType()} used for all EdgeEffects. - * - * @return @link EdgeEffect#getType()} used for all EdgeEffects. - */ - @EdgeEffect.EdgeEffectType - public int getEdgeEffectType() { - return mEdgeEffectType; - } - - /** - * Sets the {@link EdgeEffect#getType()} used in all EdgeEffects. - * Any existing over-scroll effects are cleared and new effects are created as needed. - * - * @param type the {@link EdgeEffect#getType()} used in all EdgeEffects. - */ - public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) { - mEdgeEffectType = type; - invalidateGlows(); - invalidate(); - } - - /** * Instantiate and set a LayoutManager, if specified in the attributes. */ private void createLayoutManager(Context context, String className, AttributeSet attrs, @@ -2223,7 +2189,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return; } mLeftGlow = new EdgeEffect(getContext()); - mLeftGlow.setType(mEdgeEffectType); if (mClipToPadding) { mLeftGlow.setSize(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), getMeasuredWidth() - getPaddingLeft() - getPaddingRight()); @@ -2237,7 +2202,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return; } mRightGlow = new EdgeEffect(getContext()); - mRightGlow.setType(mEdgeEffectType); if (mClipToPadding) { mRightGlow.setSize(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), getMeasuredWidth() - getPaddingLeft() - getPaddingRight()); @@ -2251,7 +2215,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return; } mTopGlow = new EdgeEffect(getContext()); - mTopGlow.setType(mEdgeEffectType); if (mClipToPadding) { mTopGlow.setSize(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), getMeasuredHeight() - getPaddingTop() - getPaddingBottom()); @@ -2266,7 +2229,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return; } mBottomGlow = new EdgeEffect(getContext()); - mBottomGlow.setType(mEdgeEffectType); if (mClipToPadding) { mBottomGlow.setSize(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), getMeasuredHeight() - getPaddingTop() - getPaddingBottom()); diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 93cde3ddb72d..1174db5b2cf7 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -387,28 +387,6 @@ public class ViewPager extends ViewGroup { } /** - * Returns the {@link EdgeEffect#getType()} for the edge effects. - * @return the {@link EdgeEffect#getType()} for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - @EdgeEffect.EdgeEffectType - public int getEdgeEffectType() { - // Both left and right edge have the same edge effect type - return mLeftEdge.getType(); - } - - /** - * Sets the {@link EdgeEffect#setType(int)} for the edge effects. - * @param type The edge effect type to use for the edge effects. - * @attr ref android.R.styleable#EdgeEffect_edgeEffectType - */ - public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) { - mLeftEdge.setType(type); - mRightEdge.setType(type); - invalidate(); - } - - /** * Set a PagerAdapter that will supply views for this pager as needed. * * @param adapter Adapter to use diff --git a/core/jni/android_media_AudioAttributes.cpp b/core/jni/android_media_AudioAttributes.cpp index b616ffc111a3..f1ae268f4c16 100644 --- a/core/jni/android_media_AudioAttributes.cpp +++ b/core/jni/android_media_AudioAttributes.cpp @@ -171,10 +171,6 @@ jint JNIAudioAttributeHelper::getJavaArray( /* * JNI registration. */ -static const JNINativeMethod gMethods[] = { - // n/a -}; - int register_android_media_AudioAttributes(JNIEnv *env) { jclass audioAttributesClass = FindClassOrDie(env, kClassPathName); @@ -218,5 +214,5 @@ int register_android_media_AudioAttributes(JNIEnv *env) env->DeleteLocalRef(audioAttributesClass); - return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); + return 0; } diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 4bd33a9cbd3b..1baea2aecc3c 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -37,11 +37,13 @@ static jmethodID gLongValueOf; namespace android { +using vintf::CompatibilityMatrix; using vintf::HalManifest; using vintf::Level; using vintf::SchemaType; using vintf::to_string; using vintf::toXml; +using vintf::Version; using vintf::VintfObject; using vintf::Vndk; @@ -119,6 +121,28 @@ static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) { return env->NewStringUTF(cString.c_str()); } +static jstring android_os_VintfObject_getPlatformSepolicyVersion(JNIEnv* env, jclass) { + std::shared_ptr<const CompatibilityMatrix> matrix = + VintfObject::GetFrameworkCompatibilityMatrix(); + if (matrix == nullptr || matrix->type() != SchemaType::FRAMEWORK) { + jniThrowRuntimeException(env, "Cannot get framework compatibility matrix"); + return nullptr; + } + + auto versions = matrix->getSepolicyVersions(); + if (versions.empty()) { + jniThrowRuntimeException(env, + "sepolicy_version in framework compatibility matrix is empty"); + return nullptr; + } + + Version latest; + for (const auto& range : versions) { + latest = std::max(latest, range.maxVer()); + } + return env->NewStringUTF(to_string(latest).c_str()); +} + static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) { std::shared_ptr<const HalManifest> manifest = VintfObject::GetFrameworkHalManifest(); if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) { @@ -145,12 +169,17 @@ static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersi // ---------------------------------------------------------------------------- static const JNINativeMethod gVintfObjectMethods[] = { - {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report}, - {"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb}, - {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions}, - {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion}, - {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots}, - {"getTargetFrameworkCompatibilityMatrixVersion", "()Ljava/lang/Long;", (void*)android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion}, + {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report}, + {"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb}, + {"getHalNamesAndVersions", "()[Ljava/lang/String;", + (void*)android_os_VintfObject_getHalNamesAndVersions}, + {"getSepolicyVersion", "()Ljava/lang/String;", + (void*)android_os_VintfObject_getSepolicyVersion}, + {"getPlatformSepolicyVersion", "()Ljava/lang/String;", + (void*)android_os_VintfObject_getPlatformSepolicyVersion}, + {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots}, + {"getTargetFrameworkCompatibilityMatrixVersion", "()Ljava/lang/Long;", + (void*)android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion}, }; const char* const kVintfObjectPathName = "android/os/VintfObject"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4dc4bef10475..4b828ba4cb02 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3947,11 +3947,11 @@ <!-- This permission is required among systems services when accessing tuner resource management related APIs or information. - <p>Protection level: signature|privileged - <p>Not for use by third-party applications. + <p>Protection level: signature|privileged|vendorPrivileged + <p>This should only be used by the OEM TvInputService. @hide --> <permission android:name="android.permission.TUNER_RESOURCE_ACCESS" - android:protectionLevel="signature|privileged" /> + android:protectionLevel="signature|privileged|vendorPrivileged" /> <!-- This permission is required by Media Resource Manager Service when accessing its overridePid Api. diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 182fddce11b0..ff07d9b7ad7b 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"এপ্লিকেশ্বনৰ ব্ৰেণ্ডৰ প্ৰতিচ্ছবি"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"এক্সেছৰ ছেটিং পৰীক্ষা কৰক"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনখন চাব আৰু পৰিচালনা কৰিব পাৰে। পৰ্যালোচনা কৰিবলৈ টিপক।"</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> অনুবাদ কৰা হ’ল।"</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"বাৰ্তাটো <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ৰ পৰা <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>লৈ অনুবাদ কৰা হ’ল।"</string> </resources> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index a265821e5b09..a065f19e0b44 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"অ্যাপের ব্র্যান্ড ছবি"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"অ্যাক্সেস করার সেটিংস চেক করুন"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> আপনার স্ক্রিন দেখতে ও কন্ট্রোল করতে পারবে। পর্যালোচনা করতে ট্যাপ করুন।"</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> অনুবাদ করা হয়েছে।"</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"মেসেজ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> থেকে <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ভাষাতে অনুবাদ করা হয়েছে।"</string> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 6a33a0a52f53..d277a80fe440 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"App-Branding-Hintergrundbild"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"Zugriffseinstellungen prüfen"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kann deinen Bildschirm sehen und steuern. Zum Prüfen tippen."</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"„<xliff:g id="MESSAGE">%1$s</xliff:g>“ wurde übersetzt."</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Nachricht wurde von <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> auf <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> übersetzt."</string> </resources> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 17cff18dcd23..b7ecc0eb4676 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ઍપ્લિકેશનની બ્રાંડિંગ છબી"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"ઍક્સેસના સેટિંગ ચેક કરો"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> તમારી સ્ક્રીન જોઈ અને નિયંત્રિત કરી શકે છે. રિવ્યૂ કરવા માટે ટૅપ કરો."</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g>નો અનુવાદ કર્યો."</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>થી <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>માં સંદેશનો અનુવાદ કરવામાં આવ્યો."</string> </resources> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index aecd79bd6527..dd96815dc551 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -2355,8 +2355,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"תדמית המותג של האפליקציה"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"בדיקה של הגדרות הגישה"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"לשירות <xliff:g id="SERVICE_NAME">%s</xliff:g> יש הרשאה להצגת המסך ושליטה בו. אפשר להקיש כדי לבדוק."</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"ההודעה <xliff:g id="MESSAGE">%1$s</xliff:g> תורגמה."</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ההודעה תורגמה מ<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ל<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> </resources> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 3a2a2b569f27..330147d6a131 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -2285,7 +2285,7 @@ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"सेन्सरसम्बन्धी गोपनीयता"</string> <string name="splash_screen_view_icon_description" msgid="180638751260598187">"एप जनाउने आइकन"</string> <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"एपको ब्रान्डिङ फोटो"</string> - <string name="view_and_control_notification_title" msgid="4300765399209912240">"हेराइ र नियन्त्रणसम्बन्धी सेटिङ जाँच्नुहोस्"</string> + <string name="view_and_control_notification_title" msgid="4300765399209912240">"भ्यु र नियन्त्रणसम्बन्धी सेटिङ जाँच्नुहोस्"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> तपाईंको स्क्रिन हेर्न र नियन्त्रण गर्न सक्छ। सेटिङ मिलाउन ट्याप गर्नुहोस्।"</string> <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> <skip /> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 5aa16e7e22de..cdd9f52aa322 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ଆପ୍ଲିକେସନ୍ ବ୍ରାଣ୍ଡିଂ ଛବି"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"ଆକ୍ସେସ୍ ସେଟିଂସକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ଦେଖିପାରିବ ଏବଂ ନିୟନ୍ତ୍ରଣ କରିପାରିବ। ସମୀକ୍ଷା କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ଅନୁବାଦ କରାଯାଇଛି।"</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ମେସେଜ୍, <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ରୁ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>କୁ ଅନୁବାଦ କରାଯାଇଛି।"</string> </resources> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 6cc4f1998183..afd9c0c12496 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ਐਪਲੀਕੇਸ਼ਨ ਦਾ ਬ੍ਰਾਂਡ ਵਾਲਾ ਚਿੱਤਰ"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"ਪਹੁੰਚ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਸੇਵਾ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਦੇਖ ਅਤੇ ਕੰਟਰੋਲ ਕਰ ਸਕਦੀ ਹੈ। ਸਮੀਖਿਆ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ਦਾ ਅਨੁਵਾਦ ਕੀਤਾ ਗਿਆ।"</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ਸੁਨੇਹੇ ਦਾ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ਤੋਂ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ਵਿੱਚ ਅਨੁਵਾਦ ਕੀਤਾ ਗਿਆ।"</string> </resources> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 49ea3638a160..e1998ddf0dfe 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"యాప్ బ్రాండింగ్ ఇమేజ్"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"యాక్సెస్ సెట్టింగ్లను చెక్ చేయండి"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> మీ స్క్రీన్ను చూడవచ్చు, కంట్రోల్ చేయవచ్చు. రివ్యూ చేయడానికి ట్యాప్ చేయండి."</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> అనువదించబడింది."</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"మెసేజ్ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> నుండి <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>కు అనువదించబడింది."</string> </resources> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 48208ac677cc..6d99dfb4563c 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -2287,8 +2287,6 @@ <string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ایپلیکیشن کی برانڈنگ تصویر"</string> <string name="view_and_control_notification_title" msgid="4300765399209912240">"رسائی کی ترتیبات چیک کریں"</string> <string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> آپ کی اسکرین کو دیکھ اور کنٹرول کر سکتی ہیں۔ جائزے کے لیے تھپتھپائیں۔"</string> - <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) --> - <skip /> - <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) --> - <skip /> + <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> کا ترجمہ کیا گیا۔"</string> + <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"پیغام کا ترجمہ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> سے<xliff:g id="TO_LANGUAGE">%2$s</xliff:g> میں کیا گیا۔"</string> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 480b47835100..f0c43ff18d36 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1179,15 +1179,6 @@ <!-- Color applied to effects. --> <attr name="effectColor" format="color" /> - <!-- The type of the edge effect. The default is glow. --> - <attr name="edgeEffectType"> - <!-- Use a colored glow at the edge. --> - <enum name="glow" value="0" /> - - <!-- Stretch the content. --> - <enum name="stretch" value="1" /> - </attr> - <!-- =================== --> <!-- Lighting properties --> <!-- =================== --> @@ -9257,7 +9248,6 @@ <!-- Used as a filter array on the theme to pull out only the EdgeEffect-relevant bits. --> <declare-styleable name="EdgeEffect"> <attr name="colorEdgeEffect" /> - <attr name="edgeEffectType" /> </declare-styleable> <!-- Use <code>tv-input</code> as the root tag of the XML resource that describes a diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 0e9526ab4e6c..482b112c0444 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3064,7 +3064,6 @@ <public name="hotwordDetectionService" /> <public name="previewLayout" /> <public name="clipToOutline" /> - <public name="edgeEffectType" /> <public name="knownCerts" /> <public name="windowBackgroundBlurRadius"/> <public name="windowSplashScreenBackground"/> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java index da6dc76a68d2..24b164bcb8c0 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java @@ -19,7 +19,6 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.DebugUtils; @@ -133,11 +132,6 @@ public class BatteryConsumerData { } } - for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) { - if (batteryConsumerId(consumer).equals(batteryConsumerId)) { - return consumer; - } - } return null; } @@ -157,11 +151,25 @@ public class BatteryConsumerData { private void computeTotalPower(BatteryUsageStats batteryUsageStats, double[] powerByComponentMah) { - for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { - for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; - component++) { - powerByComponentMah[component] += consumer.getConsumedPower(component); - } + final BatteryConsumer consumer = + batteryUsageStats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) { + powerByComponentMah[component] += consumer.getConsumedPower(component); + } + } + + private void computeTotalPowerForCustomComponent( + BatteryUsageStats batteryUsageStats, double[] powerByComponentMah) { + final BatteryConsumer consumer = + batteryUsageStats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + final int customComponentCount = consumer.getCustomPowerComponentCount(); + for (int component = 0; + component < Math.min(customComponentCount, powerByComponentMah.length); + component++) { + powerByComponentMah[component] += consumer.getConsumedPowerForCustomComponent( + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component); } } @@ -175,19 +183,6 @@ public class BatteryConsumerData { } } - private void computeTotalPowerForCustomComponent( - BatteryUsageStats batteryUsageStats, double[] powerByComponentMah) { - for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { - final int customComponentCount = consumer.getCustomPowerComponentCount(); - for (int component = 0; - component < Math.min(customComponentCount, powerByComponentMah.length); - component++) { - powerByComponentMah[component] += consumer.getConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component); - } - } - } - private void addEntry(String title, EntryType entryType, double amount, double totalAmount, boolean isSystemBatteryConsumer) { Entry entry = new Entry(); @@ -212,8 +207,6 @@ public class BatteryConsumerData { return "APP|" + UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|" + ((UidBatteryConsumer) consumer).getUid(); - } else if (consumer instanceof SystemBatteryConsumer) { - return ((SystemBatteryConsumer) consumer).getDrainType() + "|0|0"; } else { return ""; } diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java index c37b48bb5e6a..f2d6bca28136 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java @@ -23,7 +23,6 @@ import android.content.pm.PackageManager; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.util.DebugUtils; @@ -113,20 +112,6 @@ class BatteryConsumerInfoHelper { // Won't happen } } - } else if (batteryConsumer instanceof SystemBatteryConsumer) { - final SystemBatteryConsumer systemBatteryConsumer = - (SystemBatteryConsumer) batteryConsumer; - final int drainType = systemBatteryConsumer.getDrainType(); - String name = DebugUtils.constantToString(SystemBatteryConsumer.class, "DRAIN_TYPE_", - drainType); - info.label = name.charAt(0) + name.substring(1).toLowerCase().replace('_', ' '); - info.isSystemBatteryConsumer = true; - try { - info.iconInfo = - packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0); - } catch (PackageManager.NameNotFoundException nameNotFoundException) { - // Won't happen - } } else { for (int scope = 0; scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java index 63a15d6c63b4..9e63a350df41 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java @@ -18,68 +18,60 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; import android.os.Bundle; +import android.os.UidBatteryConsumer; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import androidx.activity.ComponentActivity; import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentStatePagerAdapter; -import androidx.viewpager.widget.ViewPager; +import androidx.loader.app.LoaderManager; +import androidx.loader.content.Loader; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; -import com.google.android.material.tabs.TabLayout; +import com.android.settingslib.utils.AsyncLoaderCompat; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; /** * Picker, showing a sorted lists of applications and other types of entities consuming power. * Opens BatteryStatsViewerActivity upon item selection. */ -public class BatteryConsumerPickerActivity extends FragmentActivity { +public class BatteryConsumerPickerActivity extends ComponentActivity { private static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId"; + private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000; + private BatteryConsumerListAdapter mBatteryConsumerListAdapter; + private RecyclerView mAppList; + private View mLoadingView; + private final Runnable mBatteryStatsRefresh = this::loadBatteryStats; + + private interface OnBatteryConsumerSelectedListener { + void onBatteryConsumerSelected(String batteryConsumerId); + } @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); - setContentView(R.layout.battery_consumer_picker_activity_layout); - - ViewPager viewPager = findViewById(R.id.pager); - - FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter( - getSupportFragmentManager()) { - - @Override - public int getCount() { - return 2; - } - - @NonNull - @Override - public Fragment getItem(int position) { - switch (position) { - case 0: - return new BatteryConsumerPickerFragment( - BatteryConsumerPickerFragment.PICKER_TYPE_APP); - case 1: - default: - return new BatteryConsumerPickerFragment( - BatteryConsumerPickerFragment.PICKER_TYPE_DRAIN); - } - } + setContentView(R.layout.battery_consumer_picker_layout); + mLoadingView = findViewById(R.id.loading_view); - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return "Apps"; - case 1: - return "Drains"; - } - return null; - } - }; + mAppList = findViewById(R.id.list_view); + mAppList.setLayoutManager(new LinearLayoutManager(this)); + mBatteryConsumerListAdapter = + new BatteryConsumerListAdapter((this::setSelectedBatteryConsumer)); + mAppList.setAdapter(mBatteryConsumerListAdapter); - viewPager.setAdapter(adapter); - TabLayout tabLayout = findViewById(R.id.tab_layout); - tabLayout.setupWithViewPager(viewPager); if (icicle == null) { final String batteryConsumerId = getPreferences(Context.MODE_PRIVATE) .getString(PREF_SELECTED_BATTERY_CONSUMER, null); @@ -101,4 +93,183 @@ public class BatteryConsumerPickerActivity extends FragmentActivity { .putExtra(BatteryStatsViewerActivity.EXTRA_BATTERY_CONSUMER, batteryConsumerId); startActivity(intent); } + + @Override + protected void onResume() { + super.onResume(); + loadBatteryStats(); + } + + @Override + protected void onPause() { + super.onPause(); + getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh); + } + + private void loadBatteryStats() { + LoaderManager.getInstance(this).restartLoader(0, null, + new BatteryConsumerListLoaderCallbacks()); + getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS); + } + + private static class BatteryConsumerListLoader extends + AsyncLoaderCompat<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> { + private final BatteryStatsManager mBatteryStatsManager; + private final PackageManager mPackageManager; + + BatteryConsumerListLoader(Context context) { + super(context); + mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); + mPackageManager = context.getPackageManager(); + } + + @Override + public List<BatteryConsumerInfoHelper.BatteryConsumerInfo> loadInBackground() { + final BatteryUsageStats batteryUsageStats = mBatteryStatsManager.getBatteryUsageStats(); + List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList = + new ArrayList<>(); + + for (int scope = 0; + scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; + scope++) { + batteryConsumerList.add( + BatteryConsumerInfoHelper.makeBatteryConsumerInfo( + batteryUsageStats.getAggregateBatteryConsumer(scope), + BatteryConsumerData.batteryConsumerId(scope), + mPackageManager)); + } + + for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + batteryConsumerList.add( + BatteryConsumerInfoHelper.makeBatteryConsumerInfo(consumer, + BatteryConsumerData.batteryConsumerId(consumer), + mPackageManager)); + } + + batteryConsumerList.sort( + Comparator.comparing( + (BatteryConsumerInfoHelper.BatteryConsumerInfo a) -> a.powerMah) + .reversed()); + + return batteryConsumerList; + } + + @Override + protected void onDiscardResult(List<BatteryConsumerInfoHelper.BatteryConsumerInfo> result) { + } + } + + private class BatteryConsumerListLoaderCallbacks implements + LoaderManager.LoaderCallbacks<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> { + + @NonNull + @Override + public Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> onCreateLoader(int id, + Bundle args) { + return new BatteryConsumerListLoader(BatteryConsumerPickerActivity.this); + } + + @Override + public void onLoadFinished( + @NonNull Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> loader, + List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList) { + mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList); + mAppList.setVisibility(View.VISIBLE); + mLoadingView.setVisibility(View.GONE); + } + + @Override + public void onLoaderReset( + @NonNull Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> loader) { + } + } + + public class BatteryConsumerListAdapter + extends RecyclerView.Adapter<BatteryConsumerViewHolder> { + private final OnBatteryConsumerSelectedListener mListener; + private List<BatteryConsumerInfoHelper.BatteryConsumerInfo> mBatteryConsumerList; + + public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) { + mListener = listener; + } + + void setBatteryConsumerList( + List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList) { + mBatteryConsumerList = batteryConsumerList; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mBatteryConsumerList.size(); + } + + @NonNull + @Override + public BatteryConsumerViewHolder onCreateViewHolder( + @NonNull ViewGroup viewGroup, + int position) { + LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext()); + View view = layoutInflater.inflate(R.layout.battery_consumer_info_layout, viewGroup, + false); + return new BatteryConsumerViewHolder(view, mListener); + } + + @Override + public void onBindViewHolder(@NonNull BatteryConsumerViewHolder viewHolder, int position) { + BatteryConsumerInfoHelper.BatteryConsumerInfo item = mBatteryConsumerList.get(position); + viewHolder.id = item.id; + viewHolder.titleView.setText(item.label); + if (item.details != null) { + viewHolder.detailsView.setText(item.details); + viewHolder.detailsView.setVisibility(View.VISIBLE); + } else { + viewHolder.detailsView.setVisibility(View.GONE); + } + viewHolder.powerView.setText( + String.format(Locale.getDefault(), "%.1f mAh", item.powerMah)); + if (item.iconInfo != null) { + viewHolder.iconView.setImageDrawable( + item.iconInfo.loadIcon(getPackageManager())); + } else { + viewHolder.iconView.setImageResource(R.drawable.gm_device_24); + } + if (item.packages != null) { + viewHolder.packagesView.setText(item.packages); + viewHolder.packagesView.setVisibility(View.VISIBLE); + } else { + viewHolder.packagesView.setVisibility(View.GONE); + } + } + } + + // View Holder used when displaying apps + public static class BatteryConsumerViewHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { + private final OnBatteryConsumerSelectedListener mListener; + + public String id; + public TextView titleView; + public TextView detailsView; + public ImageView iconView; + public TextView packagesView; + public TextView powerView; + + BatteryConsumerViewHolder(View view, OnBatteryConsumerSelectedListener listener) { + super(view); + mListener = listener; + view.setOnClickListener(this); + titleView = view.findViewById(android.R.id.title); + detailsView = view.findViewById(R.id.details); + iconView = view.findViewById(android.R.id.icon); + packagesView = view.findViewById(R.id.packages); + powerView = view.findViewById(R.id.power_mah); + powerView.setVisibility(View.VISIBLE); + } + + @Override + public void onClick(View v) { + mListener.onBatteryConsumerSelected(id); + } + } } diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java deleted file mode 100644 index daa6dae37f50..000000000000 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2008 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.frameworks.core.batterystatsviewer; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.BatteryStatsManager; -import android.os.BatteryUsageStats; -import android.os.Bundle; -import android.os.SystemBatteryConsumer; -import android.os.UidBatteryConsumer; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.loader.app.LoaderManager; -import androidx.loader.content.Loader; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.frameworks.core.batterystatsviewer.BatteryConsumerInfoHelper.BatteryConsumerInfo; -import com.android.settingslib.utils.AsyncLoaderCompat; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; - -/** - * Picker, showing a sorted lists of applications or other types of entities consuming power. - * Returns the selected entity ID or null. - */ -public class BatteryConsumerPickerFragment extends Fragment { - private static final String TAG = "AppPicker"; - - public static final String PICKER_TYPE = "pickertype"; - - public static final int PICKER_TYPE_APP = 0; - public static final int PICKER_TYPE_DRAIN = 1; - - private BatteryConsumerListAdapter mBatteryConsumerListAdapter; - private RecyclerView mAppList; - private View mLoadingView; - - private interface OnBatteryConsumerSelectedListener { - void onBatteryConsumerSelected(String batteryConsumerId); - } - - public BatteryConsumerPickerFragment(int pickerType) { - Bundle args = new Bundle(); - args.putInt(PICKER_TYPE, pickerType); - setArguments(args); - } - - public BatteryConsumerPickerFragment() { - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.battery_consumer_picker_layout, container, false); - mLoadingView = view.findViewById(R.id.loading_view); - - mAppList = view.findViewById(R.id.list_view); - mAppList.setLayoutManager(new LinearLayoutManager(getContext())); - mBatteryConsumerListAdapter = new BatteryConsumerListAdapter( - BatteryConsumerPickerFragment.this::setSelectedBatteryConsumer); - mAppList.setAdapter(mBatteryConsumerListAdapter); - - LoaderManager.getInstance(this).initLoader(0, getArguments(), - new BatteryConsumerListLoaderCallbacks()); - return view; - } - - public void setSelectedBatteryConsumer(String id) { - ((BatteryConsumerPickerActivity) getActivity()).setSelectedBatteryConsumer(id); - } - - private static class BatteryConsumerListLoader extends - AsyncLoaderCompat<List<BatteryConsumerInfo>> { - private final int mPickerType; - private final BatteryStatsManager mBatteryStatsManager; - private final PackageManager mPackageManager; - - BatteryConsumerListLoader(Context context, int pickerType) { - super(context); - mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); - mPickerType = pickerType; - mPackageManager = context.getPackageManager(); - } - - @Override - public List<BatteryConsumerInfo> loadInBackground() { - final BatteryUsageStats batteryUsageStats = mBatteryStatsManager.getBatteryUsageStats(); - List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>(); - - for (int scope = 0; - scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; - scope++) { - batteryConsumerList.add( - BatteryConsumerInfoHelper.makeBatteryConsumerInfo( - batteryUsageStats.getAggregateBatteryConsumer(scope), - BatteryConsumerData.batteryConsumerId(scope), - mPackageManager)); - } - - switch (mPickerType) { - case PICKER_TYPE_APP: - for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { - batteryConsumerList.add( - BatteryConsumerInfoHelper.makeBatteryConsumerInfo(consumer, - BatteryConsumerData.batteryConsumerId(consumer), - mPackageManager)); - } - break; - case PICKER_TYPE_DRAIN: - default: - for (SystemBatteryConsumer consumer : - batteryUsageStats.getSystemBatteryConsumers()) { - batteryConsumerList.add( - BatteryConsumerInfoHelper.makeBatteryConsumerInfo(consumer, - BatteryConsumerData.batteryConsumerId(consumer), - mPackageManager)); - } - break; - } - - batteryConsumerList.sort( - Comparator.comparing((BatteryConsumerInfo a) -> a.powerMah).reversed()); - return batteryConsumerList; - } - - @Override - protected void onDiscardResult(List<BatteryConsumerInfo> result) { - } - } - - private class BatteryConsumerListLoaderCallbacks implements - LoaderManager.LoaderCallbacks<List<BatteryConsumerInfo>> { - - @NonNull - @Override - public Loader<List<BatteryConsumerInfo>> onCreateLoader(int id, Bundle args) { - return new BatteryConsumerListLoader(getContext(), args.getInt(PICKER_TYPE)); - } - - @Override - public void onLoadFinished(@NonNull Loader<List<BatteryConsumerInfo>> loader, - List<BatteryConsumerInfo> batteryConsumerList) { - mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList); - mAppList.setVisibility(View.VISIBLE); - mLoadingView.setVisibility(View.GONE); - } - - @Override - public void onLoaderReset( - @NonNull Loader<List<BatteryConsumerInfo>> loader) { - } - } - - public class BatteryConsumerListAdapter extends - RecyclerView.Adapter<BatteryConsumerViewHolder> { - private final OnBatteryConsumerSelectedListener mListener; - private List<BatteryConsumerInfo> mBatteryConsumerList; - - public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) { - mListener = listener; - } - - void setBatteryConsumerList(List<BatteryConsumerInfo> batteryConsumerList) { - mBatteryConsumerList = batteryConsumerList; - notifyDataSetChanged(); - } - - @Override - public int getItemCount() { - return mBatteryConsumerList.size(); - } - - @NonNull - @Override - public BatteryConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, - int position) { - LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext()); - View view = layoutInflater.inflate(R.layout.battery_consumer_info_layout, viewGroup, - false); - return new BatteryConsumerViewHolder(view, mListener); - } - - @Override - public void onBindViewHolder(@NonNull BatteryConsumerViewHolder viewHolder, int position) { - BatteryConsumerInfo item = mBatteryConsumerList.get(position); - viewHolder.id = item.id; - viewHolder.titleView.setText(item.label); - if (item.details != null) { - viewHolder.detailsView.setText(item.details); - viewHolder.detailsView.setVisibility(View.VISIBLE); - } else { - viewHolder.detailsView.setVisibility(View.GONE); - } - viewHolder.powerView.setText( - String.format(Locale.getDefault(), "%.1f mAh", item.powerMah)); - if (item.iconInfo != null) { - viewHolder.iconView.setImageDrawable( - item.iconInfo.loadIcon(getContext().getPackageManager())); - } else { - viewHolder.iconView.setImageResource(R.drawable.gm_device_24); - } - if (item.packages != null) { - viewHolder.packagesView.setText(item.packages); - viewHolder.packagesView.setVisibility(View.VISIBLE); - } else { - viewHolder.packagesView.setVisibility(View.GONE); - } - } - } - - // View Holder used when displaying apps - public static class BatteryConsumerViewHolder extends RecyclerView.ViewHolder - implements View.OnClickListener { - private final OnBatteryConsumerSelectedListener mListener; - - public String id; - public TextView titleView; - public TextView detailsView; - public ImageView iconView; - public TextView packagesView; - public TextView powerView; - - BatteryConsumerViewHolder(View view, OnBatteryConsumerSelectedListener listener) { - super(view); - mListener = listener; - view.setOnClickListener(this); - titleView = view.findViewById(android.R.id.title); - detailsView = view.findViewById(R.id.details); - iconView = view.findViewById(android.R.id.icon); - packagesView = view.findViewById(R.id.packages); - powerView = view.findViewById(R.id.power_mah); - powerView.setVisibility(View.VISIBLE); - } - - @Override - public void onClick(View v) { - mListener.onBatteryConsumerSelected(id); - } - } -} diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java index f84e97a14297..bb75be4f5ba8 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java @@ -51,7 +51,7 @@ public class BatteryStatsViewerActivity extends ComponentActivity { private static final int LOADER_BATTERY_USAGE_STATS = 1; private BatteryStatsDataAdapter mBatteryStatsDataAdapter; - private final Runnable mBatteryStatsRefresh = this::periodicBatteryStatsRefresh; + private final Runnable mBatteryStatsRefresh = this::loadBatteryStats; private String mBatteryConsumerId; private TextView mTitleView; private TextView mDetailsView; @@ -85,13 +85,15 @@ public class BatteryStatsViewerActivity extends ComponentActivity { mLoadingView = findViewById(R.id.loading_view); mEmptyView = findViewById(R.id.empty_view); - loadBatteryStats(); + LoaderManager loaderManager = LoaderManager.getInstance(this); + loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null, + new BatteryUsageStatsLoaderCallbacks()); } @Override protected void onResume() { super.onResume(); - periodicBatteryStatsRefresh(); + loadBatteryStats(); } @Override @@ -100,15 +102,11 @@ public class BatteryStatsViewerActivity extends ComponentActivity { getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh); } - private void periodicBatteryStatsRefresh() { - loadBatteryStats(); - getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS); - } - private void loadBatteryStats() { LoaderManager loaderManager = LoaderManager.getInstance(this); loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null, new BatteryUsageStatsLoaderCallbacks()); + getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS); } private static class BatteryUsageStatsLoader extends diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 2e2e6bd07539..6f17ea994699 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -185,15 +185,6 @@ public class ActivityThreadTest { } @Test - public void testHandleActivity_assetsChanged() { - relaunchActivityAndAssertPreserveWindow(activity -> { - // Relaunches all activities. - activity.getActivityThread().handleApplicationInfoChanged( - activity.getApplicationInfo()); - }); - } - - @Test public void testRecreateActivity() { relaunchActivityAndAssertPreserveWindow(Activity::recreate); } diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java index 3e2c4e98e21a..5cee2c1389e4 100644 --- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java +++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java @@ -16,6 +16,9 @@ package android.app.people; +import static android.app.people.PeopleSpaceTile.SHOW_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS; + import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; @@ -178,6 +181,71 @@ public class PeopleSpaceTileTest { } @Test + public void testUserQuieted() { + PeopleSpaceTile tile = new PeopleSpaceTile.Builder( + new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); + assertFalse(tile.isUserQuieted()); + + tile = new PeopleSpaceTile + .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps) + .setIsUserQuieted(true) + .build(); + assertTrue(tile.isUserQuieted()); + } + + @Test + public void testCanBypassDnd() { + PeopleSpaceTile tile = new PeopleSpaceTile.Builder( + new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); + assertFalse(tile.canBypassDnd()); + + tile = new PeopleSpaceTile + .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps) + .setCanBypassDnd(true) + .build(); + assertTrue(tile.canBypassDnd()); + } + + @Test + public void testNotificationPolicyState() { + PeopleSpaceTile tile = new PeopleSpaceTile.Builder( + new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); + assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS); + + tile = new PeopleSpaceTile + .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps) + .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS) + .build(); + assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_IMPORTANT_CONVERSATIONS); + } + + @Test + public void testPackageSuspended() { + PeopleSpaceTile tile = new PeopleSpaceTile.Builder( + new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); + assertFalse(tile.isPackageSuspended()); + + tile = new PeopleSpaceTile + .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps) + .setIsPackageSuspended(true) + .build(); + assertTrue(tile.isPackageSuspended()); + } + + @Test + public void testContactAffinity() { + PeopleSpaceTile tile = new PeopleSpaceTile.Builder( + new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); + assertThat(tile.getContactAffinity()).isEqualTo(0f); + + tile = new PeopleSpaceTile + .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps) + .setContactAffinity(1f) + .build(); + assertThat(tile.getContactAffinity()).isEqualTo(1f); + } + + @Test public void testStatuses() { PeopleSpaceTile tile = new PeopleSpaceTile.Builder( new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); @@ -238,6 +306,11 @@ public class PeopleSpaceTileTest { .setNotificationDataUri(Uri.parse("data")) .setMessagesCount(2) .setIntent(new Intent()) + .setIsUserQuieted(true) + .setCanBypassDnd(false) + .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS) + .setIsPackageSuspended(true) + .setContactAffinity(1f) .build(); Parcel parcel = Parcel.obtain(); @@ -261,6 +334,12 @@ public class PeopleSpaceTileTest { assertThat(readTile.getNotificationDataUri()).isEqualTo(tile.getNotificationDataUri()); assertThat(readTile.getMessagesCount()).isEqualTo(tile.getMessagesCount()); assertThat(readTile.getIntent().toString()).isEqualTo(tile.getIntent().toString()); + assertThat(readTile.isUserQuieted()).isEqualTo(tile.isUserQuieted()); + assertThat(readTile.canBypassDnd()).isEqualTo(tile.canBypassDnd()); + assertThat(readTile.getNotificationPolicyState()).isEqualTo( + tile.getNotificationPolicyState()); + assertThat(readTile.isPackageSuspended()).isEqualTo(tile.isPackageSuspended()); + assertThat(readTile.getContactAffinity()).isEqualTo(tile.getContactAffinity()); } @Test diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java index cf126c62dac7..23fc35d6ffa5 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java @@ -36,18 +36,12 @@ public class BatteryChargeCalculatorTest { @Rule public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() - .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0); + .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 1234.0); // Should be ignored @Test public void testDischargeTotals() { - BatteryChargeCalculator calculator = - new BatteryChargeCalculator(mStatsRule.getPowerProfile()); - final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); - mStatsRule.setTime(1000, 1000); - batteryStats.resetAllStatsCmdLocked(); - batteryStats.setNoAutoReset(true); batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000, 1_000_000, 1_000_000); @@ -58,8 +52,11 @@ public class BatteryChargeCalculatorTest { /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000, 2_000_000, 2_000_000); + BatteryChargeCalculator calculator = new BatteryChargeCalculator(); BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator); + assertThat(batteryUsageStats.getConsumedPower()) + .isWithin(PRECISION).of(380.0); assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10); assertThat(batteryUsageStats.getDischargedPowerRange().getLower()) .isWithin(PRECISION).of(360.0); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java index 4533fcb39cfe..1a6408ff7eb3 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java @@ -27,7 +27,6 @@ import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; import android.util.SparseArray; @@ -206,16 +205,6 @@ public class BatteryUsageStatsRule implements TestRule { return null; } - public SystemBatteryConsumer getSystemBatteryConsumer( - @SystemBatteryConsumer.DrainType int drainType) { - for (SystemBatteryConsumer sbc : mBatteryUsageStats.getSystemBatteryConsumers()) { - if (sbc.getDrainType() == drainType) { - return sbc; - } - } - return null; - } - public UserBatteryConsumer getUserBatteryConsumer(int userId) { for (UserBatteryConsumer ubc : mBatteryUsageStats.getUserBatteryConsumers()) { if (ubc.getUserId() == userId) { diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java index ad9906b918d7..127cea84ba8c 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.fail; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; import android.os.Parcel; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import androidx.test.filters.SmallTest; @@ -71,7 +70,6 @@ public class BatteryUsageStatsTest { .setDischargePercentage(20) .setDischargedPowerRange(1000, 2000) .setStatsStartTimestamp(1000); - builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid) .setPackageWithHighestDrain("foo") .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000) @@ -87,17 +85,6 @@ public class BatteryUsageStatsTest { .setUsageDurationForCustomComponentMillis( BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 800); - builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_CAMERA) - .setConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU, 10100) - .setConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200) - .setUsageDurationMillis( - BatteryConsumer.POWER_COMPONENT_CPU, 10300) - .setUsageDurationForCustomComponentMillis( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10400) - .setPowerConsumedByApps(20000); - builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) .setConsumedPower( @@ -111,6 +98,7 @@ public class BatteryUsageStatsTest { builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) + .setConsumedPower(30000) .setConsumedPower( BatteryConsumer.POWER_COMPONENT_CPU, 20100) .setConsumedPowerForCustomComponent( @@ -124,10 +112,7 @@ public class BatteryUsageStatsTest { } public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) { - // Camera: (10100 + 10200) - 20000 (consumed by apps) = 300 - // App: 300 + 400 + 500 = 1200 - // Total: 1500 - assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(1500); + assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(30000); assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20); assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(1000); assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(2000); @@ -161,30 +146,6 @@ public class BatteryUsageStatsTest { } } - final List<SystemBatteryConsumer> systemBatteryConsumers = - batteryUsageStats.getSystemBatteryConsumers(); - for (SystemBatteryConsumer systemBatteryConsumer : systemBatteryConsumers) { - if (systemBatteryConsumer.getDrainType() == SystemBatteryConsumer.DRAIN_TYPE_CAMERA) { - assertThat(systemBatteryConsumer.getConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10100); - assertThat(systemBatteryConsumer.getConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10200); - assertThat(systemBatteryConsumer.getUsageDurationMillis( - BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10300); - assertThat(systemBatteryConsumer.getUsageDurationForCustomComponentMillis( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10400); - assertThat(systemBatteryConsumer.getConsumedPower()).isEqualTo(20300); - assertThat(systemBatteryConsumer.getPowerConsumedByApps()).isEqualTo(20000); - assertThat(systemBatteryConsumer.getUsageDurationMillis()) - .isEqualTo(10400); // max - assertThat(systemBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1); - assertThat(systemBatteryConsumer.getCustomPowerComponentName( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO"); - } else { - fail("Unexpected drain type " + systemBatteryConsumer.getDrainType()); - } - } - final BatteryConsumer appsBatteryConsumer = batteryUsageStats.getAggregateBatteryConsumer( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS); assertThat(appsBatteryConsumer.getConsumedPower( diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java index a0de6d3c4573..2de621c8fa6f 100644 --- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java @@ -64,7 +64,9 @@ public class BluetoothPowerCalculatorTest { mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull(); + assertBluetoothPowerAndDuration( + mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), + 0.11388, 6000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); assertBluetoothPowerAndDuration( mStatsRule.getUidBatteryConsumer(APP_UID), 0.24722, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); @@ -95,7 +97,9 @@ public class BluetoothPowerCalculatorTest { mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull(); + assertBluetoothPowerAndDuration( + mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), + 0.1, 6000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); assertBluetoothPowerAndDuration( mStatsRule.getUidBatteryConsumer(APP_UID), 0.2, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); @@ -123,7 +127,9 @@ public class BluetoothPowerCalculatorTest { mStatsRule.apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(), calculator); - assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull(); + assertBluetoothPowerAndDuration( + mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), + 0.10378, 3583, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); assertBluetoothPowerAndDuration( mStatsRule.getUidBatteryConsumer(APP_UID), 0.22950, 8416, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); diff --git a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java index 3fb274323720..f8c2bc6c3d80 100644 --- a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import android.os.BatteryConsumer; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.util.SparseLongArray; @@ -68,15 +67,6 @@ public class CustomMeasuredPowerCalculatorTest { BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1)) .isWithin(PRECISION).of(33.33333); - SystemBatteryConsumer systemConsumer = mStatsRule.getSystemBatteryConsumer( - SystemBatteryConsumer.DRAIN_TYPE_CUSTOM); - assertThat(systemConsumer.getConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)) - .isWithin(PRECISION).of(27.77777); - assertThat(systemConsumer.getConsumedPowerForCustomComponent( - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1)) - .isWithin(PRECISION).of(55.55555); - final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer(); assertThat(deviceBatteryConsumer.getConsumedPowerForCustomComponent( BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)) diff --git a/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java index 159d53a4cf5b..67b1e516d704 100644 --- a/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java @@ -19,7 +19,6 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import android.os.BatteryConsumer; -import android.os.SystemBatteryConsumer; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -46,13 +45,6 @@ public class IdlePowerCalculatorTest { mStatsRule.apply(calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_IDLE); - assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_IDLE)) - .isEqualTo(3000); - assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_IDLE)) - .isWithin(PRECISION).of(0.7); - BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); assertThat(deviceConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_IDLE)) .isEqualTo(3000); diff --git a/core/tests/coretests/src/com/android/internal/os/MemoryPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MemoryPowerCalculatorTest.java index 94e760a4e2e2..4868d6a87228 100644 --- a/core/tests/coretests/src/com/android/internal/os/MemoryPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/MemoryPowerCalculatorTest.java @@ -19,7 +19,6 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import android.os.BatteryConsumer; -import android.os.SystemBatteryConsumer; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -53,8 +52,7 @@ public class MemoryPowerCalculatorTest { mStatsRule.apply(calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_MEMORY); + BatteryConsumer consumer = mStatsRule.getDeviceBatteryConsumer(); assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MEMORY)) .isEqualTo(3000); assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MEMORY)) diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java index 4f5417fe7955..48a1da15d574 100644 --- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java @@ -27,7 +27,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.ModemActivityInfo; @@ -100,17 +99,6 @@ public class MobileRadioPowerCalculatorTest { mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO); - assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(2.2444); - assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertThat(consumer.getConsumedPower()) - .isWithin(PRECISION).of(2.2444); - assertThat(consumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(0.8); - UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID); assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isWithin(PRECISION).of(0.8); @@ -171,17 +159,6 @@ public class MobileRadioPowerCalculatorTest { mStatsRule.apply(calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO); - - // 100000000 uAs * (1 mA / 1000 uA) * (1 h / 3600 s) + 1.53934 (apps)= 4.31711 mAh - assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(4.31711); - assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(consumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(1.53934); - UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID); assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isWithin(PRECISION).of(1.53934); diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java index 144da38e4cb3..4c29c204618a 100644 --- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import android.app.ActivityManager; import android.os.BatteryConsumer; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.view.Display; @@ -82,21 +81,6 @@ public class ScreenPowerCalculatorTest { mStatsRule.apply(calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_SCREEN); - assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isEqualTo(80 * MINUTE_IN_MS); - - // 600000000 uAs * (1 mA / 1000 uA) * (1 h / 3600 s) = 166.66666 mAh - assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isWithin(PRECISION).of(166.66666); - assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(consumer.getConsumedPower()) - .isWithin(PRECISION).of(166.66666); - assertThat(consumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(166.66666); - UidBatteryConsumer uid1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uid1.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN)) .isEqualTo(20 * MINUTE_IN_MS); @@ -130,8 +114,6 @@ public class ScreenPowerCalculatorTest { .isWithin(PRECISION).of(166.66666); assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN)) .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(deviceConsumer.getConsumedPower()) - .isWithin(PRECISION).of(166.66666); BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer(); assertThat(appsConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN)) @@ -141,8 +123,6 @@ public class ScreenPowerCalculatorTest { .isWithin(PRECISION).of(166.66666); assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN)) .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(appsConsumer.getConsumedPower()) - .isWithin(PRECISION).of(166.66666); } @Test @@ -174,19 +154,6 @@ public class ScreenPowerCalculatorTest { mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - SystemBatteryConsumer consumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_SCREEN); - assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isEqualTo(80 * MINUTE_IN_MS); - assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isWithin(PRECISION).of(92.0); - assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertThat(consumer.getConsumedPower()) - .isWithin(PRECISION).of(92.0); - assertThat(consumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(92.0); - UidBatteryConsumer uid1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uid1.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN)) .isEqualTo(20 * MINUTE_IN_MS); diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java index f8655c5b89d2..fc44ddc216b4 100644 --- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java @@ -25,7 +25,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; import android.os.Process; -import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.WorkSource; import android.os.connectivity.WifiActivityEnergyInfo; @@ -94,17 +93,6 @@ public class WifiPowerCalculatorTest { assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - SystemBatteryConsumer systemConsumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI); - assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(5577); - assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isWithin(PRECISION).of(1.11153); - assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertThat(systemConsumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(0.466333); - BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); assertThat(deviceConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(4002); @@ -139,18 +127,6 @@ public class WifiPowerCalculatorTest { assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - SystemBatteryConsumer systemConsumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI); - assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(5577); - /* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */ - assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isWithin(PRECISION).of(1.11153 / (0.2214666 + 0.645200) * 1_000_000 / 3600000); - assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(systemConsumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(0.14946); - BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); assertThat(deviceConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(4002); @@ -196,17 +172,6 @@ public class WifiPowerCalculatorTest { .isWithin(PRECISION).of(0.8231573); assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - - SystemBatteryConsumer systemConsumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI); - assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(2222); - assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isWithin(PRECISION).of(2.575000); - assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertThat(systemConsumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(1.69907); } @Test @@ -228,17 +193,5 @@ public class WifiPowerCalculatorTest { .isWithin(PRECISION).of(0.8231573 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000); assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - - SystemBatteryConsumer systemConsumer = - mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI); - assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(2222); - /* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */ - assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isWithin(PRECISION).of(2.575000 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000); - assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI)) - .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertThat(systemConsumer.getPowerConsumedByApps()) - .isWithin(PRECISION).of(0.277777); } } diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java index b9393fff8896..b3615ff60bce 100644 --- a/graphics/java/android/graphics/FrameInfo.java +++ b/graphics/java/android/graphics/FrameInfo.java @@ -46,7 +46,7 @@ public final class FrameInfo { public static final int FLAGS = 0; // Is this the first-draw following a window layout? - public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1; + public static final long FLAG_WINDOW_VISIBILITY_CHANGED = 1; // A renderer associated with just a Surface, not with a ViewRootImpl instance. public static final long FLAG_SURFACE_CANVAS = 1 << 2; @@ -56,7 +56,7 @@ public final class FrameInfo { public static final long INVALID_VSYNC_ID = -1; @LongDef(flag = true, value = { - FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS }) + FLAG_WINDOW_VISIBILITY_CHANGED, FLAG_SURFACE_CANVAS }) @Retention(RetentionPolicy.SOURCE) public @interface FrameInfoFlags {} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java index 1971ca97d426..55dfc12966a9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java @@ -15,6 +15,7 @@ */ package com.android.wm.shell.bubbles; +import static android.graphics.Paint.ANTI_ALIAS_FLAG; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; @@ -22,10 +23,10 @@ import android.annotation.Nullable; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Path; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.PathParser; import android.widget.ImageView; @@ -75,13 +76,13 @@ public class BadgedImageView extends ImageView { private BubbleViewProvider mBubble; private BubblePositioner mPositioner; + private boolean mOnLeft; private DotRenderer mDotRenderer; private DotRenderer.DrawParams mDrawParams; - private boolean mOnLeft; - private int mDotColor; + private Paint mPaint = new Paint(ANTI_ALIAS_FLAG); private Rect mTempBounds = new Rect(); public BadgedImageView(Context context) { @@ -305,7 +306,7 @@ public class BadgedImageView extends ImageView { } void showBadge() { - Drawable badge = mBubble.getAppBadge(); + Bitmap badge = mBubble.getAppBadge(); if (badge == null) { setImageBitmap(mBubble.getBubbleIcon()); return; @@ -318,13 +319,13 @@ public class BadgedImageView extends ImageView { bubbleCanvas.setBitmap(bubble); final int bubbleSize = bubble.getWidth(); final int badgeSize = (int) (ICON_BADGE_SCALE * bubbleSize); + Rect dest = new Rect(); if (mOnLeft) { - badge.setBounds(0, bubbleSize - badgeSize, badgeSize, bubbleSize); + dest.set(0, bubbleSize - badgeSize, badgeSize, bubbleSize); } else { - badge.setBounds(bubbleSize - badgeSize, bubbleSize - badgeSize, - bubbleSize, bubbleSize); + dest.set(bubbleSize - badgeSize, bubbleSize - badgeSize, bubbleSize, bubbleSize); } - badge.draw(bubbleCanvas); + bubbleCanvas.drawBitmap(badge, null /* src */, dest, mPaint); bubbleCanvas.setBitmap(null); setImageBitmap(bubble); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index f6e92ef0e8ea..afb40d1ff95c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -104,9 +104,10 @@ public class Bubble implements BubbleViewProvider { } private FlyoutMessage mFlyoutMessage; - private Drawable mBadgeDrawable; - // Bitmap with no badge, no dot + // The developer provided image for the bubble private Bitmap mBubbleBitmap; + // The app badge for the bubble + private Bitmap mBadgeBitmap; private int mDotColor; private Path mDotPath; private int mFlags; @@ -242,8 +243,8 @@ public class Bubble implements BubbleViewProvider { } @Override - public Drawable getAppBadge() { - return mBadgeDrawable; + public Bitmap getAppBadge() { + return mBadgeBitmap; } @Override @@ -398,7 +399,7 @@ public class Bubble implements BubbleViewProvider { mAppName = info.appName; mFlyoutMessage = info.flyoutMessage; - mBadgeDrawable = info.badgeDrawable; + mBadgeBitmap = info.badgeBitmap; mBubbleBitmap = info.bubbleBitmap; mDotColor = info.dotColor; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 696f705782c0..d8ec6508d77c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -395,7 +395,6 @@ public class BubbleExpandedView extends LinearLayout { mPointerView.setBackground(mCurrentPointer); } - private String getBubbleKey() { return mBubble != null ? mBubble.getKey() : "null"; } @@ -519,16 +518,11 @@ public class BubbleExpandedView extends LinearLayout { + " bubble=" + getBubbleKey()); } mIsContentVisible = visibility; - - final float alpha = visibility ? 1f : 0f; - - mPointerView.setAlpha(alpha); if (mTaskView != null && !mIsAlphaAnimating) { - mTaskView.setAlpha(alpha); + mTaskView.setAlpha(visibility ? 1f : 0f); } } - @Nullable TaskView getTaskView() { return mTaskView; @@ -673,26 +667,48 @@ public class BubbleExpandedView extends LinearLayout { } /** - * Set the position that the tip of the triangle should point to. + * Sets the position of the pointer. + * + * When bubbles are showing "vertically" they display along the left / right sides of the + * screen with the expanded view beside them. + * + * If they aren't showing vertically they're positioned along the top of the screen with the + * expanded view below them. + * + * @param bubblePosition the x position of the bubble if showing on top, the y position of + * the bubble if showing vertically. + * @param onLeft whether the stack was on the left side of the screen when expanded. */ - public void setPointerPosition(float x, float y, boolean isLandscape, boolean onLeft) { + public void setPointerPosition(float bubblePosition, boolean onLeft) { // Pointer gets drawn in the padding - int paddingLeft = (isLandscape && onLeft) ? mPointerHeight : 0; - int paddingRight = (isLandscape && !onLeft) ? mPointerHeight : 0; - int paddingTop = isLandscape ? 0 : mExpandedViewPadding; + final boolean showVertically = mPositioner.showBubblesVertically(); + final int paddingLeft = (showVertically && onLeft) ? mPointerHeight : 0; + final int paddingRight = (showVertically && !onLeft) ? mPointerHeight : 0; + final int paddingTop = showVertically ? 0 : mExpandedViewPadding; setPadding(paddingLeft, paddingTop, paddingRight, 0); - if (isLandscape) { - // TODO: why setY vs setTranslationY ? linearlayout? - mPointerView.setY(y - (mPointerWidth / 2f)); - mPointerView.setTranslationX(onLeft ? -mPointerHeight : x - mExpandedViewPadding); - } else { - mPointerView.setTranslationY(0f); - mPointerView.setTranslationX(x - mExpandedViewPadding - (mPointerWidth / 2f)); - } - mCurrentPointer = isLandscape ? onLeft ? mLeftPointer : mRightPointer : mTopPointer; - updatePointerView(); - mPointerView.setVisibility(VISIBLE); + final float expandedViewY = mPositioner.getExpandedViewY(); + final float bubbleSize = mPositioner.getBubbleBitmapSize(); + final float bubbleCenter = showVertically + ? bubblePosition + (bubbleSize / 2f) - expandedViewY + : bubblePosition + (bubbleSize / 2f); + // Post because we need the width of the view + post(() -> { + float pointerY; + float pointerX; + if (showVertically) { + pointerY = bubbleCenter - (mPointerWidth / 2f); + pointerX = onLeft ? -mPointerHeight : getWidth() - mPaddingRight; + } else { + pointerY = 0; + pointerX = bubbleCenter - mPaddingLeft - (mPointerWidth / 2f); + } + mPointerView.setTranslationY(pointerY); + mPointerView.setTranslationX(pointerX); + mCurrentPointer = showVertically ? onLeft ? mLeftPointer : mRightPointer : mTopPointer; + updatePointerView(); + mPointerView.setVisibility(VISIBLE); + }); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java index e64ed6a0836c..b83feeedbf21 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java @@ -101,6 +101,12 @@ public class BubbleIconFactory extends BaseIconFactory { userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig()); Canvas c = new Canvas(badgeAndRing); + Paint ringPaint = new Paint(); + ringPaint.setStyle(Paint.Style.FILL); + ringPaint.setColor(importantConversationColor); + ringPaint.setAntiAlias(true); + c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint); + final int bitmapTop = (int) ringStrokeWidth; final int bitmapLeft = (int) ringStrokeWidth; final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth; @@ -110,14 +116,6 @@ public class BubbleIconFactory extends BaseIconFactory { bitmapHeight, /* filter */ true); c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null); - Paint ringPaint = new Paint(); - ringPaint.setStyle(Paint.Style.STROKE); - ringPaint.setColor(importantConversationColor); - ringPaint.setAntiAlias(true); - ringPaint.setStrokeWidth(ringStrokeWidth); - c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2 - ringStrokeWidth, - ringPaint); - shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c); return createIconBitmap(badgeAndRing); } else { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt index 51d63cff385a..36908b854842 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt @@ -24,7 +24,6 @@ import android.graphics.Matrix import android.graphics.Path import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable import android.graphics.drawable.InsetDrawable import android.util.PathParser import android.util.TypedValue @@ -151,7 +150,7 @@ class BubbleOverflow( return dotColor } - override fun getAppBadge(): Drawable? { + override fun getAppBadge(): Bitmap? { return null } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index c4d33877f17d..07d16b57d675 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -2487,7 +2487,7 @@ public class BubbleStackView extends FrameLayout // name and icon. if (show && mBubbleData.hasBubbleInStackWithKey(mExpandedBubble.getKey())) { final Bubble bubble = mBubbleData.getBubbleInStackWithKey(mExpandedBubble.getKey()); - mManageSettingsIcon.setImageDrawable(bubble.getAppBadge()); + mManageSettingsIcon.setImageBitmap(bubble.getAppBadge()); mManageSettingsText.setText(getResources().getString( R.string.bubbles_app_settings, bubble.getAppName())); } @@ -2683,7 +2683,7 @@ public class BubbleStackView extends FrameLayout Log.d(TAG, "updateExpandedView: mIsExpanded=" + mIsExpanded); } boolean isOverflowExpanded = mExpandedBubble != null - && mBubbleOverflow.KEY.equals(mExpandedBubble.getKey()); + && BubbleOverflow.KEY.equals(mExpandedBubble.getKey()); int[] paddings = mPositioner.getExpandedViewPadding( mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded); mExpandedViewContainer.setPadding(paddings[0], 0, paddings[1], 0); @@ -2695,6 +2695,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewContainer.setTranslationX(0f); mExpandedBubble.getExpandedView().updateView( mExpandedViewContainer.getLocationOnScreen()); + updatePointerPosition(); } mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide(); @@ -2732,27 +2733,7 @@ public class BubbleStackView extends FrameLayout return; } float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index); - float expandedViewY = mPositioner.getExpandedViewY(); - if (mPositioner.showBubblesVertically()) { - float x = mStackOnLeftOrWillBe - ? mPositioner.getAvailableRect().left - : mPositioner.getAvailableRect().right - - mExpandedViewContainer.getPaddingRight() - - mPointerHeight; - float bubbleCenter = bubblePosition - expandedViewY + (mBubbleSize / 2f); - mExpandedBubble.getExpandedView().setPointerPosition( - x, - bubbleCenter, - true, - mStackOnLeftOrWillBe); - } else { - float bubbleCenter = bubblePosition + (mBubbleSize / 2f); - mExpandedBubble.getExpandedView().setPointerPosition( - bubbleCenter, - expandedViewY, - false, - mStackOnLeftOrWillBe); - } + mExpandedBubble.getExpandedView().setPointerPosition(bubblePosition, mStackOnLeftOrWillBe); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index fc53ef26dbd9..932f879caef8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -126,7 +126,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask ShortcutInfo shortcutInfo; String appName; Bitmap bubbleBitmap; - Drawable badgeDrawable; + Bitmap badgeBitmap; int dotColor; Path dotPath; Bubble.FlyoutMessage flyoutMessage; @@ -188,7 +188,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon, b.isImportantConversation()); - info.badgeDrawable = badgedIcon; + info.badgeBitmap = badgeBitmapInfo.icon; info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable, null /* user */, true /* shrinkNonAdaptiveIcons */).icon; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java index da4259c42558..38b3ba9dfda0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java @@ -18,7 +18,6 @@ package com.android.wm.shell.bubbles; import android.graphics.Bitmap; import android.graphics.Path; -import android.graphics.drawable.Drawable; import android.view.View; import androidx.annotation.Nullable; @@ -48,7 +47,7 @@ public interface BubbleViewProvider { Bitmap getBubbleIcon(); /** App badge drawable to draw above bubble icon. */ - @Nullable Drawable getAppBadge(); + @Nullable Bitmap getAppBadge(); /** Path of normalized bubble icon to draw dot on. */ Path getDotPath(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAccessibilityUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAccessibilityUtil.java index 130246177fdc..4892e6b1b30f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAccessibilityUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAccessibilityUtil.java @@ -82,7 +82,7 @@ public final class OneHandedAccessibilityUtil { public void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "States: "); + pw.println(TAG); pw.print(innerPrefix + "mPackageName="); pw.println(mPackageName); pw.print(innerPrefix + "mDescription="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java index 703eba9d6af7..481b94817385 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java @@ -203,7 +203,7 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "states: "); + pw.println(TAG); pw.print(innerPrefix + "mIsShowing="); pw.println(mIsShowing); pw.print(innerPrefix + "mBkgBounds="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 04ec3917428e..ae7ab528ed0a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -630,7 +630,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController> public void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "States: "); + pw.println(); + pw.println(TAG); pw.print(innerPrefix + "mOffSetFraction="); pw.println(mOffSetFraction); pw.print(innerPrefix + "mLockedDisabled="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index 1c24338db695..b8da37fd0c25 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -305,7 +305,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "states: "); + pw.println(TAG); pw.print(innerPrefix + "mDisplayLayout.rotation()="); pw.println(mDisplayLayout.rotation()); pw.print(innerPrefix + "mDisplayAreaTokenMap="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java index 9e83a61667b2..03832294aaca 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java @@ -276,7 +276,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback { void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "States: "); + pw.println(TAG); pw.print(innerPrefix + "mAllowGesture="); pw.println(mAllowGesture); pw.print(innerPrefix + "mIsEnabled="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java index 1b2fcdd6313e..2ab51f3f1313 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java @@ -137,8 +137,8 @@ public final class OneHandedSettingsUtil { void dump(PrintWriter pw, String prefix, ContentResolver resolver, int userId) { - final String innerPrefix = prefix + " "; - pw.println(innerPrefix + TAG); + final String innerPrefix = " "; + pw.println(TAG); pw.print(innerPrefix + "isOneHandedModeEnable="); pw.println(getSettingsOneHandedModeEnabled(resolver, userId)); pw.print(innerPrefix + "oneHandedTimeOut="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java index cc874432be87..facc4bd2b6e8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java @@ -90,7 +90,7 @@ public class OneHandedState { /** Dumps internal state. */ public void dump(PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "states: "); + pw.println(TAG); pw.println(innerPrefix + "sCurrentState=" + sCurrentState); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java index 4a98941b7410..899c9ae748d0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java @@ -18,8 +18,6 @@ package com.android.wm.shell.onehanded; import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; -import android.os.Handler; - import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -122,7 +120,7 @@ public class OneHandedTimeoutHandler { void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "states: "); + pw.println(TAG); pw.print(innerPrefix + "sTimeout="); pw.println(mTimeout); pw.print(innerPrefix + "sListeners="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java index c7a49ff01d15..0f9b320791b9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java @@ -156,7 +156,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback { void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + "states: "); + pw.println(TAG); pw.print(innerPrefix + "mLastUpdatedBounds="); pw.println(mLastUpdatedBounds); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java index c60e90315dfc..e8cee8a95c44 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java @@ -224,7 +224,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; - pw.println(TAG + " states: "); + pw.println(TAG); pw.print(innerPrefix + "mTriggerState="); pw.println(mTriggerState); pw.print(innerPrefix + "mDisplayBounds="); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedUiEventLoggerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedUiEventLoggerTest.java index e29fc6a91933..aae1dd0f726f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedUiEventLoggerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedUiEventLoggerTest.java @@ -24,6 +24,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.UiEventLoggerFake; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -51,6 +52,7 @@ public class OneHandedUiEventLoggerTest extends OneHandedTestCase { } @Test + @Ignore("b/184813408, go/wm-tests showing test flaky") public void testLogEvent() { if (mUiEvent != null) { assertEquals(1, mUiEventLogger.numLogs()); diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 1e90b7c71376..17c1404c0d98 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -816,6 +816,11 @@ private: uint32_t mSourceResourceId; }; +static inline bool operator==(const android::ResXMLParser::ResXMLPosition& lhs, + const android::ResXMLParser::ResXMLPosition& rhs) { + return lhs.curNode == rhs.curNode; +} + class DynamicRefTable; /** diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index 2a134fa214e7..540a88b16dc9 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -68,7 +68,7 @@ extern const std::array<const char*, static_cast<int>(FrameInfoIndex::NumIndexes namespace FrameInfoFlags { enum { - WindowLayoutChanged = 1 << 0, + WindowVisibilityChanged = 1 << 0, RTAnimation = 1 << 1, SurfaceCanvas = 1 << 2, SkippedFrame = 1 << 3, diff --git a/mime/java/android/content/type/DefaultMimeMapFactory.java b/mime/java/android/content/type/DefaultMimeMapFactory.java index 11d20d4d6c80..bcd0eb0a9e39 100644 --- a/mime/java/android/content/type/DefaultMimeMapFactory.java +++ b/mime/java/android/content/type/DefaultMimeMapFactory.java @@ -96,7 +96,7 @@ public class DefaultMimeMapFactory { specs.add(spec); startIdx = endIdx + 1; // skip over the space } while (startIdx < line.length()); - builder.put(specs.get(0), specs.subList(1, specs.size())); + builder.addMimeMapping(specs.get(0), specs.subList(1, specs.size())); } } catch (IOException | RuntimeException e) { throw new RuntimeException("Failed to parse " + resourceName, e); diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java index 399cf1f5e0d6..33e5231acee5 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java @@ -42,10 +42,17 @@ public class DeleteStagedFileOnResult extends Activity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - File sourceFile = new File(getIntent().getData().getPath()); - sourceFile.delete(); - setResult(resultCode, data); finish(); } + + @Override + protected void onDestroy() { + super.onDestroy(); + + if (isFinishing()) { + File sourceFile = new File(getIntent().getData().getPath()); + new Thread(sourceFile::delete).start(); + } + } } diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 8b226c926c99..4f587ebba89c 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -50,13 +50,6 @@ java_library { srcs: ["src/com/android/systemui/EventLogTags.logtags"], } -java_library { - name: "SystemUI-sensors", - srcs: [ - "src/com/android/systemui/util/sensors/ThresholdSensor.java", - ], -} - android_library { name: "SystemUI-core", srcs: [ diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 173e95954014..d6989753f16e 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -62,11 +62,13 @@ <!-- Networking and telephony --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> - <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/> - <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> - <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> + <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" + android:usesPermissionFlags="neverForLocation" /> + <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" + android:usesPermissionFlags="neverForLocation" /> + <uses-permission android:name="android.permission.BLUETOOTH_SCAN" + android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp index ab9ab831157c..1b15d20d2c52 100644 --- a/packages/SystemUI/animation/Android.bp +++ b/packages/SystemUI/animation/Android.bp @@ -36,7 +36,6 @@ android_library { static_libs: [ "PluginCoreLib", - "SystemUI-sensors", ], manifest: "AndroidManifest.xml", diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp index 9f02fdbf3ec9..cafaaf854eed 100644 --- a/packages/SystemUI/plugin/Android.bp +++ b/packages/SystemUI/plugin/Android.bp @@ -34,7 +34,6 @@ java_library { static_libs: [ "androidx.annotation_annotation", "PluginCoreLib", - "SystemUI-sensors", "SystemUIAnimationLib", ], diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index b75252b46785..5ac8961aceeb 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -21,7 +21,6 @@ import android.net.Uri; import android.view.MotionEvent; import com.android.systemui.plugins.annotations.ProvidesInterface; -import com.android.systemui.util.sensors.ThresholdSensor; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -118,7 +117,7 @@ public interface FalsingManager { void cleanup(); /** Call to report a ProximityEvent to the FalsingManager. */ - void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent); + void onProximityEvent(ProximityEvent proximityEvent); /** Adds a {@link FalsingBeliefListener}. */ void addFalsingBeliefListener(FalsingBeliefListener listener); @@ -141,4 +140,13 @@ public interface FalsingManager { interface FalsingTapListener { void onDoubleTapRequired(); } + + /** Passed to {@link FalsingManager#onProximityEvent}. */ + interface ProximityEvent { + /** Returns true when the proximity sensor was covered. */ + boolean getCovered(); + + /** Returns when the proximity sensor was covered in nanoseconds. */ + long getTimestampNs(); + } } diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml index 1a38585ea78d..ce63082868bb 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml @@ -40,7 +40,7 @@ android:clipToPadding="false"> <LinearLayout - android:id="@+id/container" + android:id="@+id/pattern_container" android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="vertical" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml index 50ffbc802a7d..c64afd307f23 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml @@ -27,7 +27,7 @@ android:orientation="vertical" > <LinearLayout - android:id="@+id/container" + android:id="@+id/pin_container" android:layout_width="match_parent" android:layout_height="0dp" android:orientation="vertical" diff --git a/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml index 0e308d2f5bfb..da581061370b 100644 --- a/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml +++ b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml @@ -1,12 +1,24 @@ +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:width="16dp" + android:height="16dp" + android:viewportWidth="16.0" + android:viewportHeight="16.0"> <path android:fillColor="#FF000000" - android:pathData="M20.17,14.84l-3.26,-0.65c-0.33,-0.07 -0.67,0.04 -0.9,0.27l-2.62,2.62c-2.75,-1.49 -5.01,-3.75 -6.5,-6.5l2.62,-2.62c0.24,-0.24 0.34,-0.58 0.27,-0.9L9.13,3.8C9.04,3.34 8.63,3 8.15,3H4C3.44,3 2.97,3.47 3,4.03c0.17,2.91 1.04,5.63 2.43,8.01c1.57,2.69 3.81,4.93 6.5,6.5c2.38,1.39 5.1,2.26 8.01,2.43c0.56,0.03 1.03,-0.44 1.03,-1v-4.15C20.97,15.34 20.64,14.93 20.17,14.84z"/> - <path - android:fillColor="#FF000000" - android:pathData="M22,3.41L20.59,2L18.5,4.09L16.41,2L15,3.41l2.09,2.09L15,7.59L16.41,9l2.09,-2.08L20.59,9L22,7.59L19.92,5.5L22,3.41z"/> + android:pathData="M6.52,11.37c0.46,0.37 0.94,0.7 1.45,0.99c1.59,0.93 3.4,1.51 5.34,1.62C13.69,14 14,13.69 14,13.31v-2.77c0,-0.32 -0.23,-0.59 -0.53,-0.65l-2.17,-0.43c-0.22,-0.05 -0.45,0.03 -0.6,0.18l-1.75,1.75c-0.52,-0.28 -1.01,-0.61 -1.48,-0.97l7.61,-7.61l-0.95,-0.94L1.87,14.13l0.94,0.94L6.52,11.37L6.52,11.37zM5.59,8.55C5.22,8.08 4.89,7.58 4.61,7.05l1.75,-1.75c0.16,-0.16 0.23,-0.39 0.18,-0.6L6.1,2.53C6.04,2.23 5.77,2 5.45,2H2.68C2.31,2 1.99,2.31 2.01,2.69c0.11,1.94 0.69,3.75 1.62,5.34c0.3,0.51 0.64,1.01 1.01,1.47L5.59,8.55L5.59,8.55z"/> </vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/qs_media_button_background.xml b/packages/SystemUI/res/drawable/qs_media_button_background.xml index 2241abf130e3..ed9bd263a79d 100644 --- a/packages/SystemUI/res/drawable/qs_media_button_background.xml +++ b/packages/SystemUI/res/drawable/qs_media_button_background.xml @@ -26,4 +26,5 @@ android:right="16dp" android:top="8dp" android:bottom="8dp" /> + <solid android:color="@android:color/transparent" /> </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_carousel.xml b/packages/SystemUI/res/layout/media_carousel.xml index 95cee66af536..87acfd088939 100644 --- a/packages/SystemUI/res/layout/media_carousel.xml +++ b/packages/SystemUI/res/layout/media_carousel.xml @@ -22,7 +22,7 @@ android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" - > + android:theme="@style/MediaPlayer"> <com.android.systemui.media.MediaScrollView android:id="@+id/media_carousel_scroller" android:layout_width="match_parent" @@ -47,7 +47,7 @@ android:layout_width="wrap_content" android:layout_height="48dp" android:layout_marginBottom="4dp" - android:tint="?android:attr/textColorPrimary" + android:tint="?android:attr/textColor" android:forceHasOverlappingRendering="false" /> </FrameLayout> diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index 1c4c89fb254a..8c54e2c1cec4 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -19,7 +19,6 @@ <com.android.systemui.util.animation.TransitionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/media_recommendations" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -28,7 +27,8 @@ android:clipChildren="false" android:clipToPadding="false" android:forceHasOverlappingRendering="false" - android:background="@drawable/qs_media_background"> + android:background="@drawable/qs_media_background" + android:theme="@style/MediaPlayer"> <androidx.constraintlayout.widget.Guideline android:id="@+id/media_vertical_start_guideline" @@ -37,12 +37,19 @@ android:orientation="vertical" app:layout_constraintGuide_percent="0.25" /> - <ImageView + <androidx.constraintlayout.widget.Guideline + android:id="@+id/media_horizontal_center_guideline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + app:layout_constraintGuide_percent="0.5" /> + + <com.android.internal.widget.CachingIconView android:id="@+id/recommendation_card_icon" android:layout_width="@dimen/qs_aa_media_rec_header_icon_size" android:layout_height="@dimen/qs_aa_media_rec_header_icon_size" android:src="@drawable/ic_headset" - android:tint="?android:attr/colorPrimary" /> + android:tint="?android:attr/textColor" /> <TextView android:id="@+id/recommendation_card_text" @@ -51,7 +58,6 @@ android:singleLine="true" android:text="@string/controls_media_smartspace_rec_title" android:fontFamily="google-sans-medium" - android:textColor="?android:attr/colorPrimary" android:textDirection="locale" android:textSize="@dimen/qq_aa_media_rec_header_text_size" /> @@ -61,7 +67,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -69,7 +75,7 @@ android:id="@+id/media_logo1" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover2" @@ -77,7 +83,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -85,7 +91,7 @@ android:id="@+id/media_logo2" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover3" @@ -93,7 +99,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -101,7 +107,7 @@ android:id="@+id/media_logo3" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover4" @@ -109,7 +115,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -117,7 +123,7 @@ android:id="@+id/media_logo4" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover5" @@ -125,7 +131,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -133,7 +139,7 @@ android:id="@+id/media_logo5" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover6" @@ -141,7 +147,7 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" + style="@style/MediaPlayer.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> @@ -149,7 +155,7 @@ android:id="@+id/media_logo6" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" /> + style="@style/MediaPlayer.AppIcon" /> <!-- Long press menu --> <TextView @@ -161,7 +167,6 @@ android:id="@+id/remove_text" android:fontFamily="@*android:string/config_headlineFontFamily" android:singleLine="true" - android:textColor="?android:attr/textColorPrimary" android:text="@string/controls_media_close_session" android:gravity="center_horizontal|top" app:layout_constraintTop_toTopOf="parent" @@ -186,9 +191,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/controls_media_settings_button" /> </FrameLayout> @@ -209,9 +212,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/cancel" /> </FrameLayout> @@ -232,9 +233,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/controls_media_dismiss_button" /> </FrameLayout> diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml index cdced5a1be71..e9a24e284601 100644 --- a/packages/SystemUI/res/layout/media_view.xml +++ b/packages/SystemUI/res/layout/media_view.xml @@ -18,7 +18,6 @@ <!-- Layout for media controls inside QSPanel carousel --> <com.android.systemui.util.animation.TransitionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/qs_media_controls" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -26,7 +25,8 @@ android:clipToPadding="false" android:gravity="center_horizontal|fill_vertical" android:forceHasOverlappingRendering="false" - android:background="@drawable/qs_media_background"> + android:background="@drawable/qs_media_background" + android:theme="@style/MediaPlayer"> <androidx.constraintlayout.widget.Guideline android:id="@+id/center_vertical_guideline" @@ -55,7 +55,6 @@ android:layout_height="wrap_content" android:layout_alignParentStart="true" android:fontFamily="@*android:string/config_bodyFontFamily" - android:textColor="?android:attr/textColorPrimary" android:gravity="start" android:textSize="12sp" /> @@ -65,7 +64,6 @@ android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:fontFamily="@*android:string/config_bodyFontFamily" - android:textColor="?android:attr/textColorPrimary" android:gravity="end" android:textSize="12sp" /> </FrameLayout> @@ -86,31 +84,31 @@ <ImageButton android:id="@+id/action0" - style="@style/MediaPlayer.Button" + style="@style/MediaPlayer.Action" android:layout_width="48dp" android:layout_height="48dp" /> <ImageButton android:id="@+id/action1" - style="@style/MediaPlayer.Button" + style="@style/MediaPlayer.Action" android:layout_width="48dp" android:layout_height="48dp" /> <ImageButton android:id="@+id/action2" - style="@style/MediaPlayer.Button" + style="@style/MediaPlayer.Action" android:layout_width="48dp" android:layout_height="48dp" /> <ImageButton android:id="@+id/action3" - style="@style/MediaPlayer.Button" + style="@style/MediaPlayer.Action" android:layout_width="48dp" android:layout_height="48dp" /> <ImageButton android:id="@+id/action4" - style="@style/MediaPlayer.Button" + style="@style/MediaPlayer.Action" android:layout_width="48dp" android:layout_height="48dp" /> @@ -120,8 +118,8 @@ android:layout_width="@dimen/qs_media_album_size" android:layout_height="@dimen/qs_media_album_size" android:layout_gravity="center_vertical" + style="@style/MediaPlayer.Album" android:background="@drawable/qs_media_art_background" - android:backgroundTint="?androidprv:attr/colorAccentSecondary" android:clipToOutline="true" /> <!-- Seamless Output Switcher --> @@ -138,6 +136,7 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="@dimen/qs_seamless_height" + android:theme="@style/MediaPlayer.SolidButton" android:background="@drawable/qs_media_seamless_background" android:orientation="horizontal" android:contentDescription="@string/quick_settings_media_device_label"> @@ -146,7 +145,6 @@ android:layout_width="@dimen/qs_seamless_icon_size" android:layout_height="@dimen/qs_seamless_icon_size" android:layout_gravity="center" - android:tint="?android:attr/colorPrimary" android:src="@*android:drawable/ic_media_seamless" /> <TextView android:id="@+id/media_seamless_text" @@ -157,7 +155,6 @@ android:fontFamily="@*android:string/config_headlineFontFamily" android:singleLine="true" android:text="@*android:string/ext_media_seamless_action" - android:textColor="?android:attr/colorPrimary" android:textDirection="locale" android:textSize="12sp" /> </LinearLayout> @@ -171,7 +168,7 @@ android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginStart="@dimen/qs_center_guideline_padding" android:layout_marginEnd="@dimen/qs_seamless_fallback_margin" - android:tint="?android:attr/textColorPrimary" + android:tint="?android:attr/textColor" android:src="@drawable/ic_cast_connected" android:forceHasOverlappingRendering="false" /> @@ -179,17 +176,13 @@ <!-- As per Material Design on Biderectionality, this is forced to LTR in code --> <SeekBar android:id="@+id/media_progress_bar" - style="@android:style/Widget.ProgressBar.Horizontal" + style="@style/MediaPlayer.ProgressBar" android:layout_width="0dp" android:layout_height="wrap_content" - android:clickable="true" android:maxHeight="@dimen/qs_media_enabled_seekbar_height" android:paddingTop="@dimen/qs_media_enabled_seekbar_vertical_padding" android:layout_marginTop="-22dp" android:paddingBottom="0dp" - android:thumbTint="?android:attr/textColorPrimary" - android:progressTint="?android:attr/textColorPrimary" - android:progressBackgroundTint="?android:attr/textColorTertiary" android:splitTrack="false" /> <!-- Song name --> @@ -199,7 +192,6 @@ android:layout_height="wrap_content" android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:singleLine="true" - android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" /> <!-- Artist name --> @@ -209,16 +201,14 @@ android:layout_height="wrap_content" android:fontFamily="@*android:string/config_headlineFontFamily" android:singleLine="true" - android:textColor="?android:attr/textColorSecondary" + style="@style/MediaPlayer.Subtitle" android:textSize="14sp" /> <com.android.internal.widget.CachingIconView android:id="@+id/icon" - android:tint="?android:attr/colorAccent" + style="@style/MediaPlayer.AppIcon" android:layout_width="@dimen/qs_media_icon_size" - android:layout_height="@dimen/qs_media_icon_size" - android:background="@drawable/qs_media_icon_background" - /> + android:layout_height="@dimen/qs_media_icon_size" /> <!-- Long press menu --> <TextView @@ -230,7 +220,6 @@ android:id="@+id/remove_text" android:fontFamily="@*android:string/config_headlineFontFamily" android:singleLine="true" - android:textColor="?android:attr/textColorPrimary" android:text="@string/controls_media_close_session" android:gravity="center_horizontal|top" app:layout_constraintTop_toTopOf="parent" @@ -255,9 +244,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/controls_media_settings_button" /> </FrameLayout> @@ -278,9 +265,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/cancel" /> </FrameLayout> @@ -301,9 +286,7 @@ android:layout_gravity="bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/qs_media_button_background" - android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="?android:attr/textColorPrimary" + style="@style/MediaPlayer.OutlineButton" android:text="@string/controls_media_dismiss_button" /> </FrameLayout> diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml index ea644cfca68a..c332f4cf7a39 100644 --- a/packages/SystemUI/res/layout/notification_conversation_info.xml +++ b/packages/SystemUI/res/layout/notification_conversation_info.xml @@ -254,7 +254,6 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/notification_importance_button_description_top_margin" android:visibility="gone" - android:text="@string/notification_channel_summary_priority" android:clickable="false" android:focusable="false" android:ellipsize="end" diff --git a/packages/SystemUI/res/layout/people_tile_empty_layout.xml b/packages/SystemUI/res/layout/people_tile_empty_layout.xml new file mode 100644 index 000000000000..7d3b919ce040 --- /dev/null +++ b/packages/SystemUI/res/layout/people_tile_empty_layout.xml @@ -0,0 +1,29 @@ +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:theme="@android:style/Theme.DeviceDefault.DayNight" + android:background="@drawable/people_space_tile_view_card" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/item" + android:gravity="center" + android:layout_gravity="center" + android:padding="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> +</FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/priority_onboarding_half_shell.xml b/packages/SystemUI/res/layout/priority_onboarding_half_shell.xml deleted file mode 100644 index 3f0e514a9af2..000000000000 --- a/packages/SystemUI/res/layout/priority_onboarding_half_shell.xml +++ /dev/null @@ -1,166 +0,0 @@ -<!-- - ~ Copyright (C) 2020 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License - --> - -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/onboarding_half_shell_container" - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal|bottom" - android:paddingStart="4dp" - android:paddingEnd="4dp" - > - - <LinearLayout - android:id="@+id/half_shell" - android:layout_width="@dimen/qs_panel_width" - android:layout_height="wrap_content" - android:paddingTop="16dp" - android:paddingStart="16dp" - android:paddingEnd="16dp" - android:orientation="vertical" - android:gravity="bottom" - android:layout_gravity="center_horizontal|bottom" - android:background="@drawable/rounded_bg_full" - > - - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:clipChildren="false" - android:clipToPadding="false" - android:padding="12dp" - android:layout_gravity="center_horizontal" - > - - <!-- Big icon: 52x52, 12dp padding left + top, 16dp padding right --> - <ImageView - android:id="@+id/conversation_icon" - android:layout_width="@*android:dimen/conversation_avatar_size" - android:layout_height="@*android:dimen/conversation_avatar_size" - android:scaleType="centerCrop" - android:importantForAccessibility="no" - /> - - <FrameLayout - android:id="@+id/conversation_icon_badge" - android:layout_width="@*android:dimen/conversation_icon_size_badged" - android:layout_height="@*android:dimen/conversation_icon_size_badged" - android:layout_marginLeft="@*android:dimen/conversation_badge_side_margin" - android:layout_marginTop="@*android:dimen/conversation_badge_side_margin" - android:clipChildren="false" - android:clipToPadding="false" - > - <ImageView - android:id="@+id/conversation_icon_badge_bg" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:src="@*android:drawable/conversation_badge_background" - android:forceHasOverlappingRendering="false" - /> - <ImageView - android:id="@+id/icon" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_margin="4dp" - android:layout_gravity="center" - android:forceHasOverlappingRendering="false" - /> - <ImageView - android:id="@+id/conversation_icon_badge_ring" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@*android:drawable/conversation_badge_ring" - android:forceHasOverlappingRendering="false" - android:clipToPadding="false" - android:scaleType="center" - /> - </FrameLayout> - </FrameLayout> - - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - android:layout_marginTop="16dp" - android:text="@string/priority_onboarding_title" - style="@style/TextAppearance.NotificationImportanceChannel" - /> - - <View - android:id="@+id/divider" - android:layout_width="match_parent" - android:layout_height="0.5dp" - android:layout_marginTop="20dp" - android:layout_marginBottom="20dp" - android:background="@color/material_grey_300" /> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="start" - android:text="@string/priority_onboarding_behavior" - style="@style/TextAppearance.NotificationImportanceChannelGroup" - /> - - <TextView - android:id="@+id/behaviors" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="start" - android:layout_marginTop="8dp" - style="@style/TextAppearance.NotificationImportanceChannelGroup" - /> - - <!-- Bottom button container --> - <RelativeLayout - android:id="@+id/button_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="32dp" - android:orientation="horizontal" - > - <TextView - android:id="@+id/settings_button" - android:text="@string/priority_onboarding_settings_button_title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentStart="true" - android:gravity="start|center_vertical" - android:minWidth="@dimen/notification_importance_toggle_size" - android:minHeight="@dimen/notification_importance_toggle_size" - android:maxWidth="125dp" - style="@style/TextAppearance.NotificationInfo.Button"/> - <TextView - android:id="@+id/done_button" - android:text="@string/priority_onboarding_done_button_title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:gravity="end|center_vertical" - android:minWidth="@dimen/notification_importance_toggle_size" - android:minHeight="@dimen/notification_importance_toggle_size" - android:maxWidth="125dp" - style="@style/TextAppearance.NotificationInfo.Button"/> - - </RelativeLayout> - - </LinearLayout> -</FrameLayout> diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 5bf691928300..bb540990ccb7 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -36,7 +36,7 @@ <include layout="@layout/quick_status_bar_header_date_privacy"/> <RelativeLayout - android:id="@+id/container" + android:id="@+id/qs_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index b94e9e8ae1c3..f17067a58b69 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Beweeg na regs onder"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Beweeg na rand en versteek"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Beweeg weg van rand en wys"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"wissel"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Toestelkontroles"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Voeg kontroles vir jou gekoppelde toestelle by"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Stel toestelkontroles op"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Speel"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Fout, probeer tans weer …"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index d2ee53d54a46..d2ecd78df75c 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ታችኛውን ቀኝ አንቀሳቅስ"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ወደ ጠርዝ አንቀሳቅስ እና ደደብቅ"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ጠርዙን ወደ ውጭ አንቀሳቅስ እና አሳይ"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ቀያይር"</string> <string name="quick_controls_title" msgid="6839108006171302273">"የመሣሪያ መቆጣጠሪያዎች"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"ለእርስዎ የተገናኙ መሣሪያዎች መቆጣጠሪያዎችን ያክሉ"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"የመሣሪያ መቆጣጠሪያዎችን ያቀናብሩ"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"አሰናብት"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"አጫውት"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string> <string name="controls_error_retryable" msgid="864025882878378470">"ስህተት፣ እንደገና በመሞከር ላይ…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"አልተገኘም"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index a32a55ce8101..bceb6c9250ae 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"তলৰ সোঁফালে নিয়ক"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"কাষলৈ নিয়ক আৰু লুকুৱাওক"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"কাষৰ বাহিৰলৈ নিয়ক আৰু দেখুৱাওক"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ট’গল কৰক"</string> <string name="quick_controls_title" msgid="6839108006171302273">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহ"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"আপোনাৰ সংযোজিত ডিভাইচৰ বাবে নিয়ন্ত্ৰণ যোগ কৰক"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহ ছেট আপ কৰক"</string> @@ -1087,15 +1086,12 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"অধিক চাবলৈ ছোৱাইপ কৰক"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"এই মিডিয়াৰ ছেশ্বনটো লুকুৱাবনে?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"বৰ্তমানৰ মিডিয়াৰ ছেশ্বনটো লুকুৱাব নোৱাৰি।"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"অগ্ৰাহ্য কৰক"</string> <string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"প্লে’ কৰক"</string> <string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্টো পৰীক্ষা কৰক"</string> <string name="controls_error_retryable" msgid="864025882878378470">"আসোঁৱাহ, পুনৰ চেষ্টা কৰি আছে…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string> @@ -1156,6 +1152,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰ অক্ষম হৈ আছে"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"বিশ্বাসযোগ্যতা প্ৰমাণ কৰক"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইচ আনলক কৰক"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলিবলৈ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 9318906f4a49..466d24ef491d 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Aşağıya sağa köçürün"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"İçəri keçirib gizlədin"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Kənara daşıyıb göstərin"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"keçirin"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Cihaz idarəetmələri"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Qoşulmuş cihazlarınız üçün nizamlayıcılar əlavə edin"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Cihaz idarəetmələrini ayarlayın"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"İmtina edin"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Oxudun"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Xəta, yenidən cəhd edilir…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index eeb3061fe8e7..f1303ce06190 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -1049,8 +1049,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Premesti dole desno"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Premesti do ivice i sakrij"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Premesti izvan ivice i prikaži"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"uključite/isključite"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Podesite kontrole uređaja"</string> @@ -1098,8 +1097,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pusti"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Greška, pokušava se ponovo…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 44f6ff96d323..e857489eff56 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Преместване долу вдясно"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Преместване в края и скриване"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Преместване в края и показване"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"превключване"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Контроли за устройството"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавяне на контроли за свързаните ви устройства"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Настройване на контролите за устройството"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Отхвърляне"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Google Play"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string> <string name="controls_error_retryable" msgid="864025882878378470">"Грешка. Извършва се нов опит…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 959f07b36b92..8f9953ba2a6d 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -1087,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"আরও দেখতে সোয়াইপ করুন"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"এই মিডিয়া সেশন লুকিয়ে রাখতে চান?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"বর্তমান মিডিয়া সেশন লুকিয়ে রাখা যাবে না।"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"খারিজ করুন"</string> <string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string> @@ -1156,6 +1154,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ফিঙ্গারপ্রিন্ট সেন্সর বন্ধ করা আছে"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"যাচাই করিয়ে নিন"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইস আনলক করুন"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 674f049849b0..482c8ad816f9 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -1049,8 +1049,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Pomjeranje dolje desno"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Pomjeranje do ivice i sakrivanje"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Pomjeranje izvan ivice i prikaz"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"aktiviranje/deaktiviranje"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Postavite kontrole uređaja"</string> @@ -1098,8 +1097,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pokrenite"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Greška, ponovni pokušaj…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b9e01021df59..ac86cfbba09e 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mou a baix a la dreta"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mou dins de les vores i amaga"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mou fora de les vores i mostra"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"commuta"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controls de dispositius"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Afegeix controls per als teus dispositius connectats"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configura els controls de dispositius"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reprodueix"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Error. S\'està tornant a provar…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 123b09fc1816..bf969a19d21e 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -1054,8 +1054,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Přesunout vpravo dolů"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Přesunout k okraji a skrýt"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Přesunout okraj ven a zobrazit"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"přepnout"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Ovládání zařízení"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Přidejte si ovládací prvky pro připojená zařízení"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavení ovládání zařízení"</string> @@ -1104,8 +1103,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavřít"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Přehrát"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Chyba. Nový pokus…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 5ccdbf38680a..abcb89e0de39 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Flyt ned til højre"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Flyt ud til kanten, og skjul"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Flyt ud til kanten, og vis"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"slå til/fra"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Enhedsstyring"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Tilføj styring af dine tilsluttede enheder"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurer enhedsstyring"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Luk"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Afspil"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Fejl. Prøver igen…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 6885380b2cc5..2bc8a0392261 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -1087,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"Wischen, um weitere zu sehen"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medien"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"Diese Mediensitzung ausblenden?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"Die Mediensitzung kann nicht ausgeblendet werden."</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ablehnen"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string> @@ -1156,6 +1154,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Fingerabdrucksensor ist deaktiviert"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"zu authentifizieren"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"das Gerät einzugeben"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Mit Fingerabdruck öffnen"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index f8420271d256..545d822c50ac 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Μετακίνηση κάτω δεξιά"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Μετακίν. στο άκρο και απόκρυψη"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Μετακ. εκτός άκρου και εμφάν."</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"εναλλαγή"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Στοιχεία ελέγχου συσκευής"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Προσθήκη στοιχείων ελέγχου για τις συνδεδεμένες συσκευές σας."</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Ρύθμιση στοιχείων ελέγχου συσκευής"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Παράβλεψη"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Play"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Προέκυψε σφάλμα. Επανάληψη…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Δεν βρέθηκε."</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 21ed95421f1f..5292f8741446 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover abajo a la derecha"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover fuera de borde y ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover fuera de borde y mostrar"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar o desactivar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles de dispositivos"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Agrega controles para los dispositivos conectados"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles de dispositivos"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Descartar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Hubo un error. Reintentando…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index eaeaf0b6fbf8..d23f073d387f 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover abajo a la derecha"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover al borde y ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover al borde y mostrar"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar/desactivar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Añade controles para tus dispositivos conectados"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar control de dispositivos"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cerrar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Error; reintentando…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index ceaf3fcadb96..d227dcbfd225 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Teisalda alla paremale"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Teisalda serva ja kuva"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Teisalda servast eemale ja kuva"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"lülita"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Seadmete juhikud"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisage juhtelemendid ühendatud seadmete jaoks"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Seadmete juhtimisvidinate seadistamine"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Loobu"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Esitamine"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Viga, proovitakse uuesti …"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 3cb0b4398f4e..199107c2be56 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Eraman behealdera, eskuinetara"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Eraman ertzera eta ezkutatu"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Atera ertzetik eta erakutsi"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"aldatu"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Gailuak kontrolatzeko widgetak"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu konektatutako gailuak kontrolatzeko widgetak"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfiguratu gailuak kontrolatzeko widgetak"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Erreproduzitu"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Errorea. Berriro saiatzen…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 7e9dabb4089a..d6b018df10b7 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"انتقال به پایین سمت چپ"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"انتقال به لبه و پنهان کردن"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"انتقال به خارج از لبه و نمایش"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"روشن/ خاموش کردن"</string> <string name="quick_controls_title" msgid="6839108006171302273">"کنترلهای دستگاه"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"افزودن کنترلها برای دستگاههای متصل"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"تنظیم کنترلهای دستگاه"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"پخش"</string> <string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string> <string name="controls_error_retryable" msgid="864025882878378470">"خطا، درحال تلاش مجدد…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 89566a6e6e29..d4da4597d56c 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Déplacer dans coin inf. droit"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Éloigner du bord et masquer"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Éloigner du bord et afficher"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"basculer"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajoutez des commandes pour vos appareils connectés"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes des appareils"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Faire jouer"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erreur, nouvelle tentative…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 7f73bab04817..c17bf8ffe906 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Déplacer en bas à droite"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Rapprocher du bord et masquer"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Éloigner du bord et afficher"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activer/désactiver"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajouter des commandes pour vos appareils connectés"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes des appareils"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Lire"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erreur. Nouvelle tentative…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 4a2a93ef0ec1..73d2de64d194 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover á parte inferior dereita"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover ao bordo e ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover fóra do bordo e mostrar"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar/desactivar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Engade controis para os dispositivos conectados"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar o control de dispositivos"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando de novo…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 25eb4163d3e9..4c5308bfc2fd 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -137,8 +137,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string> - <!-- no translation found for accessibility_lock_icon (661492842417875775) --> - <skip /> + <string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string> <string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ફિંગરપ્રિન્ટની રાહ જોઈ રહ્યાં છીએ"</string> <string name="accessibility_unlock_without_fingerprint" msgid="1811563723195375298">"તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કર્યા વગર અનલૉક કરો"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ચહેરો સ્કૅન કરવો"</string> @@ -1088,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"વધુ જોવા માટે સ્વાઇપ કરો"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string> <string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"શું આ મીડિયા સત્ર છુપાવીએ?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"હાલનું મીડિયા સત્ર છુપાવી શકાતું નથી."</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"છોડી દો"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string> @@ -1153,14 +1150,9 @@ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"તમારું બૅટરી મીટર વાંચવામાં સમસ્યા આવી"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"વધુ માહિતી માટે ટૅપ કરો"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"કોઈ અલાર્મ સેટ નથી"</string> - <!-- no translation found for accessibility_fingerprint_label (5255731221854153660) --> - <skip /> - <!-- no translation found for accessibility_udfps_disabled_button (4284034245130239384) --> - <skip /> - <!-- no translation found for accessibility_authenticate_hint (798914151813205721) --> - <skip /> - <!-- no translation found for accessibility_enter_hint (2617864063504824834) --> - <skip /> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"ફિંગરપ્રિન્ટ સેન્સર"</string> + <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ફિંગરપ્રિન્ટ સેન્સર બંધ કરેલું છે"</string> + <string name="accessibility_authenticate_hint" msgid="798914151813205721">"ખાતરી કરો"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"ડિવાઇસ અનલૉક કરો"</string> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ખોલવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 02e4a45751a8..6b03458b0f73 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"सबसे नीचे दाईं ओर ले जाएं"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"एज पर ले जाएं और छिपाएं"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"एज से निकालें और दिखाएं"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"टॉगल करें"</string> <string name="quick_controls_title" msgid="6839108006171302273">"डिवाइस कंट्रोल"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"कनेक्ट किए गए डिवाइस के लिए कंट्रोल जोड़ें"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"डिवाइस कंट्रोल सेट अप करें"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string> <string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"चलाएं"</string> <string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string> <string name="controls_error_retryable" msgid="864025882878378470">"कोई गड़बड़ी हुई, फिर से कोशिश की जा रही है…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string> @@ -1153,6 +1151,6 @@ <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"फ़िंगरप्रिंट सेंसर"</string> <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"फ़िंगरप्रिंट सेंसर बंद है"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"पुष्टि करें"</string> - <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिवाइस अनलॉक करें"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिवाइस की होम स्क्रीन पर जाएं"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"खोलने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 39e628296126..3b4d034c8039 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -1049,8 +1049,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Premjesti u donji desni kut"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Premjesti na rub i sakrij"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Ukloni s ruba i prikaži"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"promijeni"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Postavljanje kontrola uređaja"</string> @@ -1098,8 +1097,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reprodukcija"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string> <string name="controls_error_retryable" msgid="864025882878378470">"Pogreška, pokušavamo ponovo…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 906b45fe13e9..1940cd5ef2ea 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Áthelyezés le és jobbra"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Áthelyezés a szélen kívül és elrejtés"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Áthelyezés a szélen kívül és mutatás"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"váltás"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Eszközvezérlők"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Vezérlők hozzáadása a csatlakoztatott eszközökhöz"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Eszközvezérlők beállítása"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Elvetés"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Játék"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Hiba, újrapróbálkozás…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 630792f1ec4f..aaf2b5d8c31a 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Færa neðst til hægri"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Færa að jaðri og fela"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Færa að jaðri og birta"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"kveikja/slökkva"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Tækjastjórnun"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Bæta við stýringum fyrir tengd tæki"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Setja upp tækjastjórnun"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hunsa"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spila"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Villa, reynir aftur…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 0fd51ec1ad09..40294d5a32fe 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Sposta in basso a destra"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Sposta fino a bordo e nascondi"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Sposta fuori da bordo e mostra"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"attiva/disattiva"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dei dispositivi"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Aggiungi controlli per i dispositivi connessi"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configura il controllo dei dispositivi"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Riproduci"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Errore. Nuovo tentativo…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 98ae9d1ae9d4..0a9cceb32c5b 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -1099,10 +1099,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"יש להחליק כדי להציג עוד פריטים"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ההמלצות בטעינה"</string> <string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"להסתיר את סשן המדיה?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"לא ניתן להסתיר את סשן המדיה הנוכחי."</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"סגירה"</string> <string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string> @@ -1168,6 +1166,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"חיישן טביעות האצבע מושבת"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"אימות"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"הזנת מכשיר"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"שימוש בטביעת אצבע כדי לפתוח"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index c3475017a066..97d94ab4d41c 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"右下に移動"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"端に移動して非表示"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"端から移動して表示"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"切り替え"</string> <string name="quick_controls_title" msgid="6839108006171302273">"デバイス コントロール"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"コネクテッド デバイスのコントロールを追加します"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"デバイス コントロールの設定"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"閉じる"</string> <string name="controls_media_resume" msgid="1933520684481586053">"再開"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"再生"</string> <string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string> <string name="controls_error_retryable" msgid="864025882878378470">"エラー。再試行しています…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index bc8abd42c929..0a181b43d1e7 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Төменгі оң жаққа жылжыту"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Шетке жылжыту және жасыру"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Шетке жылжыту және көрсету"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ауыстыру"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Құрылғыны басқару элементтері"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Жалғанған құрылғылар үшін басқару элементтерін қосу"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Құрылғыны басқару элементтерін реттеу"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Жабу"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ойнату"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string> <string name="controls_error_retryable" msgid="864025882878378470">"Қате, әрекет қайталануда…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 48b80f684471..f872660aa1c8 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ផ្លាស់ទីទៅខាងក្រោមផ្នែកខាងស្ដាំ"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ផ្លាស់ទីទៅផ្នែកខាងចុង រួចលាក់"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ផ្លាស់ទីចេញពីផ្នែកខាងចុង រួចបង្ហាញ"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"បិទ/បើក"</string> <string name="quick_controls_title" msgid="6839108006171302273">"ផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"បញ្ចូលផ្ទាំងគ្រប់គ្រងសម្រាប់ឧបករណ៍ដែលអ្នកបានភ្ជាប់"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"រៀបចំផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string> @@ -1094,8 +1093,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ច្រានចោល"</string> <string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ចាក់"</string> <string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើលកម្មវិធី"</string> <string name="controls_error_retryable" msgid="864025882878378470">"បញ្ហា កំពុងព្យាយាមម្ដងទៀត…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"រកមិនឃើញទេ"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f35c3b28b103..ffc634adbe4f 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -137,8 +137,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್ಲಾಕ್"</string> - <!-- no translation found for accessibility_lock_icon (661492842417875775) --> - <skip /> + <string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string> <string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string> <string name="accessibility_unlock_without_fingerprint" msgid="1811563723195375298">"ನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸದೆಯೇ ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> @@ -1153,14 +1152,10 @@ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ನಿಮ್ಮ ಬ್ಯಾಟರಿ ಮೀಟರ್ ಓದುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ಅಲಾರಾಂ ಸೆಟ್ ಆಗಿಲ್ಲ"</string> - <!-- no translation found for accessibility_fingerprint_label (5255731221854153660) --> - <skip /> - <!-- no translation found for accessibility_udfps_disabled_button (4284034245130239384) --> - <skip /> - <!-- no translation found for accessibility_authenticate_hint (798914151813205721) --> - <skip /> - <!-- no translation found for accessibility_enter_hint (2617864063504824834) --> - <skip /> + <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್"</string> + <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="accessibility_authenticate_hint" msgid="798914151813205721">"ದೃಢೀಕರಿಸಿ"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"ಸಾಧನವನ್ನು ಪ್ರವೇಶಿಸಿ"</string> <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 3c61f44beff2..7d27acba2fd0 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"오른쪽 하단으로 이동"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"가장자리로 옮겨서 숨기기"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"가장자리 바깥으로 옮겨서 표시"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"전환"</string> <string name="quick_controls_title" msgid="6839108006171302273">"기기 컨트롤"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"연결된 기기의 컨트롤을 추가하세요."</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"기기 컨트롤 설정"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"닫기"</string> <string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"재생"</string> <string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string> <string name="controls_error_retryable" msgid="864025882878378470">"오류 발생, 다시 시도 중…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index a0d460b40599..54310c102821 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Баруун доош зөөх"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Ирмэг рүү зөөж, нуух"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Ирмэгээс гаргаж, харуулах"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"асаах/унтраах"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Төхөөрөмжийн хяналт"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Холбогдсон төхөөрөмжүүд дээрээ хяналт нэмэх"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Төхөөрөмжийн хяналтыг тохируулах"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Хаах"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Тоглуулах"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Алдаа, дахин оролдож байна…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 6bbeb52da831..3945370ca7b7 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Alihkan ke bawah sebelah kanan"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Alihkan ke tepi dan sorokkan"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Alihkan ke tepi dan tunjukkan"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"togol"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Kawalan peranti"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Tambah kawalan untuk peranti yang disambungkan"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Sediakan kawalan peranti"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tolak"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Main"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Ralat, mencuba semula…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 649d7c509c65..3dcea65e7701 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Flytt til nederst til høyre"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Flytt til kanten og skjul"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Flytt ut kanten og vis"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"slå av/på"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyring"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Legg til kontroller for de tilkoblede enhetene dine"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurer enhetsstyring"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Lukk"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spill av"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Feil. Prøver igjen …"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 6258e4590a71..cd87cd5401d6 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -137,8 +137,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string> - <!-- no translation found for accessibility_lock_icon (661492842417875775) --> - <skip /> + <string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string> <string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"फिंगरप्रिन्ट कुर्दै"</string> <string name="accessibility_unlock_without_fingerprint" msgid="1811563723195375298">"आफ्नो फिंगरप्रिन्ट बिना नै अनलक गर्नुहोस्"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"अनुहार स्क्यान गर्दै"</string> @@ -1153,14 +1152,10 @@ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"डिभाइसको ब्याट्रीको मिटर रिडिङ क्रममा समस्या भयो"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"थप जानकारी प्राप्त गर्न ट्याप गर्नुहोस्"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"अलार्म राखिएको छैन"</string> - <!-- no translation found for accessibility_fingerprint_label (5255731221854153660) --> - <skip /> - <!-- no translation found for accessibility_udfps_disabled_button (4284034245130239384) --> - <skip /> - <!-- no translation found for accessibility_authenticate_hint (798914151813205721) --> - <skip /> - <!-- no translation found for accessibility_enter_hint (2617864063504824834) --> - <skip /> + <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"फिंगरप्रिन्ट सेन्सर"</string> + <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"फिंगरप्रिन्ट सेन्सर असक्षम पारिएको छ"</string> + <string name="accessibility_authenticate_hint" msgid="798914151813205721">"प्रमाणित गर्नुहोस्"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिभाइस हाल्नुहोस्"</string> <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 0bd3cd589401..d5d094684dd0 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Naar rechtsonder verplaatsen"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Naar rand verplaatsen en verbergen"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Over rand verplaatsen en tonen"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"schakelen"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Apparaatbediening"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Voeg bedieningselementen voor je gekoppelde apparaten toe"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Apparaatbediening instellen"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Sluiten"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Afspelen"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Fout. Opnieuw proberen…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index e9371c60af14..95f1d3589ca4 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ନିମ୍ନ ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ଧାରକୁ ମୁଭ୍ କରି ଲୁଚାନ୍ତୁ"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ଧାର ବାହାରକୁ ମୁଭ୍ କରି ଦେଖାନ୍ତୁ"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ଟୋଗଲ୍ କରନ୍ତୁ"</string> <string name="quick_controls_title" msgid="6839108006171302273">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string> @@ -1087,15 +1086,12 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"ଅଧିକ ଦେଖିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string> <string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"ଏହି ମିଡିଆ ସେସନକୁ ଲୁଚାଇବେ?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"ବର୍ତ୍ତମାନର ମିଡିଆ ସେସନକୁ ଲୁଚାଯାଇପାରିବ ନାହିଁ।"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ଖାରଜ କରନ୍ତୁ"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ଚଲାନ୍ତୁ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="controls_error_retryable" msgid="864025882878378470">"ତ୍ରୁଟି, ପୁଣି ଚେଷ୍ଟା କରୁଛି…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"ମିଳିଲା ନାହିଁ"</string> @@ -1156,6 +1152,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"ପ୍ରମାଣୀକରଣ କରନ୍ତୁ"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"ଡିଭାଇସ୍ ବିଷୟରେ ସୂଚନା ଲେଖନ୍ତୁ"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ଖୋଲିବାକୁ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index fdc20266c18a..e0e1b4f2f119 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -1087,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"ਹੋਰ ਦੇਖਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"ਕੀ ਇਹ ਮੀਡੀਆ ਸੈਸ਼ਨ ਲੁਕਾਉਣਾ ਹੈ?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"ਮੌਜੂਦਾ ਮੀਡੀਆ ਸੈਸ਼ਨ ਲੁਕਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ਖਾਰਜ ਕਰੋ"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string> @@ -1156,6 +1154,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"ਪ੍ਰਮਾਣਿਤ ਕਰੋ"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"ਡੀਵਾਈਸ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ਖੋਲ੍ਹਣ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 4c6c15911a59..d95eabc8c35a 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -1165,6 +1165,6 @@ <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Czytnik linii papilarnych"</string> <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Czytnik linii papilarnych został wyłączony"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"uwierzytelnij"</string> - <string name="accessibility_enter_hint" msgid="2617864063504824834">"dodaj urządzenie"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"otwórz urządzenie"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"By otworzyć, użyj odcisku palca"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index cc60b6a3719f..b786dfb46b03 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover para o canto inferior direito"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover para a borda e ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover para fora da borda e exibir"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"alternar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Iniciar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index c38388d42b9b..496fcb21f838 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover parte inferior direita"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover p/ extremidade e ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Retirar extremidade e mostrar"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ativar/desativar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Adicione controlos para os dispositivos associados."</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configure os controlos de dispositivos"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproduzir"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erro. A tentar novamente…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index cc60b6a3719f..b786dfb46b03 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover para o canto inferior direito"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover para a borda e ocultar"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover para fora da borda e exibir"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"alternar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Iniciar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 4e3fb127ee37..2100466e2cdf 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -1049,8 +1049,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mutați în dreapta jos"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mutați în afară și ascundeți"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mutați în afară și afișați"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"Activați / dezactivați"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Comenzile dispozitivelor"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Adăugați comenzi pentru dispozitivele conectate"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurați comenzile dispozitivelor"</string> @@ -1098,8 +1097,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Închideți"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Redați"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Eroare, se încearcă din nou…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index fe834484ab56..45abf9550ff3 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"පහළ දකුණට ගෙන යන්න"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"මායිමට ගෙන යන්න සහ සඟවන්න"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"මායිමෙන් පිටට ගන්න සහ පෙන්වන්න"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ටොගල් කරන්න"</string> <string name="quick_controls_title" msgid="6839108006171302273">"උපාංග පාලන"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"ඔබේ සම්බන්ධිත උපාංග සඳහා පාලන එක් කරන්න"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"උපාංග පාලන පිහිටුවන්න"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string> <string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"වාදනය කරන්න"</string> <string name="controls_error_timeout" msgid="794197289772728958">"අක්රියයි, යෙදුම පරීක්ෂා කරන්න"</string> <string name="controls_error_retryable" msgid="864025882878378470">"දෝෂයකි, නැවත උත්සාහ කරමින්…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index d947376d1429..63c3b8bc5876 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -1054,8 +1054,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Presunúť doprava nadol"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Presunúť k okraju a skryť"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Presunúť z okraja a zobraziť"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"prepínač"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Ovládanie zariadení"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridajte si ovládače pripojených zariadení"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavenie ovládania zariadení"</string> @@ -1104,8 +1103,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavrieť"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Prehrať"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Chyba, skúša sa znova…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index a0b5081c84ae..f1f7a7a63ff7 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Zhvendos poshtë djathtas"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Zhvendose te skaji dhe fshihe"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Zhvendose jashtë skajit dhe shfaqe"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"aktivizo/çaktivizo"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Kontrollet e pajisjes"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Shto kontrolle për pajisjet e tua të lidhura"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfiguro kontrollet e pajisjes"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hiq"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Luaj"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Gabim, po provohet përsëri"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index de323ecbffd1..22af16a5e242 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -1049,8 +1049,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Премести доле десно"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Премести до ивице и сакриј"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Премести изван ивице и прикажи"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"укључите/искључите"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Контроле уређаја"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Додајте контроле за повезане уређаје"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Подесите контроле уређаја"</string> @@ -1098,8 +1097,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Одбаци"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Пусти"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Грешка, покушава се поново…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index cc7adf5bd078..ebcae0f3ade8 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Flytta längst ned till höger"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Flytta till kanten och dölj"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Flytta från kanten och visa"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"aktivera och inaktivera"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyrning"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Lägg till snabbkontroller för anslutna enheter"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurera enhetsstyrning"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Stäng"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spela upp"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Fel, försöker igen …"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index afa23984d9e8..2a45ce5a0a33 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Sogeza chini kulia"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Sogeza kwenye ukingo kisha ufiche"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Sogeza nje ya ukingo kisha uonyeshe"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"geuza"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Vidhibiti vya vifaa"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Weka vidhibiti vya vifaa ulivyounganisha"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Weka mipangilio ya vidhibiti vya vifaa"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ondoa"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Cheza"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Hitilafu, inajaribu tena…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index ad0e4c751900..63b4c3b8560d 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"கீழே வலதுபுறத்திற்கு நகர்த்து"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ஓரத்திற்கு நகர்த்தி மறை"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ஓரத்திற்கு நகர்த்தி, காட்டு"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"நிலைமாற்று"</string> <string name="quick_controls_title" msgid="6839108006171302273">"சாதனக் கட்டுப்பாடுகள்"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"இணைக்கப்பட்ட சாதனங்களில் கட்டுப்பாடுகளைச் சேர்க்கலாம்"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"சாதனக் கட்டுப்பாடுகளை அமைத்தல்"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"மூடுக"</string> <string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"இயக்குதல்"</string> <string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string> <string name="controls_error_retryable" msgid="864025882878378470">"பிழை, மீண்டும் முயல்கிறது…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 0b030faa82e7..7b05e3620d9b 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -1087,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string> <string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"ఈ మీడియా సెషన్ను దాచాలా?"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"ప్రస్తుత మీడియా సెషన్ను దాచడం సాధ్యం కాదు."</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"విస్మరించు"</string> <string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్లు"</string> @@ -1156,6 +1154,5 @@ <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"వేలిముద్ర సెన్సార్ డిజేబుల్ చేయబడింది"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"ప్రామాణీకరించండి"</string> <string name="accessibility_enter_hint" msgid="2617864063504824834">"పరికరాన్ని ఎంటర్ చేయండి"</string> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"తెరవడానికి వేలిముద్రను ఉపయోగించండి"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 578f8a11bf39..171ecd449b06 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ย้ายไปด้านขาวล่าง"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ย้ายไปที่ขอบและซ่อน"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ย้ายออกจากขอบและแสดง"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"สลับ"</string> <string name="quick_controls_title" msgid="6839108006171302273">"ระบบควบคุมอุปกรณ์"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"เพิ่มตัวควบคุมของอุปกรณ์ที่เชื่อมต่อ"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"ตั้งค่าระบบควบคุมอุปกรณ์"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ปิด"</string> <string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"เล่น"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string> <string name="controls_error_retryable" msgid="864025882878378470">"มีข้อผิดพลาด กำลังลองอีกครั้ง…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"ไม่พบ"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 896eeade63fc..0490ff7ce286 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Ilipat sa kanan sa ibaba"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Ilipat sa sulok at itago"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Alisin sa sulok at ipakita"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"i-toggle"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Mga kontrol ng device"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Magdagdag ng kontrol para sa mga nakakonektang device"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"I-set up ang mga kontrol ng device"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"I-dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"I-play"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Nagka-error, sinusubukan ulit…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index c584d31438b4..12cae9b93216 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Sağ alta taşı"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Kenara taşıyıp gizle"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Kenarın dışına taşıyıp göster"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"değiştir"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Cihaz denetimleri"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Bağlı cihazlarınız için denetimler ekleyin"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Cihaz denetimlerini kur"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Kapat"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Oynat"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Hata, yeniden deneniyor…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 73d5e935a973..4e7de7110672 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -1165,6 +1165,6 @@ <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Сканер відбитків пальців"</string> <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"Сканер відбитків пальців вимкнено"</string> <string name="accessibility_authenticate_hint" msgid="798914151813205721">"пройти автентифікацію"</string> - <string name="accessibility_enter_hint" msgid="2617864063504824834">"виконати вхід на пристрої"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"відкрити пристрій"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Щоб відкрити, використайте відбиток пальця"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 7e9cf556a9c8..702bc7efd36b 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -137,8 +137,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string> - <!-- no translation found for accessibility_lock_icon (661492842417875775) --> - <skip /> + <string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string> <string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"فنگر پرنٹ کا انتظار ہے"</string> <string name="accessibility_unlock_without_fingerprint" msgid="1811563723195375298">"فنگر پرنٹ استعمال کیے بغیرغیر مقفل کریں"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"اسکیننگ چہرہ"</string> @@ -1088,10 +1087,8 @@ <string name="controls_structure_tooltip" msgid="4355922222944447867">"مزید دیکھنے کیلئے سوائپ کریں"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string> <string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string> - <!-- no translation found for controls_media_close_session (1193000643003066508) --> - <skip /> - <!-- no translation found for controls_media_active_session (3146882316024153337) --> - <skip /> + <string name="controls_media_close_session" msgid="1193000643003066508">"اس میڈیا سیشن کو چھپائیں؟"</string> + <string name="controls_media_active_session" msgid="3146882316024153337">"میڈیا کے موجودہ سیشن کو چھپایا نہیں جا سکتا۔"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"برخاست کریں"</string> <string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string> @@ -1153,14 +1150,9 @@ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"آپ کے بیٹری میٹر کو پڑھنے میں دشواری"</string> <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"مزید معلومات کے لیے تھپتھپائیں"</string> <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"کوئی الارم سیٹ نہیں ہے"</string> - <!-- no translation found for accessibility_fingerprint_label (5255731221854153660) --> - <skip /> - <!-- no translation found for accessibility_udfps_disabled_button (4284034245130239384) --> - <skip /> - <!-- no translation found for accessibility_authenticate_hint (798914151813205721) --> - <skip /> - <!-- no translation found for accessibility_enter_hint (2617864063504824834) --> - <skip /> - <!-- no translation found for keyguard_try_fingerprint (2825130772993061165) --> - <skip /> + <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"فنگر پرنٹ سینسر"</string> + <string name="accessibility_udfps_disabled_button" msgid="4284034245130239384">"فنگر پرنٹ سینسر غیر فعال ہے"</string> + <string name="accessibility_authenticate_hint" msgid="798914151813205721">"تصدیق کریں"</string> + <string name="accessibility_enter_hint" msgid="2617864063504824834">"آلہ درج کریں"</string> + <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"کھولنے کے لیے فنگر پرنٹ کا استعمال کریں"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index eb6a27214556..216a0944fcad 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Quyi oʻngga surish"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Chetiga olib borish va yashirish"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Chetidan qaytarish va koʻrsatish"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"oʻzgartirish"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Qurilmalarni boshqarish"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Ulangan qurilmalar uchun boshqaruv elementlari"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Qurilma boshqaruv elementlarini sozlash"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ijro"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Xato, qayta urinilmoqda…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 237036f725c8..a6a9ace99e4c 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Chuyển tới dưới cùng bên phải"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Chuyển đến cạnh và ẩn"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Chuyển ra xa cạnh và hiển thị"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"bật/tắt"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Điều khiển thiết bị"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Thêm các nút điều khiển cho các thiết bị đã kết nối"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Thiết lập các tùy chọn điều khiển thiết bị"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Đóng"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Phát"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Lỗi, đang thử lại…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index aa5e4e2b1824..51b9a545721e 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"移去右下方"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"移到邊緣並隱藏"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"從邊緣移出並顯示"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"切換"</string> <string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"為連接的裝置新增控制選項"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"設定裝置控制"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string> <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"播放"</string> <string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string> <string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"找不到"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index ed44b087f0f8..8a93729c1e34 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"移到右下方"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"移到邊緣並隱藏"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"從邊緣移出並顯示"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"切換"</string> <string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"新增已連結裝置的控制項"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"設定裝置控制項"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string> <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"播放"</string> <string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string> <string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"找不到控制項"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 01e0fca3a89e..674a7c843f5f 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -1044,8 +1044,7 @@ <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Hamba phansi ngakwesokudla"</string> <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Hamba onqenqemeni ufihle"</string> <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Phuma onqenqemeni ubonise"</string> - <!-- no translation found for accessibility_floating_button_action_double_tap_to_toggle (7976492639670692037) --> - <skip /> + <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"guqula"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Izilawuli zezinsiza"</string> <string name="quick_controls_subtitle" msgid="1667408093326318053">"Engeza izilawuli zedivayisi yakho exhunyiwe"</string> <string name="quick_controls_setup_title" msgid="8901436655997849822">"Setha izilawuli zezinsiza"</string> @@ -1092,8 +1091,7 @@ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cashisa"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string> - <!-- no translation found for controls_media_smartspace_rec_title (1699818353932537407) --> - <skip /> + <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Dlala"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string> <string name="controls_error_retryable" msgid="864025882878378470">"Iphutha, iyazama futhi…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 13c285f12393..edd8486379a2 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1279,9 +1279,10 @@ <dimen name="qs_media_disabled_seekbar_vertical_padding">36dp</dimen> <!-- Size of Smartspace media recommendations cards in the QSPanel carousel --> - <dimen name="qs_aa_media_rec_header_icon_padding">10dp</dimen> + <dimen name="qs_aa_media_rec_header_icon_start_margin">10dp</dimen> <dimen name="qs_aa_media_rec_header_icon_size">18dp</dimen> <dimen name="qs_aa_media_rec_album_size">72dp</dimen> + <dimen name="qs_aa_media_rec_album_vertical_margin">8dp</dimen> <dimen name="qq_aa_media_rec_header_text_size">16sp</dimen> <!-- Window magnification --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 673a03ddac4e..d9cc24fa38ef 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1897,13 +1897,16 @@ <string name="notification_channel_summary_automatic_demoted"><b>Status:</b> Ranked Lower</string> <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary --> - <string name="notification_channel_summary_priority">Always shown at the top of your notifications, even when Priority mode is on</string> + <string name="notification_channel_summary_priority_baseline">Shows at the top of conversation notifications and as a profile picture on lock screen</string> + <string name="notification_channel_summary_priority_bubble">Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble</string> + <string name="notification_channel_summary_priority_dnd">Shows at the top of conversation notifications and as a profile picture on lock screen, interrupts Do Not Disturb</string> + <string name="notification_channel_summary_priority_all">Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb</string> <!--[CHAR LIMIT=30] Linkable text to Settings app --> <string name="notification_conversation_channel_settings">Settings</string> <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level --> - <string name="notification_priority_title">Priority conversations</string> + <string name="notification_priority_title">Priority</string> <!-- Text shown in notification guts for conversation notifications that don't implement the full feature --> <string name="no_shortcut"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> doesn\u2019t support conversation features</string> @@ -2667,25 +2670,6 @@ <!-- Title of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=25] --> <string name="inattentive_sleep_warning_title">Standby</string> - <!-- Priority conversation onboarding screen --> - <!-- title of priority onboarding [CHAR LIMIT=75] --> - <string name="priority_onboarding_title">Conversation set to priority</string> - <!-- Text explaining that the following actions are the behaviors of priority conversations. - E.g. priority conversations will show at the top of the conversation section [CHAR LIMIT=75] --> - <string name="priority_onboarding_behavior">Priority conversations</string> - <!-- Text explaining that priority conversations show at the top of the conversation section [CHAR LIMIT=120] --> - <string name="priority_onboarding_show_at_top_text">These conversations are shown at the top of your list and can always reach you when Priority mode is on</string> - <!-- Text explaining that priority conversations show an avatar on the lock screen [CHAR LIMIT=120] --> - <string name="priority_onboarding_show_avatar_text">Profile pictures are shown on the lock screen</string> - <!-- Text explaining that priority conversations will appear as a bubble [CHAR LIMIT=120] --> - <string name="priority_onboarding_appear_as_bubble_text">You can easily find these conversations in bubbles on your Home screen</string> - <!-- Text explaining that priority conversations can interrupt DnD settings [CHAR LIMIT=120] --> - <string name="priority_onboarding_ignores_dnd_text">Interrupt Do Not Disturb</string> - <!-- Title for the affirmative button [CHAR LIMIT=50] --> - <string name="priority_onboarding_done_button_title">Got it</string> - <!-- Title for the settings button button [CHAR LIMIT=50] --> - <string name="priority_onboarding_settings_button_title">Settings</string> - <!-- Window Magnification strings --> <!-- Title for Magnification Window [CHAR LIMIT=NONE] --> <string name="magnification_window_title">Magnification Window</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index ac9ced93f2df..aa1f954cb27a 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -14,7 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="ClearAllButtonDefaultMargins"> <item name="android:layout_marginStart">0dp</item> <item name="android:layout_marginTop">0dp</item> @@ -609,12 +610,54 @@ <item name="android:elevation">10dp</item> </style> - <style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small"> + <!-- Media controls always have light background --> + <style name="MediaPlayer" parent="@*android:style/Theme.DeviceDefault.Light"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:backgroundTint">@android:color/system_accent2_50</item> + </style> + + <style name="MediaPlayer.ProgressBar" parent="@android:style/Widget.ProgressBar.Horizontal"> + <item name="android:thumbTint">?android:attr/textColorPrimary</item> + <item name="android:progressTint">?android:attr/textColorPrimary</item> + <item name="android:progressBackgroundTint">?android:attr/textColorTertiary</item> + <item name="android:clickable">true</item> + <item name="android:splitTrack">false</item> + </style> + + <style name="MediaPlayer.Subtitle" parent="MediaPlayer"> + <item name="android:textColor">?android:attr/textColorSecondary</item> + </style> + + <style name="MediaPlayer.Action" parent="@android:style/Widget.Material.Button.Borderless.Small"> <item name="android:background">@drawable/qs_media_light_source</item> <item name="android:tint">?android:attr/textColorPrimary</item> <item name="android:stateListAnimator">@anim/media_button_state_list_animator</item> </style> + <style name="MediaPlayer.OutlineButton"> + <item name="android:background">@drawable/qs_media_button_background</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:backgroundTint">?androidprv:attr/colorAccentPrimaryVariant</item> + <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item> + </style> + + <style name="MediaPlayer.SolidButton"> + <item name="android:backgroundTint">?android:attr/colorAccent</item> + <item name="android:tint">?android:attr/colorPrimary</item> + <item name="android:textColor">?android:attr/colorPrimary</item> + </style> + + <style name="MediaPlayer.AppIcon"> + <item name="android:background">@drawable/qs_media_icon_background</item> + <item name="android:backgroundTint">?android:attr/colorPrimary</item> + <item name="android:tint">?android:attr/colorAccent</item> + </style> + + <style name="MediaPlayer.Album"> + <item name="android:backgroundTint">?androidprv:attr/colorAccentSecondary</item> + + </style> + <!-- Used to style charging animation AVD animation --> <style name="ChargingAnim" /> diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml index afd800b106c3..31a924cf4892 100644 --- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml +++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml @@ -22,8 +22,8 @@ android:id="@+id/recommendation_card_icon" android:layout_width="@dimen/qs_aa_media_rec_header_icon_size" android:layout_height="@dimen/qs_aa_media_rec_header_icon_size" - android:layout_marginTop="@dimen/qs_aa_media_rec_header_icon_padding" - android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding" + android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_start_margin" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" @@ -33,7 +33,7 @@ android:id="@+id/recommendation_card_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding" + android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_start_margin" app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" @@ -45,9 +45,12 @@ android:layout_height="@dimen/qs_aa_media_rec_album_size" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" app:layout_constraintEnd_toStartOf="@id/media_cover2" app:layout_constraintHorizontal_chainStyle="spread" + app:layout_constraintVertical_chainStyle="spread" android:visibility="gone" /> <Constraint @@ -64,6 +67,8 @@ android:id="@+id/media_cover2" android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" + android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_cover1" @@ -85,6 +90,8 @@ android:id="@+id/media_cover3" android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" + android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_cover2" @@ -112,7 +119,6 @@ app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" app:layout_constraintEnd_toStartOf="@id/media_cover5" app:layout_constraintHorizontal_chainStyle="spread" - app:layout_constraintHorizontal_bias="1" android:visibility="gone" /> <Constraint @@ -134,7 +140,6 @@ app:layout_constraintStart_toEndOf="@+id/media_cover4" app:layout_constraintEnd_toStartOf="@+id/media_cover6" app:layout_constraintHorizontal_chainStyle="spread" - app:layout_constraintHorizontal_bias="1" android:visibility="gone" /> <Constraint diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml index 04a4877f8660..1411030a7431 100644 --- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml +++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml @@ -23,7 +23,7 @@ android:layout_width="@dimen/qs_aa_media_rec_header_icon_size" android:layout_height="@dimen/qs_aa_media_rec_header_icon_size" android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding" + android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_start_margin" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" @@ -33,7 +33,7 @@ android:id="@+id/recommendation_card_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding" + android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_start_margin" app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" @@ -44,11 +44,14 @@ android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_aa_media_rec_album_vertical_margin" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_cover4" + app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" app:layout_constraintEnd_toStartOf="@id/media_cover2" app:layout_constraintHorizontal_chainStyle="spread" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="0" android:visibility="gone" /> <Constraint @@ -66,11 +69,14 @@ android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_aa_media_rec_album_vertical_margin" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_cover5" + app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" app:layout_constraintStart_toEndOf="@id/media_cover1" app:layout_constraintEnd_toStartOf="@id/media_cover3" app:layout_constraintHorizontal_chainStyle="spread" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="0" android:visibility="gone" /> <Constraint @@ -88,12 +94,15 @@ android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginBottom="@dimen/qs_aa_media_rec_album_vertical_margin" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_cover6" + app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" app:layout_constraintStart_toEndOf="@id/media_cover2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="0" android:visibility="gone" /> <Constraint @@ -110,14 +119,15 @@ android:id="@+id/media_cover4" android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" - android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginTop="@dimen/qs_aa_media_rec_album_vertical_margin" android:layout_marginBottom="@dimen/qs_media_padding" - app:layout_constraintTop_toBottomOf="@+id/media_cover1" + app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" app:layout_constraintEnd_toStartOf="@id/media_cover5" app:layout_constraintHorizontal_chainStyle="spread" - app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="1" android:visibility="gone" /> <Constraint @@ -134,14 +144,15 @@ android:id="@+id/media_cover5" android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" - android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginTop="@dimen/qs_aa_media_rec_album_vertical_margin" android:layout_marginBottom="@dimen/qs_media_padding" - app:layout_constraintTop_toBottomOf="@+id/media_cover2" + app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@+id/media_cover4" app:layout_constraintEnd_toStartOf="@+id/media_cover6" app:layout_constraintHorizontal_chainStyle="spread" - app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="1" android:visibility="gone" /> <Constraint @@ -158,14 +169,16 @@ android:id="@+id/media_cover6" android:layout_width="@dimen/qs_aa_media_rec_album_size" android:layout_height="@dimen/qs_aa_media_rec_album_size" - android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginTop="@dimen/qs_aa_media_rec_album_vertical_margin" android:layout_marginBottom="@dimen/qs_media_padding" - app:layout_constraintTop_toBottomOf="@id/media_cover3" + app:layout_constraintTop_toBottomOf="@id/media_horizontal_center_guideline" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_cover5" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_chainStyle="spread" + app:layout_constraintVertical_bias="1" android:visibility="gone" /> <Constraint diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml index cce27e71dbd2..aa24bb49d868 100644 --- a/packages/SystemUI/res/xml/people_space_widget_info.xml +++ b/packages/SystemUI/res/xml/people_space_widget_info.xml @@ -26,5 +26,5 @@ android:previewLayout="@layout/people_space_placeholder_layout" android:resizeMode="horizontal|vertical" android:configure="com.android.systemui.people.PeopleSpaceActivity" - android:initialLayout="@layout/people_space_initial_layout"> + android:initialLayout="@layout/people_tile_empty_layout"> </appwidget-provider> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java index b7a2c64dd107..2325b554d507 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -76,7 +76,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { protected void onFinishInflate() { super.onFinishInflate(); - mContainer = findViewById(R.id.container); + mContainer = findViewById(R.id.pin_container); mRow0 = findViewById(R.id.row0); mRow1 = findViewById(R.id.row1); mRow2 = findViewById(R.id.row2); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index d4513384c569..98e7fb48b7a6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -97,7 +97,7 @@ public class KeyguardPatternView extends KeyguardInputView mLockPatternView = findViewById(R.id.lockPatternView); mEcaView = findViewById(R.id.keyguard_selector_fade_container); - mContainer = findViewById(R.id.container); + mContainer = findViewById(R.id.pattern_container); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index f28d1137f3e7..7f183798709c 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -73,8 +73,7 @@ public final class Prefs { Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, - Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, - Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S + Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT }) // TODO: annotate these with their types so {@link PrefsCommandLine} can know how to set them public @interface Key { @@ -123,8 +122,6 @@ public final class Prefs { String HAS_SEEN_ODI_CAPTIONS_TOOLTIP = "HasSeenODICaptionsTooltip"; String HAS_SEEN_REVERSE_BOTTOM_SHEET = "HasSeenReverseBottomSheet"; String CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT = "ControlsStructureSwipeTooltipCount"; - /** Tracks whether the user has seen the onboarding screen for priority conversations */ - String HAS_SEEN_PRIORITY_ONBOARDING_IN_S = "HasUserSeenPriorityOnboardingInS"; } public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index 58881d9a33f4..c821d100f553 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -35,7 +35,6 @@ import com.android.systemui.dagger.qualifiers.TestHarness; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.util.sensors.ThresholdSensor; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -317,7 +316,7 @@ public class BrightLineFalsingManager implements FalsingManager { } @Override - public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + public void onProximityEvent(ProximityEvent proximityEvent) { // TODO: some of these classifiers might allow us to abort early, meaning we don't have to // make these calls. mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent)); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java index 81b9f66e9bc3..d75752841023 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java @@ -18,7 +18,7 @@ package com.android.systemui.classifier; import android.view.MotionEvent; -import com.android.systemui.util.sensors.ProximitySensor; +import com.android.systemui.plugins.FalsingManager; import java.util.List; @@ -110,7 +110,7 @@ public abstract class FalsingClassifier { /** * Called when a ProximityEvent occurs (change in near/far). */ - void onProximityEvent(ProximitySensor.ThresholdSensorEvent proximityEvent) {} + void onProximityEvent(FalsingManager.ProximityEvent proximityEvent) {} /** * The phone screen has turned on and we need to begin falsing detection. diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 94e5c8ad1536..0f202b085851 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -361,7 +361,7 @@ class FalsingCollectorImpl implements FalsingCollector { private void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { // TODO: some of these classifiers might allow us to abort early, meaning we don't have to // make these calls. - mFalsingManager.onProximityEvent(proximityEvent); + mFalsingManager.onProximityEvent(new ProximityEventImpl(proximityEvent)); } @@ -374,4 +374,21 @@ class FalsingCollectorImpl implements FalsingCollector { Log.d(TAG, msg, throwable); } } + + private static class ProximityEventImpl implements FalsingManager.ProximityEvent { + private ThresholdSensor.ThresholdSensorEvent mThresholdSensorEvent; + + ProximityEventImpl(ThresholdSensor.ThresholdSensorEvent thresholdSensorEvent) { + mThresholdSensorEvent = thresholdSensorEvent; + } + @Override + public boolean getCovered() { + return mThresholdSensorEvent.getBelow(); + } + + @Override + public long getTimestampNs() { + return mThresholdSensorEvent.getTimestampNs(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java index e8445d40836e..ee69e277cc46 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -20,7 +20,6 @@ import android.net.Uri; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.util.sensors.ThresholdSensor; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -133,7 +132,7 @@ public class FalsingManagerFake implements FalsingManager { } @Override - public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + public void onProximityEvent(ProximityEvent proximityEvent) { } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 6b819fbbbcf1..ee0dba0a5087 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -31,7 +31,6 @@ import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.DeviceConfigProxy; -import com.android.systemui.util.sensors.ThresholdSensor; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -186,7 +185,7 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { } @Override - public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + public void onProximityEvent(ProximityEvent proximityEvent) { mInternalFalsingManager.onProximityEvent(proximityEvent); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 72d4303dc0ef..32d9ca59951d 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -25,8 +25,8 @@ import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import android.provider.DeviceConfig; import android.view.MotionEvent; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.DeviceConfigProxy; -import com.android.systemui.util.sensors.ProximitySensor; import java.util.Locale; @@ -107,11 +107,11 @@ class ProximityClassifier extends FalsingClassifier { @Override public void onProximityEvent( - ProximitySensor.ThresholdSensorEvent proximityEvent) { - boolean near = proximityEvent.getBelow(); + FalsingManager.ProximityEvent proximityEvent) { + boolean covered = proximityEvent.getCovered(); long timestampNs = proximityEvent.getTimestampNs(); - logDebug("Sensor is: " + near + " at time " + timestampNs); - update(near, timestampNs); + logDebug("Sensor is: " + covered + " at time " + timestampNs); + update(covered, timestampNs); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java index 2a7023a58637..0cf3333d12a6 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import com.android.systemui.media.dialog.MediaOutputDialogReceiver; import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver; +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; import com.android.systemui.screenshot.ActionProxyReceiver; import com.android.systemui.screenshot.DeleteScreenshotReceiver; import com.android.systemui.screenshot.SmartActionsReceiver; @@ -79,4 +80,13 @@ public abstract class DefaultBroadcastReceiverBinder { public abstract BroadcastReceiver bindPeopleSpaceWidgetPinnedReceiver( PeopleSpaceWidgetPinnedReceiver broadcastReceiver); + /** + * + */ + @Binds + @IntoMap + @ClassKey(PeopleSpaceWidgetProvider.class) + public abstract BroadcastReceiver bindPeopleSpaceWidgetProvider( + PeopleSpaceWidgetProvider broadcastReceiver); + } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 8e4e3081aff2..c04201caa182 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -23,6 +23,7 @@ import com.android.systemui.InitController; import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardSliceProvider; +import com.android.systemui.people.PeopleProvider; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; import com.android.wm.shell.ShellCommandHandler; @@ -156,4 +157,9 @@ public interface SysUIComponent { * Member injection into the supplied argument. */ void inject(ClockOptionsProvider clockOptionsProvider); + + /** + * Member injection into the supplied argument. + */ + void inject(PeopleProvider peopleProvider); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index 8d9a4be30ab6..24503675ae36 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -3,7 +3,6 @@ package com.android.systemui.media import android.app.smartspace.SmartspaceTarget import android.content.Context import android.content.Intent -import android.content.res.ColorStateList import android.content.res.Configuration import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS import android.util.Log @@ -20,6 +19,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PageIndicator +import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.Utils @@ -115,7 +115,6 @@ class MediaCarouselController @Inject constructor( private var needsReordering: Boolean = false private var keysNeedRemoval = mutableSetOf<String>() private var bgColor = getBackgroundColor() - private var fgColor = getForegroundColor() private var isRtl: Boolean = false set(value) { if (value != field) { @@ -156,6 +155,13 @@ class MediaCarouselController @Inject constructor( } } + var visibleToUser: Boolean = false + set(value) { + if (field != value) { + field = value + } + } + init { mediaFrame = inflateMediaCarousel() mediaCarousel = mediaFrame.requireViewById(R.id.media_carousel_scroller) @@ -203,6 +209,9 @@ class MediaCarouselController @Inject constructor( override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) { Log.d(TAG, "My Smartspace media update is here") addSmartspaceMediaRecommendations(key, data) + if (visibleToUser) { + logSmartspaceImpression() + } } override fun onMediaDataRemoved(key: String) { @@ -265,10 +274,6 @@ class MediaCarouselController @Inject constructor( } private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) { - data.actions.forEach { - it.icon?.setTintList(ColorStateList.valueOf(fgColor)) - } - data.appIcon?.setTintList(ColorStateList.valueOf(fgColor)) val dataCopy = data.copy(backgroundColor = bgColor) val existingPlayer = MediaPlayerData.getMediaPlayer(key, oldKey) if (existingPlayer == null) { @@ -317,7 +322,7 @@ class MediaCarouselController @Inject constructor( val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp) - newRecs.bindRecommendation(data, fgColor, bgColor) + newRecs.bindRecommendation(data, bgColor) MediaPlayerData.addMediaPlayer(key, newRecs) updatePlayerToState(newRecs, noAnimation = true) reorderAllPlayers() @@ -357,8 +362,6 @@ class MediaCarouselController @Inject constructor( private fun recreatePlayers() { bgColor = getBackgroundColor() - fgColor = getForegroundColor() - pageIndicator.tintList = ColorStateList.valueOf(fgColor) MediaPlayerData.mediaData().forEach { (key, data) -> removePlayer(key, dismissMediaData = false) @@ -370,11 +373,6 @@ class MediaCarouselController @Inject constructor( return context.getColor(android.R.color.system_accent2_50) } - private fun getForegroundColor(): Int { - return com.android.settingslib.Utils.getColorAttr(context, - com.android.internal.R.attr.textColorPrimary).defaultColor - } - private fun updatePageIndicator() { val numPages = mediaContent.getChildCount() pageIndicator.setNumPages(numPages) @@ -567,6 +565,29 @@ class MediaCarouselController @Inject constructor( mediaCarouselScrollHandler.playerWidthPlusPadding = playerWidthPlusPadding } } + + /** + * Log the user impression for media card. + */ + fun logSmartspaceImpression() { + MediaPlayerData.players().forEach { + // Log every impression of media recommendation card since it will only be shown + // for 1 minute after each connection. + if (it.recommendationViewHolder?.recommendations?.visibility == View.VISIBLE) { + /* ktlint-disable max-line-length */ + SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, + 800, // SMARTSPACE_CARD_SEEN + it.getInstanceId(), + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS, + it.getSurfaceForSmartspaceLogging(), + /* rank */ 0, + /* cardinality */ 1) + /* ktlint-disable max-line-length */ + } + + // TODO(shijieru): add logging for media control card + } + } } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index c713b229670d..1e9cc8cb08cc 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -55,6 +55,7 @@ import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.util.animation.TransitionLayout; +import java.net.URISyntaxException; import java.util.List; import java.util.concurrent.Executor; @@ -69,6 +70,9 @@ public class MediaControlPanel { private static final String TAG = "MediaControlPanel"; private static final float DISABLED_ALPHA = 0.38f; private static final String EXTRAS_MEDIA_SOURCE_PACKAGE_NAME = "package_name"; + private static final String EXTRAS_SMARTSPACE_INTENT = + "com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT"; + private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND"; private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3; private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6; @@ -100,6 +104,8 @@ public class MediaControlPanel { private int mBackgroundColor; private int mDevicePadding; private int mAlbumArtSize; + // Instance id for logging purpose. + private int mInstanceId; private final MediaOutputDialogFactory mMediaOutputDialogFactory; /** @@ -259,9 +265,6 @@ public class MediaControlPanel { ConstraintSet expandedSet = mMediaViewController.getExpandedLayout(); ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); - mPlayerViewHolder.getPlayer().setBackgroundTintList( - ColorStateList.valueOf(mBackgroundColor)); - // Click action PendingIntent clickIntent = data.getClickIntent(); if (clickIntent != null) { @@ -459,15 +462,12 @@ public class MediaControlPanel { /** Bind this recommendation view based on the data given. */ public void bindRecommendation( @NonNull SmartspaceTarget target, - @NonNull int primaryColor, @NonNull int backgroundColor) { if (mRecommendationViewHolder == null) { return; } - mRecommendationViewHolder.getCardIcon().setColorFilter(primaryColor); - mRecommendationViewHolder.getCardText().setTextColor(primaryColor); - + mInstanceId = target.getSmartspaceTargetId().hashCode(); mRecommendationViewHolder.getRecommendations() .setBackgroundTintList(ColorStateList.valueOf(backgroundColor)); mBackgroundColor = backgroundColor; @@ -486,8 +486,10 @@ public class MediaControlPanel { ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); int mediaRecommendationNum = Math.min(mediaRecommendationList.size(), MEDIA_RECOMMENDATION_MAX_NUM); - for (int i = 0; i < mediaRecommendationNum; i++) { - SmartspaceAction recommendation = mediaRecommendationList.get(i); + for (int itemIndex = 0, uiComponentIndex = 0; + itemIndex < mediaRecommendationNum && uiComponentIndex < mediaRecommendationNum; + itemIndex++) { + SmartspaceAction recommendation = mediaRecommendationList.get(itemIndex); if (recommendation.getIcon() == null) { Log.w(TAG, "No media cover is provided. Skipping this item..."); continue; @@ -511,31 +513,38 @@ public class MediaControlPanel { } // Set up media source app's logo. - ImageView mediaSourceLogoImageView = mediaLogoItems.get(i); + ImageView mediaSourceLogoImageView = mediaLogoItems.get(uiComponentIndex); mediaSourceLogoImageView.setImageDrawable(icon); // TODO(b/186699032): Tint the app logo using the accent color. mediaSourceLogoImageView.setColorFilter(backgroundColor, PorterDuff.Mode.XOR); // Set up media item cover. - ImageView mediaCoverImageView = mediaCoverItems.get(i); + ImageView mediaCoverImageView = mediaCoverItems.get(uiComponentIndex); mediaCoverImageView.setImageIcon(recommendation.getIcon()); // Set up the click listener if applicable. setSmartspaceRecItemOnClickListener( mediaCoverImageView, recommendation, - target.getSmartspaceTargetId(), null); - if (i < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) { - setVisibleAndAlpha(collapsedSet, mediaCoverItemsResIds.get(i), true); - setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), true); + if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) { + setVisibleAndAlpha(collapsedSet, + mediaCoverItemsResIds.get(uiComponentIndex), true); + setVisibleAndAlpha(collapsedSet, + mediaLogoItemsResIds.get(uiComponentIndex), true); } else { - setVisibleAndAlpha(collapsedSet, mediaCoverItemsResIds.get(i), false); - setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), false); + setVisibleAndAlpha(collapsedSet, + mediaCoverItemsResIds.get(uiComponentIndex), false); + setVisibleAndAlpha(collapsedSet, + mediaLogoItemsResIds.get(uiComponentIndex), false); } - setVisibleAndAlpha(expandedSet, mediaCoverItemsResIds.get(i), true); - setVisibleAndAlpha(expandedSet, mediaLogoItemsResIds.get(i), true); + setVisibleAndAlpha(expandedSet, + mediaCoverItemsResIds.get(uiComponentIndex), true); + setVisibleAndAlpha(expandedSet, + mediaLogoItemsResIds.get(uiComponentIndex), true); + + uiComponentIndex++; } // Set up long press to show guts setting panel. @@ -635,7 +644,6 @@ public class MediaControlPanel { private void setSmartspaceRecItemOnClickListener( @NonNull View view, @NonNull SmartspaceAction action, - @NonNull String targetId, @Nullable View.OnClickListener callback) { if (view == null || action == null || action.getIntent() == null) { Log.e(TAG, "No tap action can be set up"); @@ -646,24 +654,60 @@ public class MediaControlPanel { // When media recommendation card is shown, there could be only one card. SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, 760, // SMARTSPACE_CARD_CLICK - targetId.hashCode(), + mInstanceId, SysUiStatsLog .SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS, - getSurfaceForSmartspaceLogging(mMediaViewController.getCurrentEndLocation()), - /* rank */ 1, + getSurfaceForSmartspaceLogging(), + /* rank */ 0, /* cardinality */ 1); - mActivityStarter.postStartActivityDismissingKeyguard( - action.getIntent(), - 0 /* delay */, - buildLaunchAnimatorController(mRecommendationViewHolder.getRecommendations())); + if (shouldSmartspaceRecItemOpenInForeground(action)) { + // Request to unlock the device if the activity needs to be opened in foreground. + mActivityStarter.postStartActivityDismissingKeyguard( + action.getIntent(), + 0 /* delay */, + buildLaunchAnimatorController( + mRecommendationViewHolder.getRecommendations())); + } else { + // Otherwise, open the activity in background directly. + view.getContext().startActivity(action.getIntent()); + } + if (callback != null) { callback.onClick(v); } }); } - private int getSurfaceForSmartspaceLogging(int currentEndLocation) { + /** Returns if the Smartspace action will open the activity in foreground. */ + private boolean shouldSmartspaceRecItemOpenInForeground(SmartspaceAction action) { + if (action == null || action.getIntent() == null + || action.getIntent().getExtras() == null) { + return false; + } + + String intentString = action.getIntent().getExtras().getString(EXTRAS_SMARTSPACE_INTENT); + if (intentString == null) { + return false; + } + + try { + Intent wrapperIntent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME); + return wrapperIntent.getBooleanExtra(KEY_SMARTSPACE_OPEN_IN_FOREGROUND, false); + } catch (URISyntaxException e) { + Log.wtf(TAG, "Failed to create intent from URI: " + intentString); + e.printStackTrace(); + } + + return false; + } + + /** + * Get the surface given the current end location for MediaViewController + * @return surface used for Smartspace logging + */ + protected int getSurfaceForSmartspaceLogging() { + int currentEndLocation = mMediaViewController.getCurrentEndLocation(); if (currentEndLocation == MediaHierarchyManager.LOCATION_QQS || currentEndLocation == MediaHierarchyManager.LOCATION_QS) { return SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE; @@ -672,4 +716,8 @@ public class MediaControlPanel { } return SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__DEFAULT_SURFACE; } + + protected int getInstanceId() { + return mInstanceId; + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index 30bc8c1733bc..a80a410d32db 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView import javax.inject.Inject +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager /** * Similarly to isShown but also excludes views that have 0 alpha @@ -73,7 +74,8 @@ class MediaHierarchyManager @Inject constructor( private val bypassController: KeyguardBypassController, private val mediaCarouselController: MediaCarouselController, private val notifLockscreenUserManager: NotificationLockscreenUserManager, - wakefulnessLifecycle: WakefulnessLifecycle + wakefulnessLifecycle: WakefulnessLifecycle, + private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager ) { /** * The root overlay of the hierarchy. This is where the media notification is attached to @@ -162,6 +164,26 @@ class MediaHierarchyManager @Inject constructor( } /** + * Is quick setting expanded? + */ + var qsExpanded: Boolean = false + set(value) { + if (field != value) { + field = value + } + // Pull down shade from lock screen (exclude the case when shade is brought out by + // tapping twice on lock screen) + if (value && isLockScreenShadeVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } + // Release shade and back to lock screen + if (isLockScreenVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } + mediaCarouselController.visibleToUser = isVisibleToUser() + } + + /** * Is the shade currently collapsing from the expanded qs? If we're on the lockscreen and in qs, * we wouldn't want to transition in that case. */ @@ -231,6 +253,11 @@ class MediaHierarchyManager @Inject constructor( override fun onStateChanged(newState: Int) { updateTargetState() + // Enters shade from lock screen + if (newState == StatusBarState.SHADE_LOCKED && isLockScreenShadeVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } + mediaCarouselController.visibleToUser = isVisibleToUser() } override fun onDozeAmountChanged(linear: Float, eased: Float) { @@ -240,9 +267,27 @@ class MediaHierarchyManager @Inject constructor( override fun onDozingChanged(isDozing: Boolean) { if (!isDozing) { dozeAnimationRunning = false + // Enters lock screen from screen off + if (isLockScreenVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } } else { updateDesiredLocation() + qsExpanded = false } + mediaCarouselController.visibleToUser = isVisibleToUser() + } + + override fun onExpandedChanged(isExpanded: Boolean) { + // Enters shade from home screen + if (isHomeScreenShadeVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } + // Back to lock screen from bouncer + if (isLockScreenVisibleToUser()) { + mediaCarouselController.logSmartspaceImpression() + } + mediaCarouselController.visibleToUser = isVisibleToUser() } }) @@ -622,6 +667,36 @@ class MediaHierarchyManager @Inject constructor( return location } + /** + * Returns true when the media card could be visible to the user if existed. + */ + private fun isVisibleToUser(): Boolean { + return isLockScreenVisibleToUser() || isLockScreenShadeVisibleToUser() || + isHomeScreenShadeVisibleToUser() + } + + private fun isLockScreenVisibleToUser(): Boolean { + return !statusBarStateController.isDozing && + !statusBarKeyguardViewManager.isBouncerShowing && + statusBarStateController.state == StatusBarState.KEYGUARD && + notifLockscreenUserManager.shouldShowLockscreenNotifications() && + statusBarStateController.isExpanded && + !qsExpanded + } + + private fun isLockScreenShadeVisibleToUser(): Boolean { + return !statusBarStateController.isDozing && + !statusBarKeyguardViewManager.isBouncerShowing && + (statusBarStateController.state == StatusBarState.SHADE_LOCKED || + (statusBarStateController.state == StatusBarState.KEYGUARD && qsExpanded)) + } + + private fun isHomeScreenShadeVisibleToUser(): Boolean { + return !statusBarStateController.isDozing && + statusBarStateController.state == StatusBarState.SHADE && + statusBarStateController.isExpanded + } + companion object { /** * Attached in expanded quick settings diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java index a9640566d531..0f6645641dda 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java @@ -30,12 +30,15 @@ import android.widget.RemoteViews; import com.android.systemui.people.widget.PeopleSpaceWidgetManager; import com.android.systemui.shared.system.PeopleProviderUtils; +import javax.inject.Inject; + /** API that returns a People Tile preview. */ public class PeopleProvider extends ContentProvider { private static final String TAG = "PeopleProvider"; private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private static final String EMPTY_STRING = ""; + @Inject PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; @Override @@ -76,7 +79,8 @@ public class PeopleProvider extends ContentProvider { } if (mPeopleSpaceWidgetManager == null) { - mPeopleSpaceWidgetManager = new PeopleSpaceWidgetManager(getContext()); + Log.e(TAG, "Could not initialize people widget manager"); + return null; } RemoteViews view = mPeopleSpaceWidgetManager.getPreview(shortcutId, userHandle, packageName, extras); diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java index 99a17ffbe77a..a6c6103ae4c5 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java @@ -23,11 +23,11 @@ import static com.android.systemui.people.NotificationHelper.hasReadContactsPerm import static com.android.systemui.people.NotificationHelper.isMissedCall; import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri; +import android.annotation.Nullable; import android.app.Notification; import android.app.people.ConversationChannel; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; -import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.LauncherApps; @@ -40,13 +40,11 @@ import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Bundle; import android.os.UserManager; import android.provider.ContactsContract; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; -import android.widget.RemoteViews; import androidx.preference.PreferenceManager; @@ -56,7 +54,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.util.ArrayUtils; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.R; -import com.android.systemui.people.widget.AppWidgetOptionsHelper; +import com.android.systemui.people.widget.PeopleSpaceWidgetManager; import com.android.systemui.people.widget.PeopleTileKey; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -76,45 +74,17 @@ import java.util.stream.Stream; public class PeopleSpaceUtils { /** Turns on debugging information about People Space. */ public static final boolean DEBUG = true; - private static final String TAG = "PeopleSpaceUtils"; public static final String PACKAGE_NAME = "package_name"; public static final String USER_ID = "user_id"; public static final String SHORTCUT_ID = "shortcut_id"; - public static final String EMPTY_STRING = ""; public static final int INVALID_USER_ID = -1; - public static final PeopleTileKey EMPTY_KEY = new PeopleTileKey(EMPTY_STRING, INVALID_USER_ID, EMPTY_STRING); - - /** Represents whether {@link StatusBarNotification} was posted or removed. */ - public enum NotificationAction { - POSTED, - REMOVED - } - - /** - * The UiEvent enums that this class can log. - */ - public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum { - @UiEvent(doc = "People space widget deleted") - PEOPLE_SPACE_WIDGET_DELETED(666), - @UiEvent(doc = "People space widget added") - PEOPLE_SPACE_WIDGET_ADDED(667), - @UiEvent(doc = "People space widget clicked to launch conversation") - PEOPLE_SPACE_WIDGET_CLICKED(668); - - private final int mId; - - PeopleSpaceWidgetEvent(int id) { - mId = id; - } - - @Override - public int getId() { - return mId; - } - } + static final float STARRED_CONTACT = 1f; + static final float VALID_CONTACT = .5f; + static final float DEFAULT_AFFINITY = 0f; + private static final String TAG = "PeopleSpaceUtils"; /** Returns stored widgets for the conversation specified. */ public static Set<String> getStoredWidgetIds(SharedPreferences sp, PeopleTileKey key) { @@ -127,6 +97,10 @@ public class PeopleSpaceUtils { /** Sets all relevant storage for {@code appWidgetId} association to {@code tile}. */ public static void setSharedPreferencesStorageForTile(Context context, PeopleTileKey key, int appWidgetId, Uri contactUri) { + if (!key.isValid()) { + Log.e(TAG, "Not storing for invalid key"); + return; + } // Write relevant persisted storage. SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(appWidgetId), Context.MODE_PRIVATE); @@ -201,7 +175,7 @@ public class PeopleSpaceUtils { .collect(Collectors.toList()); } - /** Returns the total messages in {@code notificationEntries}.*/ + /** Returns the total messages in {@code notificationEntries}. */ public static int getMessagesCount(Set<NotificationEntry> notificationEntries) { if (DEBUG) { Log.d(TAG, "Calculating messages count from " + notificationEntries.size() @@ -247,19 +221,34 @@ public class PeopleSpaceUtils { * {@code messagesCount}. */ public static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile, - PeopleTileKey key, NotificationEntry notificationEntry, int messagesCount) { + PeopleTileKey key, NotificationEntry notificationEntry, int messagesCount, + Optional<Integer> appWidgetId) { if (notificationEntry == null || notificationEntry.getSbn().getNotification() == null) { if (DEBUG) Log.d(TAG, "Tile key: " + key.toString() + ". Notification is null"); return removeNotificationFields(tile); } Notification notification = notificationEntry.getSbn().getNotification(); + + PeopleSpaceTile.Builder updatedTile = tile.toBuilder(); + String uriFromNotification = getContactUri(notificationEntry.getSbn()); + if (appWidgetId.isPresent() && tile.getContactUri() == null && !TextUtils.isEmpty( + uriFromNotification)) { + if (DEBUG) Log.d(TAG, "Add uri from notification to tile: " + uriFromNotification); + Uri contactUri = Uri.parse(uriFromNotification); + // Update storage. + setSharedPreferencesStorageForTile(context, new PeopleTileKey(tile), appWidgetId.get(), + contactUri); + // Update cached tile in-memory. + updatedTile.setContactUri(contactUri); + } + boolean isMissedCall = isMissedCall(notification); List<Notification.MessagingStyle.Message> messages = getMessagingStyleMessages(notification); if (!isMissedCall && ArrayUtils.isEmpty(messages)) { if (DEBUG) Log.d(TAG, "Tile key: " + key.toString() + ". Notification has no content"); - return removeNotificationFields(tile); + return removeNotificationFields(updatedTile.build()); } // messages are in chronological order from most recent to least. @@ -276,8 +265,7 @@ public class PeopleSpaceUtils { } CharSequence sender = getSenderIfGroupConversation(notification, message); - return tile - .toBuilder() + return updatedTile .setNotificationKey(notificationEntry.getSbn().getKey()) .setNotificationCategory(notification.category) .setNotificationContent(content) @@ -378,17 +366,18 @@ public class PeopleSpaceUtils { context.getString(R.string.birthday_status)); } - /** Calls to retrieve birthdays on a background thread. */ - public static void getBirthdaysOnBackgroundThread(Context context, - AppWidgetManager appWidgetManager, + /** Calls to retrieve birthdays & contact affinity on a background thread. */ + public static void getDataFromContactsOnBackgroundThread(Context context, + PeopleSpaceWidgetManager manager, Map<Integer, PeopleSpaceTile> peopleSpaceTiles, int[] appWidgetIds) { ThreadUtils.postOnBackgroundThread( - () -> getBirthdays(context, appWidgetManager, peopleSpaceTiles, appWidgetIds)); + () -> getDataFromContacts(context, manager, peopleSpaceTiles, appWidgetIds)); } - /** Queries the Contacts DB for any birthdays today. */ + /** Queries the Contacts DB for any birthdays today & updates contact affinity. */ @VisibleForTesting - public static void getBirthdays(Context context, AppWidgetManager appWidgetManager, + public static void getDataFromContacts(Context context, + PeopleSpaceWidgetManager peopleSpaceWidgetManager, Map<Integer, PeopleSpaceTile> widgetIdToTile, int[] appWidgetIds) { if (DEBUG) Log.d(TAG, "Get birthdays"); if (appWidgetIds.length == 0) return; @@ -397,28 +386,37 @@ public class PeopleSpaceUtils { PeopleSpaceTile storedTile = widgetIdToTile.get(appWidgetId); if (storedTile == null || storedTile.getContactUri() == null) { if (DEBUG) Log.d(TAG, "No contact uri for: " + storedTile); - removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId); - continue; - } - if (lookupKeysWithBirthdaysToday.isEmpty()) { - if (DEBUG) Log.d(TAG, "No birthdays today"); - removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId); + updateTileContactFields(peopleSpaceWidgetManager, context, storedTile, + appWidgetId, DEFAULT_AFFINITY, /* birthdayString= */ null); continue; } - updateTileWithBirthday(context, appWidgetManager, lookupKeysWithBirthdaysToday, + updateTileWithBirthdayAndUpdateAffinity(context, peopleSpaceWidgetManager, + lookupKeysWithBirthdaysToday, storedTile, appWidgetId); } } - /** Removes the birthday status if present in {@code storedTile} and pushes the update. */ - private static void removeBirthdayStatusIfPresent(AppWidgetManager appWidgetManager, - Context context, PeopleSpaceTile storedTile, int appWidgetId) { - if (hasBirthdayStatus(storedTile, context)) { - if (DEBUG) Log.d(TAG, "Remove " + storedTile.getUserName() + "'s birthday"); - updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, + /** + * Updates the {@code storedTile} with {@code affinity} & {@code birthdayString} if + * necessary. + */ + private static void updateTileContactFields(PeopleSpaceWidgetManager manager, + Context context, PeopleSpaceTile storedTile, int appWidgetId, float affinity, + @Nullable String birthdayString) { + boolean outdatedBirthdayStatus = hasBirthdayStatus(storedTile, context) + && birthdayString == null; + boolean addBirthdayStatus = !hasBirthdayStatus(storedTile, context) + && birthdayString != null; + boolean shouldUpdate = + storedTile.getContactAffinity() != affinity || outdatedBirthdayStatus + || addBirthdayStatus; + if (shouldUpdate) { + if (DEBUG) Log.d(TAG, "Update " + storedTile.getUserName() + " from contacts"); + manager.updateAppWidgetOptionsAndView(appWidgetId, storedTile.toBuilder() - .setBirthdayText(null) + .setBirthdayText(birthdayString) + .setContactAffinity(affinity) .build()); } } @@ -427,7 +425,8 @@ public class PeopleSpaceUtils { * Update {@code storedTile} if the contact has a lookup key matched to any {@code * lookupKeysWithBirthdays}. */ - private static void updateTileWithBirthday(Context context, AppWidgetManager appWidgetManager, + private static void updateTileWithBirthdayAndUpdateAffinity(Context context, + PeopleSpaceWidgetManager manager, List<String> lookupKeysWithBirthdaysToday, PeopleSpaceTile storedTile, int appWidgetId) { Cursor cursor = null; @@ -437,14 +436,16 @@ public class PeopleSpaceUtils { while (cursor != null && cursor.moveToNext()) { String storedLookupKey = cursor.getString( cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)); + float affinity = getContactAffinity(cursor); if (!storedLookupKey.isEmpty() && lookupKeysWithBirthdaysToday.contains( storedLookupKey)) { if (DEBUG) Log.d(TAG, storedTile.getUserName() + "'s birthday today!"); - updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, - storedTile.toBuilder() - .setBirthdayText(context.getString(R.string.birthday_status)) - .build()); - return; + updateTileContactFields(manager, context, storedTile, appWidgetId, + affinity, /* birthdayString= */ + context.getString(R.string.birthday_status)); + } else { + updateTileContactFields(manager, context, storedTile, appWidgetId, + affinity, /* birthdayString= */ null); } } } catch (SQLException e) { @@ -454,51 +455,20 @@ public class PeopleSpaceUtils { cursor.close(); } } - removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId); - } - - /** Updates the current widget view with provided {@link PeopleSpaceTile}. */ - public static void updateAppWidgetViews(AppWidgetManager appWidgetManager, - Context context, int appWidgetId, PeopleSpaceTile tile, Bundle options) { - if (tile == null) { - if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + ". Tile is null, skipping update"); - return; - } - if (DEBUG) { - Log.d(TAG, "Widget: " + appWidgetId + ", " + tile.getUserName() + ", " - + tile.getPackageName() + ". Updating app widget view."); - } - RemoteViews views = new PeopleTileViewHelper(context, tile, appWidgetId, - options).getViews(); - - // Tell the AppWidgetManager to perform an update on the current app widget. - appWidgetManager.updateAppWidget(appWidgetId, views); - } - - /** Updates tile in app widget options and the current view. */ - public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager, - Context context, int appWidgetId, PeopleSpaceTile tile) { - if (tile == null) { - if (DEBUG) { - Log.w(TAG, "Widget: " + appWidgetId + "Tile is null, skipping storage and update."); - } - return; - } - Bundle options = AppWidgetOptionsHelper.setPeopleTile(appWidgetManager, appWidgetId, tile); - updateAppWidgetViews(appWidgetManager, context, appWidgetId, tile, options); } - /** Wrapper around {@link #updateAppWidgetOptionsAndView} with optional tile as a parameter. */ - public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager, - Context context, int appWidgetId, Optional<PeopleSpaceTile> optionalTile) { - if (!optionalTile.isPresent()) { - if (DEBUG) { - Log.w(TAG, "Widget: " + appWidgetId - + "Optional tile is not present, skipping storage and update."); + /** Pulls the contact affinity from {@code cursor}. */ + private static float getContactAffinity(Cursor cursor) { + float affinity = VALID_CONTACT; + int starIdx = cursor.getColumnIndex(ContactsContract.Contacts.STARRED); + if (starIdx >= 0) { + boolean isStarred = cursor.getInt(starIdx) != 0; + if (isStarred) { + affinity = Math.max(affinity, STARRED_CONTACT); } - return; } - updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, optionalTile.get()); + if (DEBUG) Log.d(TAG, "Affinity is: " + affinity); + return affinity; } /** @@ -546,4 +516,33 @@ public class PeopleSpaceUtils { public static int getUserId(PeopleSpaceTile tile) { return tile.getUserHandle().getIdentifier(); } + + /** Represents whether {@link StatusBarNotification} was posted or removed. */ + public enum NotificationAction { + POSTED, + REMOVED + } + + /** + * The UiEvent enums that this class can log. + */ + public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "People space widget deleted") + PEOPLE_SPACE_WIDGET_DELETED(666), + @UiEvent(doc = "People space widget added") + PEOPLE_SPACE_WIDGET_ADDED(667), + @UiEvent(doc = "People space widget clicked to launch conversation") + PEOPLE_SPACE_WIDGET_CLICKED(668); + + private final int mId; + + PeopleSpaceWidgetEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index a23db63a70fc..6980d723583b 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -30,6 +30,8 @@ import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH; +import static com.android.systemui.people.PeopleSpaceUtils.STARRED_CONTACT; +import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT; import static com.android.systemui.people.PeopleSpaceUtils.convertDrawableToBitmap; import static com.android.systemui.people.PeopleSpaceUtils.getUserId; @@ -39,6 +41,8 @@ import android.app.people.ConversationStatus; import android.app.people.PeopleSpaceTile; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; @@ -48,6 +52,7 @@ import android.icu.util.Measure; import android.icu.util.MeasureUnit; import android.net.Uri; import android.os.Bundle; +import android.os.UserHandle; import android.text.TextUtils; import android.util.IconDrawableFactory; import android.util.Log; @@ -57,6 +62,8 @@ import android.widget.RemoteViews; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; +import com.android.launcher3.icons.FastBitmapDrawable; +import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.people.widget.LaunchConversationActivity; import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; @@ -142,7 +149,9 @@ public class PeopleTileViewHelper { private int mMediumVerticalPadding; private Context mContext; + @Nullable private PeopleSpaceTile mTile; + private PeopleTileKey mKey; private float mDensity; private int mAppWidgetId; private int mWidth; @@ -152,10 +161,11 @@ public class PeopleTileViewHelper { private Locale mLocale; private NumberFormat mIntegerFormat; - public PeopleTileViewHelper(Context context, PeopleSpaceTile tile, - int appWidgetId, Bundle options) { + public PeopleTileViewHelper(Context context, @Nullable PeopleSpaceTile tile, + int appWidgetId, Bundle options, PeopleTileKey key) { mContext = context; mTile = tile; + mKey = key; mAppWidgetId = appWidgetId; mDensity = mContext.getResources().getDisplayMetrics().density; int display = mContext.getResources().getConfiguration().orientation; @@ -184,8 +194,19 @@ public class PeopleTileViewHelper { * content, then birthdays, then the most recent status, and finally last interaction. */ private RemoteViews getViewForTile() { - PeopleTileKey key = new PeopleTileKey(mTile); - if (DEBUG) Log.d(TAG, "Creating view for tile key: " + key.toString()); + if (DEBUG) Log.d(TAG, "Creating view for tile key: " + mKey.toString()); + if (mTile == null || mTile.isPackageSuspended() || mTile.isUserQuieted()) { + if (DEBUG) Log.d(TAG, "Create empty view: " + mTile); + return createEmptyView(); + } + + boolean dndBlockingTileData = isDndBlockingTileData(mTile); + if (dndBlockingTileData) { + if (DEBUG) Log.d(TAG, "Create DND view: " + mTile.getNotificationPolicyState()); + // TODO: Create DND view. + return createEmptyView(); + } + if (Objects.equals(mTile.getNotificationCategory(), CATEGORY_MISSED_CALL)) { if (DEBUG) Log.d(TAG, "Create missed call view"); return createMissedCallRemoteViews(); @@ -217,6 +238,58 @@ public class PeopleTileViewHelper { return createLastInteractionRemoteViews(); } + private boolean isDndBlockingTileData(PeopleSpaceTile tile) { + int notificationPolicyState = tile.getNotificationPolicyState(); + if ((notificationPolicyState & PeopleSpaceTile.SHOW_CONVERSATIONS) != 0) { + // Not in DND, or all conversations + if (DEBUG) Log.d(TAG, "Tile can show all data: " + tile.getUserName()); + return false; + } + if ((notificationPolicyState & PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS) != 0 + && tile.isImportantConversation()) { + if (DEBUG) Log.d(TAG, "Tile can show important: " + tile.getUserName()); + return false; + } + if ((notificationPolicyState & PeopleSpaceTile.SHOW_STARRED_CONTACTS) != 0 + && tile.getContactAffinity() == STARRED_CONTACT) { + if (DEBUG) Log.d(TAG, "Tile can show starred: " + tile.getUserName()); + return false; + } + if ((notificationPolicyState & PeopleSpaceTile.SHOW_CONTACTS) != 0 + && (tile.getContactAffinity() == VALID_CONTACT + || tile.getContactAffinity() == STARRED_CONTACT)) { + if (DEBUG) Log.d(TAG, "Tile can show contacts: " + tile.getUserName()); + return false; + } + if (DEBUG) Log.d(TAG, "Tile can show if can bypass DND: " + tile.getUserName()); + return !tile.canBypassDnd(); + } + + private RemoteViews createEmptyView() { + RemoteViews views = new RemoteViews(mContext.getPackageName(), + R.layout.people_tile_empty_layout); + Drawable appIcon = getAppBadge(mKey.getPackageName(), mKey.getUserId()); + Bitmap appIconAsBitmap = convertDrawableToBitmap(appIcon); + FastBitmapDrawable drawable = new FastBitmapDrawable( + appIconAsBitmap); + drawable.setIsDisabled(true); + Bitmap convertedBitmap = convertDrawableToBitmap(drawable); + views.setImageViewBitmap(R.id.item, convertedBitmap); + return views; + } + + private Drawable getAppBadge(String packageName, int userId) { + Drawable badge = null; + try { + final ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfoAsUser( + packageName, PackageManager.GET_META_DATA, userId); + badge = Utils.getBadgedIcon(mContext, appInfo); + } catch (PackageManager.NameNotFoundException e) { + badge = mContext.getPackageManager().getDefaultActivityIcon(); + } + return badge; + } + private void setMaxLines(RemoteViews views, boolean showSender) { int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp( R.dimen.content_text_size_for_medium) @@ -337,6 +410,9 @@ public class PeopleTileViewHelper { private RemoteViews setCommonRemoteViewsFields(RemoteViews views, int maxAvatarSize) { try { + if (mTile == null) { + return views; + } boolean isAvailable = mTile.getStatuses() != null && mTile.getStatuses().stream().anyMatch( c -> c.getAvailability() == AVAILABILITY_AVAILABLE); @@ -367,13 +443,16 @@ public class PeopleTileViewHelper { | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mTile.getId()); + activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mKey.getShortcutId()); activityIntent.putExtra( - PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mTile.getPackageName()); + PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mKey.getPackageName()); activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE, - mTile.getUserHandle()); - activityIntent.putExtra( - PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY, mTile.getNotificationKey()); + new UserHandle(mKey.getUserId())); + if (mTile != null) { + activityIntent.putExtra( + PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY, + mTile.getNotificationKey()); + } views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity( mContext, mAppWidgetId, @@ -727,6 +806,9 @@ public class PeopleTileViewHelper { c -> c.getActivity() == ACTIVITY_NEW_STORY); Icon icon = tile.getUserIcon(); + if (icon == null) { + return null; + } PeopleStoryIconFactory storyIcon = new PeopleStoryIconFactory(context, context.getPackageManager(), IconDrawableFactory.newInstance(context, false), diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java index 64a6509ea0aa..ea1724f96669 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java @@ -17,6 +17,12 @@ package com.android.systemui.people.widget; import static android.Manifest.permission.READ_CONTACTS; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; +import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; +import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; +import static android.content.Intent.ACTION_BOOT_COMPLETED; +import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE; import static com.android.systemui.people.NotificationHelper.getContactUri; import static com.android.systemui.people.NotificationHelper.getHighestPriorityNotification; @@ -30,13 +36,12 @@ import static com.android.systemui.people.PeopleSpaceUtils.augmentTileFromNotifi import static com.android.systemui.people.PeopleSpaceUtils.getMessagesCount; import static com.android.systemui.people.PeopleSpaceUtils.getNotificationsByUri; import static com.android.systemui.people.PeopleSpaceUtils.removeNotificationFields; -import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetOptionsAndView; -import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetViews; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.INotificationManager; import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Person; import android.app.people.ConversationChannel; @@ -44,8 +49,11 @@ import android.app.people.IPeopleManager; import android.app.people.PeopleManager; import android.app.people.PeopleSpaceTile; import android.appwidget.AppWidgetManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; @@ -60,6 +68,8 @@ import android.preference.PreferenceManager; import android.service.notification.ConversationChannelWrapper; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; +import android.service.notification.ZenModeConfig; +import android.text.TextUtils; import android.util.Log; import android.widget.RemoteViews; @@ -67,8 +77,9 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLoggerImpl; -import com.android.settingslib.utils.ThreadUtils; -import com.android.systemui.Dependency; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.people.NotificationHelper; import com.android.systemui.people.PeopleSpaceUtils; import com.android.systemui.people.PeopleTileViewHelper; @@ -85,15 +96,15 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.Executor; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; -import javax.inject.Singleton; /** Manager for People Space widget. */ -@Singleton +@SysUISingleton public class PeopleSpaceWidgetManager { private static final String TAG = "PeopleSpaceWidgetMgr"; private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; @@ -107,12 +118,15 @@ public class PeopleSpaceWidgetManager { private PeopleManager mPeopleManager; private NotificationEntryManager mNotificationEntryManager; private PackageManager mPackageManager; - private PeopleSpaceWidgetProvider mPeopleSpaceWidgetProvider; private INotificationManager mINotificationManager; private UserManager mUserManager; + private PeopleSpaceWidgetManager mManager; public UiEventLogger mUiEventLogger = new UiEventLoggerImpl(); + private NotificationManager mNotificationManager; + private BroadcastDispatcher mBroadcastDispatcher; + private Executor mBgExecutor; @GuardedBy("mLock") - public static Map<PeopleTileKey, PeopleSpaceWidgetProvider.TileConversationListener> + public static Map<PeopleTileKey, TileConversationListener> mListeners = new HashMap<>(); @GuardedBy("mLock") @@ -120,46 +134,91 @@ public class PeopleSpaceWidgetManager { // This is required because on notification removal, the contact Uri field is stripped and we // only have the notification key to determine which widget IDs should be updated. private Map<String, Set<String>> mNotificationKeyToWidgetIdsMatchedByUri = new HashMap<>(); - private boolean mIsForTesting; + private boolean mRegisteredReceivers; @Inject - public PeopleSpaceWidgetManager(Context context) { + public PeopleSpaceWidgetManager(Context context, LauncherApps launcherApps, + NotificationEntryManager notificationEntryManager, + PackageManager packageManager, UserManager userManager, + NotificationManager notificationManager, BroadcastDispatcher broadcastDispatcher, + @Background Executor bgExecutor) { if (DEBUG) Log.d(TAG, "constructor"); mContext = context; mAppWidgetManager = AppWidgetManager.getInstance(context); mIPeopleManager = IPeopleManager.Stub.asInterface( ServiceManager.getService(Context.PEOPLE_SERVICE)); - mLauncherApps = context.getSystemService(LauncherApps.class); + mLauncherApps = launcherApps; mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); - mPeopleManager = mContext.getSystemService(PeopleManager.class); - mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); - mPackageManager = mContext.getPackageManager(); - mPeopleSpaceWidgetProvider = new PeopleSpaceWidgetProvider(); + mPeopleManager = context.getSystemService(PeopleManager.class); + mNotificationEntryManager = notificationEntryManager; + mPackageManager = packageManager; mINotificationManager = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - mUserManager = context.getSystemService(UserManager.class); + mUserManager = userManager; + mNotificationManager = notificationManager; + mManager = this; + mBroadcastDispatcher = broadcastDispatcher; + mBgExecutor = bgExecutor; + } + + /** Initializes {@PeopleSpaceWidgetManager}. */ + public void init() { + synchronized (mLock) { + if (!mRegisteredReceivers) { + IntentFilter filter = new IntentFilter(); + filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); + filter.addAction(ACTION_BOOT_COMPLETED); + filter.addAction(Intent.ACTION_LOCALE_CHANGED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); + filter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); + filter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); + filter.addAction(Intent.ACTION_USER_UNLOCKED); + mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter, + null /* executor */, UserHandle.ALL); + mRegisteredReceivers = true; + } + } + } + + /** Listener for the shortcut data changes. */ + public class TileConversationListener implements PeopleManager.ConversationListener { + + @Override + public void onConversationUpdate(@NonNull ConversationChannel conversation) { + if (DEBUG) { + Log.d(TAG, + "Received updated conversation: " + + conversation.getShortcutInfo().getLabel()); + } + updateWidgetsWithConversationChanged(conversation); + } } /** - * AppWidgetManager setter used for testing. + * PeopleSpaceWidgetManager setter used for testing. */ @VisibleForTesting - public void setAppWidgetManager( + PeopleSpaceWidgetManager(Context context, AppWidgetManager appWidgetManager, IPeopleManager iPeopleManager, PeopleManager peopleManager, LauncherApps launcherApps, NotificationEntryManager notificationEntryManager, PackageManager packageManager, - boolean isForTesting, PeopleSpaceWidgetProvider peopleSpaceWidgetProvider, - UserManager userManager, INotificationManager notificationManager) { + UserManager userManager, INotificationManager iNotificationManager, + NotificationManager notificationManager, @Background Executor executor) { + mContext = context; mAppWidgetManager = appWidgetManager; mIPeopleManager = iPeopleManager; mPeopleManager = peopleManager; mLauncherApps = launcherApps; mNotificationEntryManager = notificationEntryManager; mPackageManager = packageManager; - mIsForTesting = isForTesting; - mPeopleSpaceWidgetProvider = peopleSpaceWidgetProvider; mUserManager = userManager; - mINotificationManager = notificationManager; + mINotificationManager = iNotificationManager; + mNotificationManager = notificationManager; + mManager = this; + mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); + mBgExecutor = executor; } /** @@ -173,7 +232,7 @@ public class PeopleSpaceWidgetManager { return; } - if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets"); + if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets: " + widgetIds); synchronized (mLock) { updateSingleConversationWidgets(widgetIds); } @@ -191,16 +250,47 @@ public class PeopleSpaceWidgetManager { for (int appWidgetId : appWidgetIds) { PeopleSpaceTile tile = getTileForExistingWidget(appWidgetId); if (tile == null) { - if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID"); - //TODO: Delete app widget id when crash is fixed (b/172932636) - continue; + Log.e(TAG, "Matching conversation not found for shortcut ID"); } Bundle options = mAppWidgetManager.getAppWidgetOptions(appWidgetId); - updateAppWidgetViews(mAppWidgetManager, mContext, appWidgetId, tile, options); + updateAppWidgetViews(appWidgetId, tile, options); widgetIdToTile.put(appWidgetId, tile); + if (tile != null) { + registerConversationListenerIfNeeded(appWidgetId, + new PeopleTileKey(tile)); + } + } + PeopleSpaceUtils.getDataFromContactsOnBackgroundThread( + mContext, mManager, widgetIdToTile, appWidgetIds); + } + + /** Updates the current widget view with provided {@link PeopleSpaceTile}. */ + private void updateAppWidgetViews(int appWidgetId, PeopleSpaceTile tile, Bundle options) { + PeopleTileKey key = getKeyFromStorageByWidgetId(appWidgetId); + if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + " for: " + key.toString()); + if (!key.isValid()) { + Log.e(TAG, "Cannot update invalid widget"); + return; + } + RemoteViews views = new PeopleTileViewHelper(mContext, tile, appWidgetId, + options, key).getViews(); + + // Tell the AppWidgetManager to perform an update on the current app widget. + mAppWidgetManager.updateAppWidget(appWidgetId, views); + } + + /** Updates tile in app widget options and the current view. */ + public void updateAppWidgetOptionsAndViewOptional(int appWidgetId, + Optional<PeopleSpaceTile> tile) { + if (tile.isPresent()) { + updateAppWidgetOptionsAndView(appWidgetId, tile.get()); } - PeopleSpaceUtils.getBirthdaysOnBackgroundThread( - mContext, mAppWidgetManager, widgetIdToTile, appWidgetIds); + } + + /** Updates tile in app widget options and the current view. */ + public void updateAppWidgetOptionsAndView(int appWidgetId, PeopleSpaceTile tile) { + Bundle options = AppWidgetOptionsHelper.setPeopleTile(mAppWidgetManager, appWidgetId, tile); + updateAppWidgetViews(appWidgetId, tile, options); } /** @@ -226,7 +316,7 @@ public class PeopleSpaceWidgetManager { widgetSp.getInt(USER_ID, INVALID_USER_ID), widgetSp.getString(PACKAGE_NAME, EMPTY_STRING)); - return getTileFromPersistentStorage(key); + return getTileFromPersistentStorage(key, appWidgetId); } /** @@ -234,7 +324,7 @@ public class PeopleSpaceWidgetManager { * If a {@link PeopleTileKey} is not provided, fetch one from {@link SharedPreferences}. */ @Nullable - public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key) { + public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId) { if (!key.isValid()) { Log.e(TAG, "PeopleTileKey invalid: " + key.toString()); return null; @@ -254,7 +344,22 @@ public class PeopleSpaceWidgetManager { return null; } - return new PeopleSpaceTile.Builder(channel, mLauncherApps).build(); + // Get tile from shortcut & conversation storage. + PeopleSpaceTile.Builder storedTile = new PeopleSpaceTile.Builder(channel, + mLauncherApps); + if (storedTile == null) { + return storedTile.build(); + } + + // Supplement with our storage. + String contactUri = mSharedPrefs.getString(String.valueOf(appWidgetId), null); + if (contactUri != null && storedTile.build().getContactUri() == null) { + if (DEBUG) Log.d(TAG, "Restore contact uri from storage: " + contactUri); + storedTile.setContactUri(Uri.parse(contactUri)); + } + + // Add current state. + return updateWithCurrentState(storedTile.build(), ACTION_BOOT_COMPLETED); } catch (Exception e) { Log.e(TAG, "Failed to retrieve conversation for tile: " + e); return null; @@ -275,11 +380,7 @@ public class PeopleSpaceWidgetManager { Log.d(TAG, "Notification removed, key: " + sbn.getKey()); } } - if (mIsForTesting) { - updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction); - return; - } - ThreadUtils.postOnBackgroundThread( + mBgExecutor.execute( () -> updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction)); } @@ -331,8 +432,7 @@ public class PeopleSpaceWidgetManager { .collect(Collectors.toMap( Function.identity(), id -> getAugmentedTileForExistingWidget(id, groupedNotifications))) - .forEach((id, tile) -> - updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, id, tile)); + .forEach((id, tile) -> updateAppWidgetOptionsAndViewOptional(id, tile)); } catch (Exception e) { Log.e(TAG, "Exception updating widgets: " + e); } @@ -341,16 +441,20 @@ public class PeopleSpaceWidgetManager { /** * Augments {@code tile} based on notifications returned from {@code notificationEntryManager}. */ - public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile) { + public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile, + Optional<Integer> appWidgetId) { PeopleTileKey key = new PeopleTileKey(tile); - Log.d(TAG, "Augmenting tile from NotificationEntryManager widget: " + key.toString()); + if (DEBUG) { + Log.d(TAG, + "Augmenting tile from NotificationEntryManager widget: " + key.toString()); + } Map<PeopleTileKey, Set<NotificationEntry>> notifications = getGroupedConversationNotifications(); String contactUri = null; if (tile.getContactUri() != null) { contactUri = tile.getContactUri().toString(); } - return augmentTileFromNotifications(tile, key, contactUri, notifications); + return augmentTileFromNotifications(tile, key, contactUri, notifications, appWidgetId); } /** Returns active and pending notifications grouped by {@link PeopleTileKey}. */ @@ -380,9 +484,11 @@ public class PeopleSpaceWidgetManager { /** Augments {@code tile} based on {@code notifications}, matching {@code contactUri}. */ public PeopleSpaceTile augmentTileFromNotifications(PeopleSpaceTile tile, PeopleTileKey key, - String contactUri, Map<PeopleTileKey, Set<NotificationEntry>> notifications) { + String contactUri, + Map<PeopleTileKey, Set<NotificationEntry>> notifications, + Optional<Integer> appWidgetId) { if (DEBUG) Log.d(TAG, "Augmenting tile from notifications. Tile key: " + key.toString()); - boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS, + boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS, tile.getPackageName()) == PackageManager.PERMISSION_GRANTED; List<NotificationEntry> notificationsByUri = new ArrayList<>(); @@ -413,7 +519,8 @@ public class PeopleSpaceWidgetManager { NotificationEntry highestPriority = getHighestPriorityNotification(allNotifications); if (DEBUG) Log.d(TAG, "Augmenting tile from notification, key: " + key.toString()); - return augmentTileFromNotification(mContext, tile, key, highestPriority, messagesCount); + return augmentTileFromNotification(mContext, tile, key, highestPriority, messagesCount, + appWidgetId); } /** Returns an augmented tile for an existing widget. */ @@ -434,7 +541,8 @@ public class PeopleSpaceWidgetManager { PeopleTileKey key = new PeopleTileKey(tile); if (DEBUG) Log.d(TAG, "Existing widget: " + widgetId + ". Tile key: " + key.toString()); return Optional.ofNullable( - augmentTileFromNotifications(tile, key, contactUriString, notifications)); + augmentTileFromNotifications(tile, key, contactUriString, notifications, + Optional.of(widgetId))); } /** Returns stored widgets for the conversation specified. */ @@ -552,10 +660,8 @@ public class PeopleSpaceWidgetManager { .setStatuses(conversation.getStatuses()) .setLastInteractionTimestamp(conversation.getLastEventTimestamp()) .setIsImportantConversation(conversation.getParentNotificationChannel() != null - && conversation.getParentNotificationChannel().isImportantConversation()) - .build(); - updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, - updatedTile.build()); + && conversation.getParentNotificationChannel().isImportantConversation()); + updateAppWidgetOptionsAndView(appWidgetId, updatedTile.build()); } /** @@ -640,11 +746,11 @@ public class PeopleSpaceWidgetManager { /** Adds a widget based on {@code key} mapped to {@code appWidgetId}. */ public void addNewWidget(int appWidgetId, PeopleTileKey key) { if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId); - PeopleSpaceTile tile = getTileFromPersistentStorage(key); + PeopleSpaceTile tile = getTileFromPersistentStorage(key, appWidgetId); if (tile == null) { return; } - tile = augmentTileFromNotificationEntryManager(tile); + tile = augmentTileFromNotificationEntryManager(tile, Optional.of(appWidgetId)); PeopleTileKey existingKeyIfStored; synchronized (mLock) { @@ -665,6 +771,8 @@ public class PeopleSpaceWidgetManager { PeopleSpaceUtils.setSharedPreferencesStorageForTile(mContext, key, appWidgetId, tile.getContactUri()); } + if (DEBUG) Log.d(TAG, "Ensure listener is registered for widget: " + appWidgetId); + registerConversationListenerIfNeeded(appWidgetId, key); try { if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + key.toString()); mLauncherApps.cacheShortcuts(tile.getPackageName(), @@ -674,23 +782,17 @@ public class PeopleSpaceWidgetManager { Log.w(TAG, "Exception caching shortcut:" + e); } - PeopleSpaceUtils.updateAppWidgetOptionsAndView( - mAppWidgetManager, mContext, appWidgetId, tile); - mPeopleSpaceWidgetProvider.onUpdate(mContext, mAppWidgetManager, new int[]{appWidgetId}); + updateAppWidgetOptionsAndView(appWidgetId, tile); } /** Registers a conversation listener for {@code appWidgetId} if not already registered. */ - public void registerConversationListenerIfNeeded(int widgetId, - PeopleSpaceWidgetProvider.TileConversationListener newListener) { + public void registerConversationListenerIfNeeded(int widgetId, PeopleTileKey key) { // Retrieve storage needed for registration. - PeopleTileKey key; - synchronized (mLock) { - key = getKeyFromStorageByWidgetId(widgetId); - if (!key.isValid()) { - if (DEBUG) Log.w(TAG, "Could not register listener for widget: " + widgetId); - return; - } + if (!key.isValid()) { + if (DEBUG) Log.w(TAG, "Could not register listener for widget: " + widgetId); + return; } + TileConversationListener newListener = new TileConversationListener(); synchronized (mListeners) { if (mListeners.containsKey(key)) { if (DEBUG) Log.d(TAG, "Already registered listener"); @@ -760,7 +862,7 @@ public class PeopleSpaceWidgetManager { /** Unregisters the conversation listener for {@code appWidgetId}. */ private void unregisterConversationListener(PeopleTileKey key, int appWidgetId) { - PeopleSpaceWidgetProvider.TileConversationListener registeredListener; + TileConversationListener registeredListener; synchronized (mListeners) { registeredListener = mListeners.get(key); if (registeredListener == null) { @@ -875,9 +977,153 @@ public class PeopleSpaceWidgetManager { return null; } - PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile); + PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile, + Optional.empty()); if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId); - return new PeopleTileViewHelper(mContext, augmentedTile, 0, options).getViews(); + return new PeopleTileViewHelper(mContext, augmentedTile, 0, options, + new PeopleTileKey(augmentedTile)).getViews(); + } + + protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (DEBUG) Log.d(TAG, "Update widgets from: " + action); + mBgExecutor.execute(() -> updateWidgetsOnStateChange(action)); + } + }; + + /** Updates any app widget based on the current state. */ + @VisibleForTesting + void updateWidgetsOnStateChange(String entryPoint) { + int[] appWidgetIds = mAppWidgetManager.getAppWidgetIds( + new ComponentName(mContext, PeopleSpaceWidgetProvider.class)); + if (appWidgetIds == null) { + return; + } + synchronized (mLock) { + for (int appWidgetId : appWidgetIds) { + PeopleSpaceTile tile = getTileForExistingWidget(appWidgetId); + if (tile == null) { + Log.e(TAG, "Matching conversation not found for shortcut ID"); + } else { + tile = updateWithCurrentState(tile, entryPoint); + } + updateAppWidgetOptionsAndView(appWidgetId, tile); + } + } + } + + /** Checks the current state of {@code tile} dependencies, updating fields as necessary. */ + @Nullable + private PeopleSpaceTile updateWithCurrentState(PeopleSpaceTile tile, + String entryPoint) { + PeopleSpaceTile.Builder updatedTile = tile.toBuilder(); + try { + switch (entryPoint) { + case NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED: + updatedTile.setNotificationPolicyState(getNotificationPolicyState()); + break; + case Intent.ACTION_PACKAGES_SUSPENDED: + case Intent.ACTION_PACKAGES_UNSUSPENDED: + updatedTile.setIsPackageSuspended(getPackageSuspended(tile)); + break; + case Intent.ACTION_MANAGED_PROFILE_AVAILABLE: + case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE: + case Intent.ACTION_USER_UNLOCKED: + updatedTile.setIsUserQuieted(getUserQuieted(tile)); + break; + case Intent.ACTION_LOCALE_CHANGED: + break; + case ACTION_BOOT_COMPLETED: + default: + updatedTile.setIsUserQuieted(getUserQuieted(tile)).setIsPackageSuspended( + getPackageSuspended(tile)).setNotificationPolicyState( + getNotificationPolicyState()); + } + } catch (Exception e) { + Log.e(TAG, "Package no longer found for tile: " + tile.toString() + e); + return null; + } + return updatedTile.build(); + } + + private boolean getPackageSuspended(PeopleSpaceTile tile) throws Exception { + boolean packageSuspended = !TextUtils.isEmpty(tile.getPackageName()) + && mPackageManager.isPackageSuspended(tile.getPackageName()); + if (DEBUG) Log.d(TAG, "Package suspended: " + packageSuspended); + return packageSuspended; + } + + private boolean getUserQuieted(PeopleSpaceTile tile) { + boolean workProfileQuieted = + tile.getUserHandle() != null && mUserManager.isQuietModeEnabled( + tile.getUserHandle()); + if (DEBUG) Log.d(TAG, "Work profile quiet: " + workProfileQuieted); + return workProfileQuieted; + } + + private int getNotificationPolicyState() { + NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); + boolean suppressVisualEffects = + NotificationManager.Policy.areAllVisualEffectsSuppressed( + policy.suppressedVisualEffects); + int notificationPolicyState = 0; + switch (mNotificationManager.getCurrentInterruptionFilter()) { + case INTERRUPTION_FILTER_ALL: + if (DEBUG) Log.d(TAG, "All interruptions allowed"); + return PeopleSpaceTile.SHOW_CONVERSATIONS; + case INTERRUPTION_FILTER_PRIORITY: + if (policy.allowConversations()) { + // If the user sees notifications in DND, show notifications in tiles in DND. + if (!suppressVisualEffects) { + if (DEBUG) Log.d(TAG, "Visual effects not suppressed."); + return PeopleSpaceTile.SHOW_CONVERSATIONS; + } + if (policy.priorityConversationSenders == CONVERSATION_SENDERS_ANYONE) { + if (DEBUG) Log.d(TAG, "All conversations allowed"); + // We only show conversations, so we can show everything. + return PeopleSpaceTile.SHOW_CONVERSATIONS; + } else if (policy.priorityConversationSenders + == NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT) { + if (DEBUG) Log.d(TAG, "Important conversations allowed"); + notificationPolicyState |= PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS; + } + } + if (policy.allowMessages()) { + switch (policy.allowMessagesFrom()) { + case ZenModeConfig.SOURCE_CONTACT: + if (DEBUG) Log.d(TAG, "All contacts allowed"); + notificationPolicyState |= PeopleSpaceTile.SHOW_CONTACTS; + return notificationPolicyState; + case ZenModeConfig.SOURCE_STAR: + if (DEBUG) Log.d(TAG, "Starred contacts allowed"); + notificationPolicyState |= PeopleSpaceTile.SHOW_STARRED_CONTACTS; + return notificationPolicyState; + case ZenModeConfig.SOURCE_ANYONE: + default: + if (DEBUG) Log.d(TAG, "All messages allowed"); + return PeopleSpaceTile.SHOW_CONVERSATIONS; + } + } + if (notificationPolicyState != 0) { + if (DEBUG) Log.d(TAG, "Return block state: " + notificationPolicyState); + return notificationPolicyState; + } + // If only alarms or nothing can bypass DND, the tile shouldn't show conversations. + case INTERRUPTION_FILTER_NONE: + case INTERRUPTION_FILTER_ALARMS: + default: + // If the user sees notifications in DND, show notifications in tiles in DND. + if (!suppressVisualEffects) { + if (DEBUG) Log.d(TAG, "Visual effects not suppressed."); + return PeopleSpaceTile.SHOW_CONVERSATIONS; + } + if (DEBUG) Log.d(TAG, "Block conversations"); + return PeopleSpaceTile.BLOCK_CONVERSATIONS; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java index 3bc5b29bd05d..3522b76e6460 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java @@ -16,9 +16,6 @@ package com.android.systemui.people.widget; -import android.annotation.NonNull; -import android.app.people.ConversationChannel; -import android.app.people.PeopleManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; @@ -28,6 +25,8 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.people.PeopleSpaceUtils; +import javax.inject.Inject; + /** People Space Widget Provider class. */ public class PeopleSpaceWidgetProvider extends AppWidgetProvider { private static final String TAG = "PeopleSpaceWidgetPvd"; @@ -38,25 +37,11 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider { public static final String EXTRA_USER_HANDLE = "extra_user_handle"; public static final String EXTRA_NOTIFICATION_KEY = "extra_notification_key"; - public PeopleSpaceWidgetManager peopleSpaceWidgetManager; - - /** Listener for the shortcut data changes. */ - public class TileConversationListener implements PeopleManager.ConversationListener { + public PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; - @Override - public void onConversationUpdate(@NonNull ConversationChannel conversation) { - if (DEBUG) { - Log.d(TAG, - "Received updated conversation: " - + conversation.getShortcutInfo().getLabel()); - } - if (peopleSpaceWidgetManager == null) { - // This shouldn't happen since onUpdate is called at reboot. - Log.e(TAG, "Skipping conversation update: WidgetManager uninitialized"); - return; - } - peopleSpaceWidgetManager.updateWidgetsWithConversationChanged(conversation); - } + @Inject + PeopleSpaceWidgetProvider(PeopleSpaceWidgetManager peopleSpaceWidgetManager) { + mPeopleSpaceWidgetManager = peopleSpaceWidgetManager; } /** Called when widget updates. */ @@ -65,15 +50,8 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider { super.onUpdate(context, appWidgetManager, appWidgetIds); if (DEBUG) Log.d(TAG, "onUpdate called"); - ensurePeopleSpaceWidgetManagerInitialized(context); - peopleSpaceWidgetManager.updateWidgets(appWidgetIds); - for (int appWidgetId : appWidgetIds) { - if (DEBUG) Log.d(TAG, "Ensure listener is registered for widget: " + appWidgetId); - PeopleSpaceWidgetProvider.TileConversationListener - newListener = new PeopleSpaceWidgetProvider.TileConversationListener(); - peopleSpaceWidgetManager.registerConversationListenerIfNeeded(appWidgetId, - newListener); - } + ensurePeopleSpaceWidgetManagerInitialized(); + mPeopleSpaceWidgetManager.updateWidgets(appWidgetIds); } /** Called when widget updates. */ @@ -81,25 +59,23 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider { public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); - ensurePeopleSpaceWidgetManagerInitialized(context); - peopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions); + ensurePeopleSpaceWidgetManagerInitialized(); + mPeopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions); } @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); - ensurePeopleSpaceWidgetManagerInitialized(context); - peopleSpaceWidgetManager.deleteWidgets(appWidgetIds); + ensurePeopleSpaceWidgetManagerInitialized(); + mPeopleSpaceWidgetManager.deleteWidgets(appWidgetIds); } - private void ensurePeopleSpaceWidgetManagerInitialized(Context context) { - if (peopleSpaceWidgetManager == null) { - peopleSpaceWidgetManager = new PeopleSpaceWidgetManager(context); - } + private void ensurePeopleSpaceWidgetManagerInitialized() { + mPeopleSpaceWidgetManager.init(); } @VisibleForTesting public void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager manager) { - peopleSpaceWidgetManager = manager; + mPeopleSpaceWidgetManager = manager; } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index c552e89a3625..aa4fb712090b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -7,7 +7,6 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.res.Configuration; -import android.content.res.Resources; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; @@ -333,11 +332,6 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { @Override public boolean updateResources() { - // Update bottom padding, useful for removing extra space once the panel page indicator is - // hidden. - Resources res = getContext().getResources(); - setPageMargin(res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal)); - setPadding(0, 0, 0, getContext().getResources().getDimensionPixelSize( R.dimen.qs_paged_tile_layout_padding_bottom)); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index f486c535d9e2..3b436769a456 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -207,11 +207,12 @@ public class QSContainerImpl extends FrameLayout { mContext.getResources().getDimensionPixelSize(R.dimen.qs_container_bottom_padding) ); - mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings); + int sideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings); int padding = getResources().getDimensionPixelSize( R.dimen.notification_shade_content_margin_horizontal); - boolean marginsChanged = padding != mContentPadding; + boolean marginsChanged = padding != mContentPadding || sideMargins != mSideMargins; mContentPadding = padding; + mSideMargins = sideMargins; if (marginsChanged) { updatePaddingsAndMargins(qsPanelController, quickStatusBarHeaderController); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index e3f00f42d2ca..c69956f90c67 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -55,9 +55,13 @@ public class QuickStatusBarHeader extends FrameLayout { private TouchAnimator mAlphaAnimator; private TouchAnimator mTranslationAnimator; + private TouchAnimator mIconsAlphaAnimator; + private TouchAnimator mIconsAlphaAnimatorFixed; protected QuickQSPanel mHeaderQsPanel; private View mDatePrivacyView; + private View mDateView; + private View mSecurityHeaderView; private View mClockIconsView; private View mContainer; @@ -66,7 +70,7 @@ public class QuickStatusBarHeader extends FrameLayout { private Space mSpace; private BatteryMeterView mBatteryRemainingIcon; private StatusIconContainer mIconContainer; - + private View mPrivacyChip; private TintedIconManager mTintedIconManager; private QSExpansionPathInterpolator mQSExpansionPathInterpolator; @@ -79,7 +83,6 @@ public class QuickStatusBarHeader extends FrameLayout { private int mCutOutPaddingLeft; private int mCutOutPaddingRight; private float mClockIconsAlpha = 1.0f; - private float mDatePrivacyAlpha = 1.0f; private float mKeyguardExpansionFraction; private int mTextColorPrimary = Color.TRANSPARENT; private int mTopViewMeasureHeight; @@ -111,8 +114,11 @@ public class QuickStatusBarHeader extends FrameLayout { mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy); mClockIconsView = findViewById(R.id.quick_qs_status_icons); mQSCarriers = findViewById(R.id.carrier_group); - mContainer = findViewById(R.id.container); + mContainer = findViewById(R.id.qs_container); mIconContainer = findViewById(R.id.statusIcons); + mPrivacyChip = findViewById(R.id.privacy_chip); + mDateView = findViewById(R.id.date); + mSecurityHeaderView = findViewById(R.id.header_text_container); mClockView = findViewById(R.id.clock); mSpace = findViewById(R.id.space); @@ -126,6 +132,11 @@ public class QuickStatusBarHeader extends FrameLayout { // QS will always show the estimate, and BatteryMeterView handles the case where // it's unavailable or charging mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE); + + mIconsAlphaAnimatorFixed = new TouchAnimator.Builder() + .addFloat(mIconContainer, "alpha", 0, 1) + .addFloat(mBatteryRemainingIcon, "alpha", 0, 1) + .build(); } void onAttach(TintedIconManager iconManager, @@ -226,8 +237,12 @@ public class QuickStatusBarHeader extends FrameLayout { StatusBarIconView callStrengthIcon = ((StatusBarIconView) mIconContainer.getViewForSlot(mCallStrengthSlotName)); TouchAnimator.Builder builder = new TouchAnimator.Builder() - .addFloat(mQSCarriers, "alpha", 0, 1) - .addFloat(mDatePrivacyView, "alpha", 0, mDatePrivacyAlpha); + // The following two views have to be hidden manually, so as not to hide the + // Privacy chip in QQS + .addFloat(mDateView, "alpha", 0, 1) + .addFloat(mSecurityHeaderView, "alpha", 0, 1) + .addFloat(mQSCarriers, "alpha", 0, 1); + if (noCallingIcon != null || callStrengthIcon != null) { if (noCallingIcon != null) { builder.addFloat(noCallingIcon, "alpha", 1, 0); @@ -259,6 +274,20 @@ public class QuickStatusBarHeader extends FrameLayout { mAlphaAnimator = builder.build(); } + void setChipVisibility(boolean visibility) { + mPrivacyChip.setVisibility(visibility ? View.VISIBLE : View.GONE); + if (visibility) { + // Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible + mIconsAlphaAnimator = mIconsAlphaAnimatorFixed; + mIconsAlphaAnimator.setPosition(mKeyguardExpansionFraction); + } else { + mIconsAlphaAnimator = null; + mIconContainer.setAlpha(1); + mBatteryRemainingIcon.setAlpha(1); + } + + } + /** */ public void setExpanded(boolean expanded, QuickQSPanelController quickQSPanelController) { if (mExpanded == expanded) return; @@ -285,6 +314,9 @@ public class QuickStatusBarHeader extends FrameLayout { if (mTranslationAnimator != null) { mTranslationAnimator.setPosition(keyguardExpansionFraction); } + if (mIconsAlphaAnimator != null) { + mIconsAlphaAnimator.setPosition(keyguardExpansionFraction); + } // If forceExpanded (we are opening QS from lockscreen), the animators have been set to // position = 1f. if (forceExpanded) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 3aafea98ff2a..617b067be891 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -225,7 +225,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private void setChipVisibility(boolean chipVisible) { if (chipVisible && getChipEnabled()) { - mPrivacyChip.setVisibility(View.VISIBLE); mPrivacyLogger.logChipVisible(true); // Makes sure that the chip is logged as viewed at most once each time QS is opened // mListening makes sure that the callback didn't return after the user closed QS @@ -235,8 +234,8 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } } else { mPrivacyLogger.logChipVisible(false); - mPrivacyChip.setVisibility(View.GONE); } + mView.setChipVisibility(chipVisible); } private List<String> getIgnoredIconSlots() { diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index f078ccd9d382..1ec785d4712e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -213,7 +213,9 @@ public class OverviewProxyService extends CurrentUserTracker implements // TODO move this logic to message queue mStatusBarOptionalLazy.ifPresent(statusBarLazy -> { StatusBar statusBar = statusBarLazy.get(); - statusBar.getPanelController().startExpandLatencyTracking(); + if (event.getActionMasked() == ACTION_DOWN) { + statusBar.getPanelController().startExpandLatencyTracking(); + } mHandler.post(()-> { int action = event.getActionMasked(); if (action == ACTION_DOWN) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index 5437ce63475e..7f31fddbfb6c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import static com.android.systemui.statusbar.RemoteInputController.processForRemoteInput; import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; +import static com.android.systemui.statusbar.phone.StatusBar.DEBUG; import android.annotation.NonNull; import android.annotation.SuppressLint; @@ -34,7 +35,6 @@ import android.util.Log; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.dagger.StatusBarModule; import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins; -import com.android.systemui.statusbar.phone.StatusBar; import java.util.ArrayList; import java.util.List; @@ -46,7 +46,6 @@ import java.util.List; @SuppressLint("OverrideAbstract") public class NotificationListener extends NotificationListenerWithPlugins { private static final String TAG = "NotificationListener"; - private static final boolean DEBUG = StatusBar.DEBUG; private final Context mContext; private final NotificationManager mNotificationManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt b/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt index 1da42a705311..78e85f1e6f73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt @@ -168,7 +168,6 @@ private class PrefsCommand(val context: Context) : Command { when (topLevel) { "list-prefs" -> listPrefs(pw) - "set-pref" -> setPref(pw, args.drop(1)) else -> help(pw) } } @@ -180,25 +179,4 @@ private class PrefsCommand(val context: Context) : Command { pw.println(field.get(Prefs.Key::class.java)) } } - - /** - * Sets a preference from [Prefs] - */ - private fun setPref(pw: PrintWriter, args: List<String>) { - if (args.isEmpty()) { - pw.println("invalid arguments: $args") - return - } - val pref = args[0] - - when (pref) { - Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S -> { - val value = Integer.parseInt(args[1]) - Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, value != 0) - } - else -> { - pw.println("Cannot set pref ($pref)") - } - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt index 5ab71bc62fe6..b3f7ca6f2630 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt @@ -29,6 +29,8 @@ import com.android.systemui.animation.Interpolators import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher +import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener import java.lang.IllegalStateException import java.util.concurrent.Executor @@ -51,8 +53,9 @@ import javax.inject.Inject @SysUISingleton class PrivacyDotViewController @Inject constructor( - @Main val mainExecutor: Executor, - val animationScheduler: SystemStatusAnimationScheduler + @Main private val mainExecutor: Executor, + private val locationPublisher: StatusBarLocationPublisher, + private val animationScheduler: SystemStatusAnimationScheduler ) { private var rotation = 0 private var leftSize = 0 @@ -80,12 +83,21 @@ class PrivacyDotViewController @Inject constructor( private val views: Sequence<View> get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl) + init { + locationPublisher.addCallback(object : StatusBarMarginUpdatedListener { + override fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) { + setStatusBarMargins(marginLeft, marginRight) + } + }) + } + fun setUiExecutor(e: Executor) { uiExecutor = e } @UiThread fun updateRotation(rot: Int) { + dlog("updateRotation: ") if (rot == rotation) { return } @@ -248,7 +260,7 @@ class PrivacyDotViewController @Inject constructor( * @param left the space between the status bar contents and the left side of the screen * @param right space between the status bar contents and the right side of the screen */ - fun setStatusBarMargins(left: Int, right: Int) { + private fun setStatusBarMargins(left: Int, right: Int) { leftSize = left rightSize = right @@ -262,6 +274,7 @@ class PrivacyDotViewController @Inject constructor( } private fun doUpdates(rot: Boolean, height: Boolean, width: Boolean) { + dlog("doUpdates: ") var newDesignatedCorner: View? = null if (rot) { @@ -324,12 +337,19 @@ class PrivacyDotViewController @Inject constructor( } } +private fun dlog(s: String) { + if (DEBUG) { + Log.d(TAG, s) + } +} + const val TOP_LEFT = 0 const val TOP_RIGHT = 1 const val BOTTOM_RIGHT = 2 const val BOTTOM_LEFT = 3 private const val DURATION = 160L private const val TAG = "PrivacyDotViewController" +private const val DEBUG = false private fun Int.toGravity(): Int { return when (this) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt index 620963060b49..b861c1db9b8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt @@ -27,6 +27,7 @@ import android.widget.FrameLayout import com.android.systemui.R import com.android.systemui.statusbar.SuperStatusBarViewFactory +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher import com.android.systemui.statusbar.phone.StatusBarWindowController import com.android.systemui.statusbar.phone.StatusBarWindowView @@ -39,7 +40,8 @@ import javax.inject.Inject class SystemEventChipAnimationController @Inject constructor( private val context: Context, private val statusBarViewFactory: SuperStatusBarViewFactory, - private val statusBarWindowController: StatusBarWindowController + private val statusBarWindowController: StatusBarWindowController, + private val locationPublisher: StatusBarLocationPublisher ) : SystemStatusChipAnimationCallback { var showPersistentDot = false set(value) { @@ -64,13 +66,15 @@ class SystemEventChipAnimationController @Inject constructor( if (state == ANIMATING_IN) { currentAnimatedView = viewCreator(context) - animationWindowView.addView(currentAnimatedView, layoutParamsDefault) + animationWindowView.addView(currentAnimatedView, layoutParamsDefault()) // We are animating IN; chip comes in from View.END currentAnimatedView?.apply { - translationX = width.toFloat() + val translation = width.toFloat() + translationX = if (isLayoutRtl) -translation else translation alpha = 0f visibility = View.VISIBLE + setPadding(locationPublisher.marginLeft, 0, locationPublisher.marginRight, 0) } } else { // We are animating away @@ -109,7 +113,7 @@ class SystemEventChipAnimationController @Inject constructor( val w = width val translation = (1 - amt) * w - translationX = translation + translationX = if (isLayoutRtl) -translation else translation } } @@ -131,7 +135,13 @@ class SystemEventChipAnimationController @Inject constructor( statusBarWindowView.addView(animationWindowView, lp) } - private val layoutParamsDefault = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { - it.gravity = Gravity.END or Gravity.CENTER_VERTICAL + private fun start() = if (animationWindowView.isLayoutRtl) right() else left() + private fun right() = locationPublisher.marginRight + private fun left() = locationPublisher.marginLeft + + private fun layoutParamsDefault(): FrameLayout.LayoutParams = + FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { + it.gravity = Gravity.END or Gravity.CENTER_VERTICAL + it.marginStart = start() } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt index 1e071312065b..40049373610c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -127,7 +127,6 @@ class SystemStatusAnimationScheduler @Inject constructor( } private fun isTooEarly(): Boolean { - Log.d(TAG, "time=> ${systemClock.uptimeMillis() - Process.getStartUptimeMillis()}") return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME } @@ -339,4 +338,4 @@ private const val ENTRANCE_ANIM_LENGTH = 500L private const val CHIP_ANIM_LENGTH = 500L private const val MIN_UPTIME: Long = 5 * 1000 -private const val DEBUG = false
\ No newline at end of file +private const val DEBUG = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java index d95c265c1460..d6356de5ea51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java @@ -16,9 +16,7 @@ package com.android.systemui.statusbar.notification.collection.legacy; -import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.Notification; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.Log; @@ -33,7 +31,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.wm.shell.bubbles.Bubbles; @@ -42,12 +39,10 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.TreeSet; import javax.inject.Inject; @@ -63,21 +58,13 @@ import dagger.Lazy; public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener, GroupMembershipManager, GroupExpansionManager, Dumpable { - private static final String TAG = "NotifGroupManager"; - private static final boolean DEBUG = StatusBar.DEBUG; - private static final boolean SPEW = StatusBar.SPEW; - /** - * The maximum amount of time (in ms) between the posting of notifications that can be - * considered part of the same update batch. - */ - private static final long POST_BATCH_MAX_AGE = 5000; + private static final String TAG = "NotificationGroupManager"; private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>(); private final ArraySet<OnGroupExpansionChangeListener> mExpansionChangeListeners = new ArraySet<>(); private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>(); private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier; private final Optional<Bubbles> mBubblesOptional; - private final EventBuffer mEventBuffer = new EventBuffer(); private int mBarState = -1; private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>(); private HeadsUpManager mHeadsUpManager; @@ -147,14 +134,8 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, * When we want to remove an entry from being tracked for grouping */ public void onEntryRemoved(NotificationEntry removed) { - if (SPEW) { - Log.d(TAG, "onEntryRemoved: entry=" + removed); - } onEntryRemovedInternal(removed, removed.getSbn()); - StatusBarNotification oldSbn = mIsolatedEntries.remove(removed.getKey()); - if (oldSbn != null) { - updateSuppression(mGroupMap.get(oldSbn.getGroupKey())); - } + mIsolatedEntries.remove(removed.getKey()); } /** @@ -181,9 +162,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, // the close future. See b/23676310 for reference. return; } - if (SPEW) { - Log.d(TAG, "onEntryRemovedInternal: entry=" + removed + " group=" + group.groupKey); - } if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) { group.children.remove(removed.getKey()); } else { @@ -204,9 +182,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, * Notify the group manager that a new entry was added */ public void onEntryAdded(final NotificationEntry added) { - if (SPEW) { - Log.d(TAG, "onEntryAdded: entry=" + added); - } updateIsolation(added); onEntryAddedInternal(added); } @@ -220,16 +195,13 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, String groupKey = getGroupKey(sbn); NotificationGroup group = mGroupMap.get(groupKey); if (group == null) { - group = new NotificationGroup(groupKey); + group = new NotificationGroup(); mGroupMap.put(groupKey, group); for (OnGroupChangeListener listener : mGroupChangeListeners) { listener.onGroupCreated(group, groupKey); } } - if (SPEW) { - Log.d(TAG, "onEntryAddedInternal: entry=" + added + " group=" + group.groupKey); - } if (isGroupChild) { NotificationEntry existing = group.children.get(added.getKey()); if (existing != null && existing != added) { @@ -241,11 +213,9 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, + " added removed" + added.isRowRemoved(), new Throwable()); } group.children.put(added.getKey(), added); - addToPostBatchHistory(group, added); updateSuppression(group); } else { group.summary = added; - addToPostBatchHistory(group, added); group.expanded = added.areChildrenExpanded(); updateSuppression(group); if (!group.children.isEmpty()) { @@ -261,27 +231,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, } } - private void addToPostBatchHistory(NotificationGroup group, @Nullable NotificationEntry entry) { - if (entry == null) { - return; - } - boolean didAdd = group.postBatchHistory.add(new PostRecord(entry)); - if (didAdd) { - trimPostBatchHistory(group.postBatchHistory); - } - } - - /** remove all history that's too old to be in the batch. */ - private void trimPostBatchHistory(@NonNull TreeSet<PostRecord> postBatchHistory) { - if (postBatchHistory.size() <= 1) { - return; - } - long batchStartTime = postBatchHistory.last().postTime - POST_BATCH_MAX_AGE; - while (!postBatchHistory.isEmpty() && postBatchHistory.first().postTime < batchStartTime) { - postBatchHistory.pollFirst(); - } - } - private void onEntryBecomingChild(NotificationEntry entry) { updateIsolation(entry); } @@ -290,9 +239,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, if (group == null) { return; } - NotificationEntry prevAlertOverride = group.alertOverride; - group.alertOverride = getPriorityConversationAlertOverride(group); - int childCount = 0; boolean hasBubbles = false; for (NotificationEntry entry : group.children.values()) { @@ -309,146 +255,16 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, group.suppressed = group.summary != null && !group.expanded && (childCount == 1 || (childCount == 0 - && group.summary.getSbn().getNotification().isGroupSummary() - && (hasIsolatedChildren(group) || hasBubbles))); - - boolean alertOverrideChanged = prevAlertOverride != group.alertOverride; - boolean suppressionChanged = prevSuppressed != group.suppressed; - if (alertOverrideChanged || suppressionChanged) { - if (DEBUG && alertOverrideChanged) { - Log.d(TAG, group + " alertOverride was=" + prevAlertOverride + " now=" - + group.alertOverride); - } - if (DEBUG && suppressionChanged) { - Log.d(TAG, group + " suppressed changed to " + group.suppressed); - } - if (!mIsUpdatingUnchangedGroup) { - if (alertOverrideChanged) { - mEventBuffer.notifyAlertOverrideChanged(group, prevAlertOverride); - } - if (suppressionChanged) { - for (OnGroupChangeListener listener : mGroupChangeListeners) { - listener.onGroupSuppressionChanged(group, group.suppressed); - } - } - mEventBuffer.notifyGroupsChanged(); - } else { - if (DEBUG) { - Log.d(TAG, group + " did not notify listeners of above change(s)"); - } - } - } - } - - /** - * Finds the isolated logical child of this group which is should be alerted instead. - * - * Notifications from priority conversations are isolated from their groups to make them more - * prominent, however apps may post these with a GroupAlertBehavior that has the group receiving - * the alert. This would lead to the group alerting even though the conversation that was - * updated was not actually a part of that group. This method finds the best priority - * conversation in this situation, if there is one, so they can be set as the alertOverride of - * the group. - * - * @param group the group to check - * @return the entry which should receive the alert instead of the group, if any. - */ - @Nullable - private NotificationEntry getPriorityConversationAlertOverride(NotificationGroup group) { - // GOAL: if there is a priority child which wouldn't alert based on its groupAlertBehavior, - // but which should be alerting (because priority conversations are isolated), find it. - if (group == null || group.summary == null) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: null group or summary"); - } - return null; - } - if (isIsolated(group.summary.getKey())) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: isolated group"); - } - return null; - } - - // Precondiions: - // * Only necessary when all notifications in the group use GROUP_ALERT_SUMMARY - // * Only necessary when at least one notification in the group is on a priority channel - if (group.summary.getSbn().getNotification().getGroupAlertBehavior() - != Notification.GROUP_ALERT_SUMMARY) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: summary != GROUP_ALERT_SUMMARY"); - } - return null; - } - - // Get the important children first, copy the keys for the final importance check, - // then add the non-isolated children to the map for unified lookup. - HashMap<String, NotificationEntry> children = getImportantConversations(group); - if (children == null || children.isEmpty()) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: no important conversations"); - } - return null; - } - HashSet<String> importantChildKeys = new HashSet<>(children.keySet()); - children.putAll(group.children); - - // Ensure all children have GROUP_ALERT_SUMMARY - for (NotificationEntry child : children.values()) { - if (child.getSbn().getNotification().getGroupAlertBehavior() - != Notification.GROUP_ALERT_SUMMARY) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: " - + "child != GROUP_ALERT_SUMMARY"); - } - return null; - } - } - - // Create a merged post history from all the children - TreeSet<PostRecord> combinedHistory = new TreeSet<>(group.postBatchHistory); - for (String importantChildKey : importantChildKeys) { - NotificationGroup importantChildGroup = mGroupMap.get(importantChildKey); - combinedHistory.addAll(importantChildGroup.postBatchHistory); - } - trimPostBatchHistory(combinedHistory); - - // This is a streamlined implementation of the following idea: - // * From the subset of notifications in the latest 'batch' of updates. A batch is: - // * Notifs posted less than POST_BATCH_MAX_AGE before the most recently posted. - // * Only including notifs newer than the second-to-last post of any notification. - // * Find the newest child in the batch -- the with the largest 'when' value. - // * If the newest child is a priority conversation, set that as the override. - HashSet<String> batchKeys = new HashSet<>(); - long newestChildWhen = -1; - NotificationEntry newestChild = null; - // Iterate backwards through the post history, tracking the child with the smallest sort key - for (PostRecord record : combinedHistory.descendingSet()) { - if (batchKeys.contains(record.key)) { - // Once you see a notification again, the batch has ended - break; - } - batchKeys.add(record.key); - NotificationEntry child = children.get(record.key); - if (child != null) { - long childWhen = child.getSbn().getNotification().when; - if (newestChild == null || childWhen > newestChildWhen) { - newestChildWhen = childWhen; - newestChild = child; + && group.summary.getSbn().getNotification().isGroupSummary() + && (hasIsolatedChildren(group) || hasBubbles))); + if (prevSuppressed != group.suppressed) { + for (OnGroupChangeListener listener : mGroupChangeListeners) { + if (!mIsUpdatingUnchangedGroup) { + listener.onGroupSuppressionChanged(group, group.suppressed); + listener.onGroupsChanged(); } } } - if (newestChild != null && importantChildKeys.contains(newestChild.getKey())) { - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: result=" + newestChild); - } - return newestChild; - } - if (SPEW) { - Log.d(TAG, "getPriorityConversationAlertOverride: result=null, newestChild=" - + newestChild); - } - return null; } private boolean hasIsolatedChildren(NotificationGroup group) { @@ -465,33 +281,12 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, return count; } - @Nullable - private HashMap<String, NotificationEntry> getImportantConversations(NotificationGroup group) { - String groupKey = group.summary.getSbn().getGroupKey(); - HashMap<String, NotificationEntry> result = null; - for (StatusBarNotification sbn : mIsolatedEntries.values()) { - if (sbn.getGroupKey().equals(groupKey)) { - NotificationEntry entry = mGroupMap.get(sbn.getKey()).summary; - if (isImportantConversation(entry)) { - if (result == null) { - result = new HashMap<>(); - } - result.put(sbn.getKey(), entry); - } - } - } - return result; - } - /** * Update an entry's group information * @param entry notification entry to update * @param oldNotification previous notification info before this update */ public void onEntryUpdated(NotificationEntry entry, StatusBarNotification oldNotification) { - if (SPEW) { - Log.d(TAG, "onEntryUpdated: entry=" + entry); - } onEntryUpdated(entry, oldNotification.getGroupKey(), oldNotification.isGroup(), oldNotification.getNotification().isGroupSummary()); } @@ -530,17 +325,7 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, * Whether the given notification is the summary of a group that is being suppressed */ public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) { - return sbn.getNotification().isGroupSummary() && isGroupSuppressed(getGroupKey(sbn)); - } - - /** - * If the given notification is a summary, get the group for it. - */ - public NotificationGroup getGroupForSummary(StatusBarNotification sbn) { - if (sbn.getNotification().isGroupSummary()) { - return mGroupMap.get(getGroupKey(sbn)); - } - return null; + return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary(); } private boolean isOnlyChild(StatusBarNotification sbn) { @@ -760,7 +545,9 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) { return false; } - if (isImportantConversation(entry)) { + int peopleNotificationType = + mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry); + if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) { return true; } if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) { @@ -773,25 +560,18 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, || isGroupNotFullyVisible(notificationGroup)); } - private boolean isImportantConversation(NotificationEntry entry) { - int peopleNotificationType = - mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry); - return peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON; - } - /** * Isolate a notification from its group so that it visually shows as its own group. * * @param entry the notification to isolate */ private void isolateNotification(NotificationEntry entry) { - if (SPEW) { - Log.d(TAG, "isolateNotification: entry=" + entry); - } + StatusBarNotification sbn = entry.getSbn(); + // We will be isolated now, so lets update the groups onEntryRemovedInternal(entry, entry.getSbn()); - mIsolatedEntries.put(entry.getKey(), entry.getSbn()); + mIsolatedEntries.put(sbn.getKey(), sbn); onEntryAddedInternal(entry); // We also need to update the suppression of the old group, because this call comes @@ -808,14 +588,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, * Update the isolation of an entry, splitting it from the group. */ public void updateIsolation(NotificationEntry entry) { - // We need to buffer a few events because we do isolation changes in 3 steps: - // removeInternal, update mIsolatedEntries, addInternal. This means that often the - // alertOverride will update on the removal, however processing the event in that case can - // cause problems because the mIsolatedEntries map is not in its final state, so the event - // listener may be unable to correctly determine the true state of the group. By delaying - // the alertOverride change until after the add phase, we can ensure that listeners only - // have to handle a consistent state. - mEventBuffer.startBuffering(); boolean isIsolated = isIsolated(entry.getSbn().getKey()); if (shouldIsolate(entry)) { if (!isIsolated) { @@ -824,7 +596,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, } else if (isIsolated) { stopIsolatingNotification(entry); } - mEventBuffer.flushAndStopBuffering(); } /** @@ -833,15 +604,15 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, * @param entry the notification to un-isolate */ private void stopIsolatingNotification(NotificationEntry entry) { - if (SPEW) { - Log.d(TAG, "stopIsolatingNotification: entry=" + entry); - } - // not isolated anymore, we need to update the groups - onEntryRemovedInternal(entry, entry.getSbn()); - mIsolatedEntries.remove(entry.getKey()); - onEntryAddedInternal(entry); - for (OnGroupChangeListener listener : mGroupChangeListeners) { - listener.onGroupsChanged(); + StatusBarNotification sbn = entry.getSbn(); + if (isIsolated(sbn.getKey())) { + // not isolated anymore, we need to update the groups + onEntryRemovedInternal(entry, entry.getSbn()); + mIsolatedEntries.remove(sbn.getKey()); + onEntryAddedInternal(entry); + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupsChanged(); + } } } @@ -877,154 +648,33 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, } /** - * A record of a notification being posted, containing the time of the post and the key of the - * notification entry. These are stored in a TreeSet by the NotificationGroup and used to - * calculate a batch of notifications. - */ - public static class PostRecord implements Comparable<PostRecord> { - public final long postTime; - public final String key; - - /** constructs a record containing the post time and key from the notification entry */ - public PostRecord(@NonNull NotificationEntry entry) { - this.postTime = entry.getSbn().getPostTime(); - this.key = entry.getKey(); - } - - @Override - public int compareTo(PostRecord o) { - int postTimeComparison = Long.compare(this.postTime, o.postTime); - return postTimeComparison == 0 - ? String.CASE_INSENSITIVE_ORDER.compare(this.key, o.key) - : postTimeComparison; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PostRecord that = (PostRecord) o; - return postTime == that.postTime && key.equals(that.key); - } - - @Override - public int hashCode() { - return Objects.hash(postTime, key); - } - } - - /** * Represents a notification group in the notification shade. */ public static class NotificationGroup { - public final String groupKey; public final HashMap<String, NotificationEntry> children = new HashMap<>(); - public final TreeSet<PostRecord> postBatchHistory = new TreeSet<>(); public NotificationEntry summary; public boolean expanded; /** * Is this notification group suppressed, i.e its summary is hidden */ public boolean suppressed; - /** - * The child (which is isolated from this group) to which the alert should be transferred, - * due to priority conversations. - */ - public NotificationEntry alertOverride; - - NotificationGroup(String groupKey) { - this.groupKey = groupKey; - } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(" groupKey: ").append(groupKey); - sb.append("\n summary:"); - appendEntry(sb, summary); - sb.append("\n children size: ").append(children.size()); + String result = " summary:\n " + + (summary != null ? summary.getSbn() : "null") + + (summary != null && summary.getDebugThrowable() != null + ? Log.getStackTraceString(summary.getDebugThrowable()) + : ""); + result += "\n children size: " + children.size(); for (NotificationEntry child : children.values()) { - appendEntry(sb, child); - } - sb.append("\n alertOverride:"); - appendEntry(sb, alertOverride); - sb.append("\n summary suppressed: ").append(suppressed); - return sb.toString(); - } - - private void appendEntry(StringBuilder sb, NotificationEntry entry) { - sb.append("\n ").append(entry != null ? entry.getSbn() : "null"); - if (entry != null && entry.getDebugThrowable() != null) { - sb.append(Log.getStackTraceString(entry.getDebugThrowable())); - } - } - } - - /** - * This class is a toggleable buffer for a subset of events of {@link OnGroupChangeListener}. - * When buffering, instead of notifying the listeners it will set internal state that will allow - * it to notify listeners of those events later - */ - private class EventBuffer { - private final HashMap<String, NotificationEntry> mOldAlertOverrideByGroup = new HashMap<>(); - private boolean mIsBuffering = false; - private boolean mDidGroupsChange = false; - - void notifyAlertOverrideChanged(NotificationGroup group, - NotificationEntry oldAlertOverride) { - if (mIsBuffering) { - // The value in this map is the override before the event. If there is an entry - // already in the map, then we are effectively coalescing two events, which means - // we need to preserve the original initial value. - mOldAlertOverrideByGroup.putIfAbsent(group.groupKey, oldAlertOverride); - } else { - for (OnGroupChangeListener listener : mGroupChangeListeners) { - listener.onGroupAlertOverrideChanged(group, oldAlertOverride, - group.alertOverride); - } - } - } - - void notifyGroupsChanged() { - if (mIsBuffering) { - mDidGroupsChange = true; - } else { - for (OnGroupChangeListener listener : mGroupChangeListeners) { - listener.onGroupsChanged(); - } - } - } - - void startBuffering() { - mIsBuffering = true; - } - - void flushAndStopBuffering() { - // stop buffering so that we can call our own helpers - mIsBuffering = false; - // alert all group alert override changes for groups that were not removed - for (Map.Entry<String, NotificationEntry> entry : mOldAlertOverrideByGroup.entrySet()) { - NotificationGroup group = mGroupMap.get(entry.getKey()); - if (group == null) { - // The group can be null if this alertOverride changed before the group was - // permanently removed, meaning that there's no guarantee that listeners will - // that field clear. - continue; - } - NotificationEntry oldAlertOverride = entry.getValue(); - if (group.alertOverride == oldAlertOverride) { - // If the final alertOverride equals the initial, it means we coalesced two - // events which undid the change, so we can drop it entirely. - continue; - } - notifyAlertOverrideChanged(group, oldAlertOverride); - } - mOldAlertOverrideByGroup.clear(); - // alert that groups changed - if (mDidGroupsChange) { - notifyGroupsChanged(); - mDidGroupsChange = false; + result += "\n " + child.getSbn() + + (child.getDebugThrowable() != null + ? Log.getStackTraceString(child.getDebugThrowable()) + : ""); } + result += "\n summary suppressed: " + suppressed; + return result; } } @@ -1064,18 +714,6 @@ public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, boolean suppressed) {} /** - * The alert override of a group has changed. - * - * @param group the group that has changed - * @param oldAlertOverride the previous notification to which the group's alerts were sent - * @param newAlertOverride the notification to which the group's alerts should now be sent - */ - default void onGroupAlertOverrideChanged( - NotificationGroup group, - @Nullable NotificationEntry oldAlertOverride, - @Nullable NotificationEntry newAlertOverride) {} - - /** * A group of children just received a summary notification and should therefore become * children of it. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 617dadb42594..e2a37f647bf5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -69,7 +69,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; -import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm; import com.android.systemui.statusbar.phone.ShadeController; @@ -141,7 +140,6 @@ public interface NotificationsModule { ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, UserContextProvider contextTracker, - Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, Optional<BubblesManager> bubblesManagerOptional, UiEventLogger uiEventLogger, @@ -161,7 +159,6 @@ public interface NotificationsModule { shortcutManager, channelEditorDialogController, contextTracker, - builderProvider, assistantFeedbackController, bubblesManagerOptional, uiEventLogger, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index 40be4bfa47dc..1f4f3caea517 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -22,6 +22,8 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; +import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE; +import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; import static com.android.systemui.animation.Interpolators.FAST_OUT_SLOW_IN; @@ -34,7 +36,6 @@ import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; -import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -55,7 +56,6 @@ import android.transition.TransitionManager; import android.transition.TransitionSet; import android.util.AttributeSet; import android.util.Log; -import android.view.LayoutInflater; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.widget.ImageView; @@ -64,7 +64,6 @@ import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.notification.ConversationIconFactory; -import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -78,8 +77,6 @@ import com.android.systemui.wmshell.BubblesManager; import java.lang.annotation.Retention; import java.util.Optional; -import javax.inject.Provider; - /** * The guts of a conversation notification revealed when performing a long press. */ @@ -107,7 +104,6 @@ public class NotificationConversationInfo extends LinearLayout implements private StatusBarNotification mSbn; @Nullable private Notification.BubbleMetadata mBubbleMetadata; private Context mUserContext; - private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider; private boolean mIsDeviceProvisioned; private int mAppBubble; @@ -172,13 +168,9 @@ public class NotificationConversationInfo extends LinearLayout implements private OnClickListener mOnDone = v -> { mPressedApply = true; - // If the user selected Priority, maybe show the priority onboarding. // If the user selected Priority and the previous selection was not priority, show a - // People Tile add request. If showing the priority onboarding, however, delay the request - // to when the onboarding dialog closes. - if (mSelectedAction == ACTION_FAVORITE && shouldShowPriorityOnboarding()) { - showPriorityOnboarding(); - } else if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) { + // People Tile add request. + if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) { mShadeController.animateCollapsePanels(); mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()); } @@ -229,7 +221,6 @@ public class NotificationConversationInfo extends LinearLayout implements OnSnoozeClickListener onSnoozeClickListener, ConversationIconFactory conversationIconFactory, Context userContext, - Provider<PriorityOnboardingDialogController.Builder> builderProvider, boolean isDeviceProvisioned, @Main Handler mainHandler, @Background Handler bgHandler, @@ -258,7 +249,6 @@ public class NotificationConversationInfo extends LinearLayout implements mBubbleMetadata = bubbleMetadata; mBubblesManagerOptional = bubblesManagerOptional; mShadeController = shadeController; - mBuilderProvider = builderProvider; mMainHandler = mainHandler; mBgHandler = bgHandler; mShortcutManager = shortcutManager; @@ -342,6 +332,18 @@ public class NotificationConversationInfo extends LinearLayout implements // bindName(); bindPackage(); bindIcon(mNotificationChannel.isImportantConversation()); + + mPriorityDescriptionView = findViewById(R.id.priority_summary); + if (willShowAsBubble() && willBypassDnd()) { + mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_all); + } else if (willShowAsBubble()) { + mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_bubble); + } else if (willBypassDnd()) { + mPriorityDescriptionView.setText(R.string.notification_channel_summary_priority_dnd); + } else { + mPriorityDescriptionView.setText( + R.string.notification_channel_summary_priority_baseline); + } } private void bindIcon(boolean important) { @@ -428,7 +430,6 @@ public class NotificationConversationInfo extends LinearLayout implements protected void onFinishInflate() { super.onFinishInflate(); - mPriorityDescriptionView = findViewById(R.id.priority_summary); mDefaultDescriptionView = findViewById(R.id.default_summary); mSilentDescriptionView = findViewById(R.id.silence_summary); } @@ -552,51 +553,22 @@ public class NotificationConversationInfo extends LinearLayout implements StackStateAnimator.ANIMATION_DURATION_STANDARD); } - private boolean shouldShowPriorityOnboarding() { - return !Prefs.getBoolean(mUserContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, false); - } - - private void showPriorityOnboarding() { - View onboardingView = LayoutInflater.from(mContext) - .inflate(R.layout.priority_onboarding_half_shell, null); - - boolean ignoreDnd = false; + private boolean willBypassDnd() { + boolean bypassesDnd = false; try { - ignoreDnd = mINotificationManager - .getConsolidatedNotificationPolicy().priorityConversationSenders == - NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; + int allowedSenders = mINotificationManager + .getConsolidatedNotificationPolicy().priorityConversationSenders; + bypassesDnd = allowedSenders == CONVERSATION_SENDERS_IMPORTANT + || allowedSenders == CONVERSATION_SENDERS_ANYONE; } catch (RemoteException e) { Log.e(TAG, "Could not check conversation senders", e); } + return bypassesDnd; + } - boolean showAsBubble = mBubbleMetadata != null - && mBubbleMetadata.getAutoExpandBubble() + private boolean willShowAsBubble() { + return mBubbleMetadata != null && BubblesManager.areBubblesEnabled(mContext, mSbn.getUser()); - - Drawable person = mIconFactory.getBaseIconDrawable(mShortcutInfo); - if (person == null) { - person = mContext.getDrawable(R.drawable.ic_person).mutate(); - TypedArray ta = mContext.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); - int colorAccent = ta.getColor(0, 0); - ta.recycle(); - person.setTint(colorAccent); - } - - PriorityOnboardingDialogController controller = mBuilderProvider.get() - .setContext(mUserContext) - .setView(onboardingView) - .setIgnoresDnd(ignoreDnd) - .setShowsAsBubble(showAsBubble) - .setIcon(person) - .setBadge(mIconFactory.getAppBadge( - mPackageName, UserHandle.getUserId(mSbn.getUid()))) - .setOnSettingsClick(mOnConversationSettingsClickListener) - .setPeopleSpaceWidgetManager(mPeopleSpaceWidgetManager) - .setShadeController(mShadeController) - .build(); - - controller.init(mShortcutInfo); - controller.show(); } @Override 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 1a7f5b0bf5af..59b88a53b45e 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 @@ -129,7 +129,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final LauncherApps mLauncherApps; private final ShortcutManager mShortcutManager; private final UserContextProvider mContextTracker; - private final Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider; private final UiEventLogger mUiEventLogger; private final ShadeController mShadeController; private final AppWidgetManager mAppWidgetManager; @@ -150,7 +149,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx ShortcutManager shortcutManager, ChannelEditorDialogController channelEditorDialogController, UserContextProvider contextTracker, - Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, Optional<BubblesManager> bubblesManagerOptional, UiEventLogger uiEventLogger, @@ -168,7 +166,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mLauncherApps = launcherApps; mShortcutManager = shortcutManager; mContextTracker = contextTracker; - mBuilderProvider = builderProvider; mChannelEditorDialogController = channelEditorDialogController; mAssistantFeedbackController = assistantFeedbackController; mBubblesManagerOptional = bubblesManagerOptional; @@ -503,7 +500,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx onSnoozeClickListener, iconFactoryLoader, mContextTracker.getUserContext(), - mBuilderProvider, mDeviceProvisionedController.isDeviceProvisioned(), mMainHandler, mBgHandler, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PriorityOnboardingDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PriorityOnboardingDialogController.kt deleted file mode 100644 index 270721ffa4b8..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PriorityOnboardingDialogController.kt +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.notification.row - -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.animation.AnimatorSet -import android.animation.ValueAnimator -import android.app.Dialog -import android.content.Context -import android.content.pm.ShortcutInfo -import android.graphics.Color -import android.graphics.PixelFormat -import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable -import android.graphics.drawable.GradientDrawable -import android.os.Bundle -import android.text.SpannableStringBuilder -import android.text.style.BulletSpan -import android.view.Gravity -import android.view.View -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import android.view.Window -import android.view.WindowInsets.Type.statusBars -import android.view.WindowManager -import android.view.animation.Interpolator -import android.view.animation.PathInterpolator -import android.widget.ImageView -import android.widget.TextView -import com.android.systemui.Prefs -import com.android.systemui.R -import com.android.systemui.animation.Interpolators.LINEAR_OUT_SLOW_IN -import com.android.systemui.people.widget.PeopleSpaceWidgetManager -import com.android.systemui.statusbar.notification.row.NotificationConversationInfo.OnConversationSettingsClickListener -import com.android.systemui.statusbar.phone.ShadeController -import javax.inject.Inject - -/** - * Controller to handle presenting the priority conversations onboarding dialog - */ -class PriorityOnboardingDialogController @Inject constructor( - val view: View, - val context: Context, - private val ignoresDnd: Boolean, - private val showsAsBubble: Boolean, - val icon: Drawable, - private val onConversationSettingsClickListener: OnConversationSettingsClickListener, - val badge: Drawable, - private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager, - private val shadeController: ShadeController -) { - - private lateinit var dialog: Dialog - private lateinit var shortcutInfo: ShortcutInfo - private val OVERSHOOT: Interpolator = PathInterpolator(0.4f, 0f, 0.2f, 1.4f) - private val IMPORTANCE_ANIM_DELAY = 150L - private val IMPORTANCE_ANIM_GROW_DURATION = 250L - private val IMPORTANCE_ANIM_SHRINK_DURATION = 200L - private val IMPORTANCE_ANIM_SHRINK_DELAY = 25L - - fun init(info: ShortcutInfo) { - shortcutInfo = info - initDialog() - } - - fun show() { - dialog.show() - } - - private fun done() { - // Log that the user has seen the onboarding - Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true) - dialog.dismiss() - shadeController.animateCollapsePanels() - peopleSpaceWidgetManager.requestPinAppWidget(shortcutInfo, Bundle()) - } - - private fun settings() { - // Log that the user has seen the onboarding - Prefs.putBoolean(context, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true) - dialog.dismiss() - onConversationSettingsClickListener?.onClick() - } - - class Builder @Inject constructor() { - private lateinit var view: View - private lateinit var context: Context - private var ignoresDnd = false - private var showAsBubble = false - private lateinit var icon: Drawable - private lateinit var onConversationSettingsClickListener: - OnConversationSettingsClickListener - private lateinit var badge: Drawable - private lateinit var peopleSpaceWidgetManager: PeopleSpaceWidgetManager - private lateinit var shadeController: ShadeController - - fun setView(v: View): Builder { - view = v - return this - } - - fun setContext(c: Context): Builder { - context = c - return this - } - - fun setIgnoresDnd(ignore: Boolean): Builder { - ignoresDnd = ignore - return this - } - - fun setShowsAsBubble(bubble: Boolean): Builder { - showAsBubble = bubble - return this - } - - fun setIcon(draw: Drawable): Builder { - icon = draw - return this - } - fun setBadge(badge: Drawable): Builder { - this.badge = badge - return this - } - - fun setOnSettingsClick(onClick: OnConversationSettingsClickListener): Builder { - onConversationSettingsClickListener = onClick - return this - } - - fun setShadeController(shadeController: ShadeController): Builder { - this.shadeController = shadeController - return this - } - - fun setPeopleSpaceWidgetManager(peopleSpaceWidgetManager: PeopleSpaceWidgetManager): - Builder { - this.peopleSpaceWidgetManager = peopleSpaceWidgetManager - return this - } - - fun build(): PriorityOnboardingDialogController { - val controller = PriorityOnboardingDialogController( - view, context, ignoresDnd, showAsBubble, icon, - onConversationSettingsClickListener, badge, peopleSpaceWidgetManager, - shadeController) - return controller - } - } - - private fun initDialog() { - dialog = Dialog(context) - - if (dialog.window == null) { - throw IllegalStateException("Need a window for the onboarding dialog to show") - } - - dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) - // Prevent a11y readers from reading the first element in the dialog twice - dialog.setTitle("\u00A0") - dialog.apply { - setContentView(view) - setCanceledOnTouchOutside(true) - - findViewById<TextView>(R.id.done_button)?.setOnClickListener { - done() - } - - findViewById<TextView>(R.id.settings_button)?.setOnClickListener { - settings() - } - - findViewById<ImageView>(R.id.conversation_icon)?.setImageDrawable(icon) - findViewById<ImageView>(R.id.icon)?.setImageDrawable(badge) - val mImportanceRingView = findViewById<ImageView>(R.id.conversation_icon_badge_ring) - val conversationIconBadgeBg = findViewById<ImageView>(R.id.conversation_icon_badge_bg) - - val ring: GradientDrawable = mImportanceRingView.drawable as GradientDrawable - ring.mutate() - val bg = conversationIconBadgeBg.drawable as GradientDrawable - bg.mutate() - val ringColor = context.getResources() - .getColor(com.android.internal.R.color.conversation_important_highlight) - val standardThickness = context.resources.getDimensionPixelSize( - com.android.internal.R.dimen.importance_ring_stroke_width) - val largeThickness = context.resources.getDimensionPixelSize( - com.android.internal.R.dimen.importance_ring_anim_max_stroke_width) - val standardSize = context.resources.getDimensionPixelSize( - com.android.internal.R.dimen.importance_ring_size) - val baseSize = standardSize - standardThickness * 2 - val largeSize = baseSize + largeThickness * 2 - val bgSize = context.resources.getDimensionPixelSize( - com.android.internal.R.dimen.conversation_icon_size_badged) - - val animatorUpdateListener: ValueAnimator.AnimatorUpdateListener = - ValueAnimator.AnimatorUpdateListener { animation -> - val strokeWidth = animation.animatedValue as Int - ring.setStroke(strokeWidth, ringColor) - val newSize = baseSize + strokeWidth * 2 - ring.setSize(newSize, newSize) - mImportanceRingView.invalidate() - } - - val growAnimation: ValueAnimator = ValueAnimator.ofInt(0, largeThickness) - growAnimation.interpolator = LINEAR_OUT_SLOW_IN - growAnimation.duration = IMPORTANCE_ANIM_GROW_DURATION - growAnimation.addUpdateListener(animatorUpdateListener) - - val shrinkAnimation: ValueAnimator = - ValueAnimator.ofInt(largeThickness, standardThickness) - shrinkAnimation.duration = IMPORTANCE_ANIM_SHRINK_DURATION - shrinkAnimation.startDelay = IMPORTANCE_ANIM_SHRINK_DELAY - shrinkAnimation.interpolator = OVERSHOOT - shrinkAnimation.addUpdateListener(animatorUpdateListener) - shrinkAnimation.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { - // Shrink the badge bg so that it doesn't peek behind the animation - bg.setSize(baseSize, baseSize) - conversationIconBadgeBg.invalidate() - } - - override fun onAnimationEnd(animation: Animator?) { - // Reset bg back to normal size - bg.setSize(bgSize, bgSize) - conversationIconBadgeBg.invalidate() - } - }) - - val anims = AnimatorSet() - anims.startDelay = IMPORTANCE_ANIM_DELAY - anims.playSequentially(growAnimation, shrinkAnimation) - - val gapWidth = dialog.context.getResources().getDimensionPixelSize( - R.dimen.conversation_onboarding_bullet_gap_width) - val description = SpannableStringBuilder() - description.append(context.getText(R.string.priority_onboarding_show_at_top_text), - BulletSpan(gapWidth), /* flags */0) - description.append(System.lineSeparator()) - description.append(context.getText(R.string.priority_onboarding_show_avatar_text), - BulletSpan(gapWidth), /* flags */0) - if (showsAsBubble) { - description.append(System.lineSeparator()) - description.append(context.getText( - R.string.priority_onboarding_appear_as_bubble_text), - BulletSpan(gapWidth), /* flags */0) - } - if (ignoresDnd) { - description.append(System.lineSeparator()) - description.append(context.getText(R.string.priority_onboarding_ignores_dnd_text), - BulletSpan(gapWidth), /* flags */0) - } - findViewById<TextView>(R.id.behaviors).setText(description) - - window?.apply { - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - addFlags(wmFlags) - setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL) - setWindowAnimations(com.android.internal.R.style.Animation_InputMethod) - - attributes = attributes.apply { - format = PixelFormat.TRANSLUCENT - title = PriorityOnboardingDialogController::class.java.simpleName - gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL - fitInsetsTypes = attributes.fitInsetsTypes and statusBars().inv() - width = MATCH_PARENT - height = WRAP_CONTENT - } - } - anims.start() - } - } - - private val wmFlags = (WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS - or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) -} 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 b81619317b95..506d8a185adc 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 @@ -1000,7 +1000,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mAmbientState.setCurrentScrollVelocity(mScroller.isFinished() ? 0 : mScroller.getCurrVelocity()); - mAmbientState.setScrollY(mOwnScrollY); mStackScrollAlgorithm.resetViewStates(mAmbientState, getSpeedBumpIndex()); if (!isCurrentlyAnimating() && !mNeedsAnimation) { applyCurrentState(); @@ -1143,16 +1142,18 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ private void updateStackPosition() { // Consider interpolating from an mExpansionStartY for use on lockscreen and AOD - final float stackY = MathUtils.lerp(0, mTopPadding, mAmbientState.getExpansionFraction()); + final float fraction = mAmbientState.getExpansionFraction(); + final float stackY = MathUtils.lerp(0, mTopPadding, fraction); mAmbientState.setStackY(stackY); if (mOnStackYChanged != null) { mOnStackYChanged.run(); } - final float shadeBottom = getHeight() - getEmptyBottomMargin(); - mAmbientState.setStackEndHeight(shadeBottom - mTopPadding); + final float stackEndHeight = getHeight() - getEmptyBottomMargin() - mTopPadding; + mAmbientState.setStackEndHeight(stackEndHeight); mAmbientState.setStackHeight( - MathUtils.lerp(0, shadeBottom - mTopPadding, mAmbientState.getExpansionFraction())); + MathUtils.lerp(stackEndHeight * StackScrollAlgorithm.START_FRACTION, + stackEndHeight, fraction)); } void setOnStackYChanged(Runnable onStackYChanged) { @@ -2439,18 +2440,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.COORDINATOR) - public int getPeekHeight() { - final ExpandableView firstChild = getFirstChildNotGone(); - final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight() - : mCollapsedSize; - int shelfHeight = 0; - if (getLastVisibleSection() != null && mShelf.getVisibility() != GONE) { - shelfHeight = mShelf.getIntrinsicHeight(); - } - return mIntrinsicPadding + firstChildMinHeight + shelfHeight; - } - - @ShadeViewRefactor(RefactorComponent.COORDINATOR) private int clampPadding(int desiredPadding) { return Math.max(desiredPadding, mIntrinsicPadding); } @@ -4542,7 +4531,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable // We still want to call the normal scrolled changed for accessibility reasons onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY); mOwnScrollY = ownScrollY; - updateChildren(); + mAmbientState.setScrollY(mOwnScrollY); updateOnScrollChange(); updateStackPosition(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index b039df3f32af..f7eb574feac3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -1061,10 +1061,6 @@ public class NotificationStackScrollLayoutController { mView.setUnlockHintRunning(running); } - public float getPeekHeight() { - return mView.getPeekHeight(); - } - public boolean isFooterViewNotGone() { return mView.isFooterViewNotGone(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index c1a5f148d4ca..413048d6ce54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -42,6 +42,8 @@ import java.util.List; */ public class StackScrollAlgorithm { + public static final float START_FRACTION = 0.3f; + private static final String LOG_TAG = "StackScrollAlgorithm"; private final ViewGroup mHostView; @@ -442,7 +444,8 @@ public class StackScrollAlgorithm { maxViewHeight = algorithmState.viewHeightBeforeShelf; } } - viewState.height = (int) MathUtils.lerp(0, maxViewHeight, expansionFraction); + viewState.height = (int) MathUtils.lerp(maxViewHeight * START_FRACTION, maxViewHeight, + expansionFraction); } currentYPosition += viewState.height + expansionFraction * mPaddingBetweenElements; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index 76657ad5ab07..16bed6f3f38d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -43,7 +43,6 @@ import com.android.systemui.animation.Interpolators; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager; @@ -92,7 +91,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private CommandQueue mCommandQueue; private OngoingCallController mOngoingCallController; private final SystemStatusAnimationScheduler mAnimationScheduler; - private final PrivacyDotViewController mDotViewController; + private final StatusBarLocationPublisher mLocationPublisher; private NotificationIconAreaController mNotificationIconAreaController; private List<String> mBlockedIcons = new ArrayList<>(); @@ -120,12 +119,12 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public CollapsedStatusBarFragment( OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, - PrivacyDotViewController dotViewController, + StatusBarLocationPublisher locationPublisher, NotificationIconAreaController notificationIconAreaController ) { mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; - mDotViewController = dotViewController; + mLocationPublisher = locationPublisher; mNotificationIconAreaController = notificationIconAreaController; } @@ -540,7 +539,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue int leftMargin = left - mStatusBar.getLeft(); int rightMargin = mStatusBar.getRight() - right; - mDotViewController.setStatusBarMargins(leftMargin, rightMargin); + mLocationPublisher.updateStatusBarMargin(leftMargin, rightMargin); } // Listen for view end changes of PhoneStatusBarView and publish that to the privacy dot diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index 0b747f94e935..42f301d2f222 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -118,7 +118,6 @@ public class HeadsUpTouchHelper implements Gefingerpoken { mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f ? (float) startHeight / maxPanelHeight : 0f); mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight); - mPanel.startExpandingFromPeek(); // This call needs to be after the expansion start otherwise we will get a // flicker of one frame as it's not expanded yet. mHeadsUpManager.unpinAll(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java index 9787a9446019..3181f520dca2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java @@ -22,12 +22,12 @@ import android.app.Notification; import android.os.SystemClock; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; -import android.util.Log; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dependency; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; +import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -41,21 +41,17 @@ import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** * A helper class dealing with the alert interactions between {@link NotificationGroupManagerLegacy} * and {@link HeadsUpManager}. In particular, this class deals with keeping - * the correct notification in a group alerting based off the group suppression and alertOverride. + * the correct notification in a group alerting based off the group suppression. */ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener, StateListener { private static final long ALERT_TRANSFER_TIMEOUT = 300; - private static final String TAG = "NotifGroupAlertTransfer"; - private static final boolean DEBUG = StatusBar.DEBUG; - private static final boolean SPEW = StatusBar.SPEW; /** * The list of entries containing group alert metadata for each group. Keyed by group key. @@ -146,98 +142,41 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis @Override public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) { - if (DEBUG) { - Log.d(TAG, "!! onGroupSuppressionChanged: group.summary=" + group.summary - + " suppressed=" + suppressed); - } - NotificationEntry oldAlertOverride = group.alertOverride; - onGroupChanged(group, oldAlertOverride); - } - - @Override - public void onGroupAlertOverrideChanged(NotificationGroup group, - @Nullable NotificationEntry oldAlertOverride, - @Nullable NotificationEntry newAlertOverride) { - if (DEBUG) { - Log.d(TAG, "!! onGroupAlertOverrideChanged: group.summary=" + group.summary - + " oldAlertOverride=" + oldAlertOverride - + " newAlertOverride=" + newAlertOverride); - } - onGroupChanged(group, oldAlertOverride); - } - }; - - /** - * Called when either the suppressed or alertOverride fields of the group changed - * - * @param group the group which changed - * @param oldAlertOverride the previous value of group.alertOverride - */ - private void onGroupChanged(NotificationGroup group, - NotificationEntry oldAlertOverride) { - // Group summary can be null if we are no longer suppressed because the summary was - // removed. In that case, we don't need to alert the summary. - if (group.summary == null) { - if (DEBUG) { - Log.d(TAG, "onGroupChanged: summary is null"); - } - return; - } - if (group.suppressed || group.alertOverride != null) { - checkForForwardAlertTransfer(group.summary, oldAlertOverride); - } else { - if (DEBUG) { - Log.d(TAG, "onGroupChanged: maybe transfer back"); - } - GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey( - group.summary.getSbn())); - // Group is no longer suppressed or overridden. - // We should check if we need to transfer the alert back to the summary. - if (groupAlertEntry.mAlertSummaryOnNextAddition) { - if (!mHeadsUpManager.isAlerting(group.summary.getKey())) { - alertNotificationWhenPossible(group.summary); + if (suppressed) { + if (mHeadsUpManager.isAlerting(group.summary.getKey())) { + handleSuppressedSummaryAlerted(group.summary, mHeadsUpManager); } - groupAlertEntry.mAlertSummaryOnNextAddition = false; } else { - checkShouldTransferBack(groupAlertEntry); + // Group summary can be null if we are no longer suppressed because the summary was + // removed. In that case, we don't need to alert the summary. + if (group.summary == null) { + return; + } + GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey( + group.summary.getSbn())); + // Group is no longer suppressed. We should check if we need to transfer the alert + // back to the summary now that it's no longer suppressed. + if (groupAlertEntry.mAlertSummaryOnNextAddition) { + if (!mHeadsUpManager.isAlerting(group.summary.getKey())) { + alertNotificationWhenPossible(group.summary, mHeadsUpManager); + } + groupAlertEntry.mAlertSummaryOnNextAddition = false; + } else { + checkShouldTransferBack(groupAlertEntry); + } } } - } + }; @Override public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { - if (DEBUG) { - Log.d(TAG, "!! onHeadsUpStateChanged: entry=" + entry + " isHeadsUp=" + isHeadsUp); - } - if (isHeadsUp && entry.getSbn().getNotification().isGroupSummary()) { - // a group summary is alerting; trigger the forward transfer checks - checkForForwardAlertTransfer(entry, /* oldAlertOverride */ null); - } + onAlertStateChanged(entry, isHeadsUp, mHeadsUpManager); } - /** - * Handles changes in a group's suppression or alertOverride, but where at least one of those - * conditions is still true (either the group is suppressed, the group has an alertOverride, - * or both). The method determined which kind of child needs to receive the alert, finds the - * entry currently alerting, and makes the transfer. - * - * Internally, this is handled with two main cases: the override needs the alert, or there is - * no override but the summary is suppressed (so an isolated child needs the alert). - * - * @param summary the notification entry of the summary of the logical group. - * @param oldAlertOverride the former value of group.alertOverride, before whatever event - * required us to check for for a transfer condition. - */ - private void checkForForwardAlertTransfer(NotificationEntry summary, - NotificationEntry oldAlertOverride) { - if (DEBUG) { - Log.d(TAG, "checkForForwardAlertTransfer: enter"); - } - NotificationGroup group = mGroupManager.getGroupForSummary(summary.getSbn()); - if (group != null && group.alertOverride != null) { - handleOverriddenSummaryAlerted(summary); - } else if (mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())) { - handleSuppressedSummaryAlerted(summary, oldAlertOverride); + private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting, + AlertingNotificationManager alertManager) { + if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.getSbn())) { + handleSuppressedSummaryAlerted(entry, alertManager); } } @@ -247,16 +186,9 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis // see as early as we can if we need to abort a transfer. @Override public void onPendingEntryAdded(NotificationEntry entry) { - if (DEBUG) { - Log.d(TAG, "!! onPendingEntryAdded: entry=" + entry); - } String groupKey = mGroupManager.getGroupKey(entry.getSbn()); GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey); - if (groupAlertEntry != null && groupAlertEntry.mGroup.alertOverride == null) { - // new pending group entries require us to transfer back from the child to the - // group, but alertOverrides are only present in very limited circumstances, so - // while it's possible the group should ALSO alert, the previous detection which set - // this alertOverride won't be invalidated by this notification added to this group. + if (groupAlertEntry != null) { checkShouldTransferBack(groupAlertEntry); } } @@ -330,128 +262,43 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis } /** - * Handles the scenario where a summary that has been suppressed is itself, or has a former - * alertOverride (in the form of an isolated logical child) which was alerted. A suppressed + * Handles the scenario where a summary that has been suppressed is alerted. A suppressed * summary should for all intents and purposes be invisible to the user and as a result should * not alert. When this is the case, it is our responsibility to pass the alert to the * appropriate child which will be the representative notification alerting for the group. * - * @param summary the summary that is suppressed and (potentially) alerting - * @param oldAlertOverride the alertOverride before whatever event triggered this method. If - * the alert override was removed, this will be the entry that should - * be transferred back from. + * @param summary the summary that is suppressed and alerting + * @param alertManager the alert manager that manages the alerting summary */ private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary, - NotificationEntry oldAlertOverride) { - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: summary=" + summary); - } + @NonNull AlertingNotificationManager alertManager) { + StatusBarNotification sbn = summary.getSbn(); GroupAlertEntry groupAlertEntry = - mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn())); - + mGroupAlertEntries.get(mGroupManager.getGroupKey(sbn)); if (!mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn()) + || !alertManager.isAlerting(sbn.getKey()) || groupAlertEntry == null) { - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: invalid state"); - } - return; - } - boolean summaryIsAlerting = mHeadsUpManager.isAlerting(summary.getKey()); - boolean priorityIsAlerting = oldAlertOverride != null - && mHeadsUpManager.isAlerting(oldAlertOverride.getKey()); - if (!summaryIsAlerting && !priorityIsAlerting) { - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: no summary or override alerting"); - } return; } if (pendingInflationsWillAddChildren(groupAlertEntry.mGroup)) { // New children will actually be added to this group, let's not transfer the alert. - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: pending inflations"); - } return; } NotificationEntry child = mGroupManager.getLogicalChildren(summary.getSbn()).iterator().next(); - if (summaryIsAlerting) { - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: transfer summary -> child"); - } - tryTransferAlertState(summary, /*from*/ summary, /*to*/ child, groupAlertEntry); - return; - } - // Summary didn't have the alert, so we're in "transfer back" territory. First, make sure - // it's not too late to transfer back, then transfer the alert from the oldAlertOverride to - // the isolated child which should receive the alert. - if (!canStillTransferBack(groupAlertEntry)) { - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: transfer from override: too late"); - } - return; - } - - if (DEBUG) { - Log.d(TAG, "handleSuppressedSummaryAlerted: transfer override -> child"); - } - tryTransferAlertState(summary, /*from*/ oldAlertOverride, /*to*/ child, groupAlertEntry); - } - - /** - * Checks for and handles the scenario where the given entry is the summary of a group which - * has an alertOverride, and either the summary itself or one of its logical isolated children - * is currently alerting (which happens if the summary is suppressed). - */ - private void handleOverriddenSummaryAlerted(NotificationEntry summary) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: summary=" + summary); - } - GroupAlertEntry groupAlertEntry = - mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn())); - NotificationGroup group = mGroupManager.getGroupForSummary(summary.getSbn()); - if (group == null || group.alertOverride == null || groupAlertEntry == null) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: invalid state"); - } - return; - } - boolean summaryIsAlerting = mHeadsUpManager.isAlerting(summary.getKey()); - if (summaryIsAlerting) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: transfer summary -> override"); - } - tryTransferAlertState(summary, /*from*/ summary, group.alertOverride, groupAlertEntry); - return; - } - // Summary didn't have the alert, so we're in "transfer back" territory. First, make sure - // it's not too late to transfer back, then remove the alert from any of the logical - // children, and if one of them was alerting, we can alert the override. - if (!canStillTransferBack(groupAlertEntry)) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: transfer from child: too late"); - } - return; - } - List<NotificationEntry> children = mGroupManager.getLogicalChildren(summary.getSbn()); - if (children == null) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: no children"); - } - return; - } - children.remove(group.alertOverride); // do not release the alert on our desired destination - boolean releasedChild = releaseChildAlerts(children); - if (releasedChild) { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: transfer child -> override"); + if (child != null) { + if (child.getRow().keepInParent() + || child.isRowRemoved() + || child.isRowDismissed()) { + // The notification is actually already removed. No need to alert it. + return; } - tryTransferAlertState(summary, /*from*/ null, group.alertOverride, groupAlertEntry); - } else { - if (DEBUG) { - Log.d(TAG, "handleOverriddenSummaryAlerted: no child alert released"); + if (!alertManager.isAlerting(child.getKey()) && onlySummaryAlerts(summary)) { + groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime(); } + transferAlertState(summary, child, alertManager); } } @@ -460,37 +307,14 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis * immediately to have the incorrect one up as short as possible. The second should alert * when possible. * - * @param summary entry of the summary * @param fromEntry entry to transfer alert from * @param toEntry entry to transfer to + * @param alertManager alert manager for the alert type */ - private void tryTransferAlertState( - NotificationEntry summary, - NotificationEntry fromEntry, - NotificationEntry toEntry, - GroupAlertEntry groupAlertEntry) { - if (toEntry != null) { - if (toEntry.getRow().keepInParent() - || toEntry.isRowRemoved() - || toEntry.isRowDismissed()) { - // The notification is actually already removed. No need to alert it. - return; - } - if (!mHeadsUpManager.isAlerting(toEntry.getKey()) && onlySummaryAlerts(summary)) { - groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime(); - } - if (DEBUG) { - Log.d(TAG, "transferAlertState: fromEntry=" + fromEntry + " toEntry=" + toEntry); - } - transferAlertState(fromEntry, toEntry); - } - } - private void transferAlertState(@Nullable NotificationEntry fromEntry, - @NonNull NotificationEntry toEntry) { - if (fromEntry != null) { - mHeadsUpManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */); - } - alertNotificationWhenPossible(toEntry); + private void transferAlertState(@NonNull NotificationEntry fromEntry, @NonNull NotificationEntry toEntry, + @NonNull AlertingNotificationManager alertManager) { + alertManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */); + alertNotificationWhenPossible(toEntry, alertManager); } /** @@ -502,13 +326,11 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis * more children are coming. Thus, if a child is added within a certain timeframe after we * transfer, we back out and alert the summary again. * - * An alert can only transfer back within a small window of time after a transfer away from the - * summary to a child happened. - * * @param groupAlertEntry group alert entry to check */ private void checkShouldTransferBack(@NonNull GroupAlertEntry groupAlertEntry) { - if (canStillTransferBack(groupAlertEntry)) { + if (SystemClock.elapsedRealtime() - groupAlertEntry.mLastAlertTransferTime + < ALERT_TRANSFER_TIMEOUT) { NotificationEntry summary = groupAlertEntry.mGroup.summary; if (!onlySummaryAlerts(summary)) { @@ -516,17 +338,30 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis } ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren( summary.getSbn()); - int numActiveChildren = children.size(); + int numChildren = children.size(); int numPendingChildren = getPendingChildrenNotAlerting(groupAlertEntry.mGroup); - int numChildren = numActiveChildren + numPendingChildren; + numChildren += numPendingChildren; if (numChildren <= 1) { return; } - boolean releasedChild = releaseChildAlerts(children); + boolean releasedChild = false; + for (int i = 0; i < children.size(); i++) { + NotificationEntry entry = children.get(i); + if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) { + releasedChild = true; + mHeadsUpManager.removeNotification( + entry.getKey(), true /* releaseImmediately */); + } + if (mPendingAlerts.containsKey(entry.getKey())) { + // This is the child that would've been removed if it was inflated. + releasedChild = true; + mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true; + } + } if (releasedChild && !mHeadsUpManager.isAlerting(summary.getKey())) { - boolean notifyImmediately = numActiveChildren > 1; + boolean notifyImmediately = (numChildren - numPendingChildren) > 1; if (notifyImmediately) { - alertNotificationWhenPossible(summary); + alertNotificationWhenPossible(summary, mHeadsUpManager); } else { // Should wait until the pending child inflates before alerting. groupAlertEntry.mAlertSummaryOnNextAddition = true; @@ -536,61 +371,25 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis } } - private boolean canStillTransferBack(@NonNull GroupAlertEntry groupAlertEntry) { - return SystemClock.elapsedRealtime() - groupAlertEntry.mLastAlertTransferTime - < ALERT_TRANSFER_TIMEOUT; - } - - private boolean releaseChildAlerts(List<NotificationEntry> children) { - boolean releasedChild = false; - if (SPEW) { - Log.d(TAG, "releaseChildAlerts: numChildren=" + children.size()); - } - for (int i = 0; i < children.size(); i++) { - NotificationEntry entry = children.get(i); - if (SPEW) { - Log.d(TAG, "releaseChildAlerts: checking i=" + i + " entry=" + entry - + " onlySummaryAlerts=" + onlySummaryAlerts(entry) - + " isAlerting=" + mHeadsUpManager.isAlerting(entry.getKey()) - + " isPendingAlert=" + mPendingAlerts.containsKey(entry.getKey())); - } - if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) { - releasedChild = true; - mHeadsUpManager.removeNotification( - entry.getKey(), true /* releaseImmediately */); - } - if (mPendingAlerts.containsKey(entry.getKey())) { - // This is the child that would've been removed if it was inflated. - releasedChild = true; - mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true; - } - } - if (SPEW) { - Log.d(TAG, "releaseChildAlerts: didRelease=" + releasedChild); - } - return releasedChild; - } - /** * Tries to alert the notification. If its content view is not inflated, we inflate and continue * when the entry finishes inflating the view. * * @param entry entry to show + * @param alertManager alert manager for the alert type */ - private void alertNotificationWhenPossible(@NonNull NotificationEntry entry) { - @InflationFlag int contentFlag = mHeadsUpManager.getContentFlag(); + private void alertNotificationWhenPossible(@NonNull NotificationEntry entry, + @NonNull AlertingNotificationManager alertManager) { + @InflationFlag int contentFlag = alertManager.getContentFlag(); final RowContentBindParams params = mRowContentBindStage.getStageParams(entry); if ((params.getContentViews() & contentFlag) == 0) { - if (DEBUG) { - Log.d(TAG, "alertNotificationWhenPossible: async requestRebind entry=" + entry); - } mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry)); params.requireContentViews(contentFlag); mRowContentBindStage.requestRebind(entry, en -> { PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.getKey()); if (alertInfo != null) { if (alertInfo.isStillValid()) { - alertNotificationWhenPossible(entry); + alertNotificationWhenPossible(entry, mHeadsUpManager); } else { // The transfer is no longer valid. Free the content. mRowContentBindStage.getStageParams(entry).markContentViewsFreeable( @@ -601,16 +400,10 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis }); return; } - if (mHeadsUpManager.isAlerting(entry.getKey())) { - if (DEBUG) { - Log.d(TAG, "alertNotificationWhenPossible: continue alerting entry=" + entry); - } - mHeadsUpManager.updateNotification(entry.getKey(), true /* alert */); + if (alertManager.isAlerting(entry.getKey())) { + alertManager.updateNotification(entry.getKey(), true /* alert */); } else { - if (DEBUG) { - Log.d(TAG, "alertNotificationWhenPossible: start alerting entry=" + entry); - } - mHeadsUpManager.showNotification(entry); + alertManager.showNotification(entry); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index c79e503379bd..20b37e26dcee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -22,7 +22,6 @@ import static androidx.constraintlayout.widget.ConstraintSet.END; import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID; import static androidx.constraintlayout.widget.ConstraintSet.START; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; @@ -1730,7 +1729,6 @@ public class NotificationPanelViewController extends PanelViewController { return; } mExpectingSynthesizedDown = true; - InteractionJankMonitor.getInstance().begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); onTrackingStarted(); updatePanelExpanded(); } @@ -2075,20 +2073,18 @@ public class NotificationPanelViewController extends PanelViewController { setQsExpansionEnabled(mAmbientState.getScrollY() == 0); int radius = mScrimCornerRadius; - if (visible || !mShouldUseSplitNotificationShade) { - if (!mShouldUseSplitNotificationShade) { - top = (int) Math.min(qsPanelBottomY, notificationTop); - bottom = getView().getBottom(); - left = getView().getLeft(); - right = getView().getRight(); - radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius, - Math.min(top / (float) mScrimCornerRadius, 1f)); - } else { - top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding); - bottom = mNotificationStackScrollLayoutController.getHeight(); - left = mNotificationStackScrollLayoutController.getLeft(); - right = mNotificationStackScrollLayoutController.getRight(); - } + if (!mShouldUseSplitNotificationShade) { + top = (int) Math.min(qsPanelBottomY, notificationTop); + bottom = getView().getBottom(); + left = getView().getLeft(); + right = getView().getRight(); + radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius, + Math.min(top / (float) mScrimCornerRadius, 1f)); + } else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen + top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding); + bottom = mNotificationStackScrollLayoutController.getHeight(); + left = mNotificationStackScrollLayoutController.getLeft(); + right = mNotificationStackScrollLayoutController.getRight(); } // Fancy clipping for quick settings @@ -2698,6 +2694,7 @@ public class NotificationPanelViewController extends PanelViewController { mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed()); mIsExpanding = false; mMediaHierarchyManager.setCollapsingShadeFromQS(false); + mMediaHierarchyManager.setQsExpanded(mQsExpanded); if (isFullyCollapsed()) { DejankUtils.postAfterTraversal(new Runnable() { @Override @@ -2834,15 +2831,6 @@ public class NotificationPanelViewController extends PanelViewController { } @Override - protected float getPeekHeight() { - if (mNotificationStackScrollLayoutController.getNotGoneChildCount() > 0) { - return mNotificationStackScrollLayoutController.getPeekHeight(); - } else { - return mQsMinExpansionHeight; - } - } - - @Override protected boolean shouldUseDismissingAnimation() { return mBarState != StatusBarState.SHADE && (mKeyguardStateController.canDismissLockScreen() || !isTracking()); @@ -3709,6 +3697,12 @@ public class NotificationPanelViewController extends PanelViewController { @Override public void flingTopOverscroll(float velocity, boolean open) { + // in split shade mode we want to expand/collapse QS only when touch happens within QS + if (mShouldUseSplitNotificationShade + && (mInitialTouchX < mQsFrame.getX() + || mInitialTouchX > mQsFrame.getX() + mQsFrame.getWidth())) { + return; + } mLastOverscroll = 0f; mQsExpansionFromOverscroll = false; setQsExpansion(mQsExpansionHeight); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 28cfe214dd3a..64e2c1c5d268 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -212,7 +212,6 @@ public abstract class PanelBar extends FrameLayout { } else { pv.resetViews(false /* animate */); pv.setExpandedFraction(0); // just in case - pv.cancelPeek(); } if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting); if (!waiting && mState != STATE_CLOSED) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index d0bdf40d1f0b..f9a644fe2def 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -68,8 +68,6 @@ import java.util.ArrayList; public abstract class PanelViewController { public static final boolean DEBUG = PanelBar.DEBUG; public static final String TAG = PanelView.class.getSimpleName(); - private static final int INITIAL_OPENING_PEEK_DURATION = 200; - private static final int PEEK_ANIMATION_DURATION = 360; private static final int NO_FIXED_DURATION = -1; private static final long SHADE_OPEN_SPRING_OUT_DURATION = 350L; private static final long SHADE_OPEN_SPRING_BACK_DURATION = 200L; @@ -96,7 +94,6 @@ public abstract class PanelViewController { protected HeadsUpManagerPhone mHeadsUpManager; protected final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; - private float mPeekHeight; private float mHintDistance; private float mInitialOffsetOnTouch; private boolean mCollapsedAndHeadsUpOnDown; @@ -106,8 +103,6 @@ public abstract class PanelViewController { private boolean mHasLayoutedSinceDown; private float mUpdateFlingVelocity; private boolean mUpdateFlingOnLayout; - private boolean mPeekTouching; - private boolean mJustPeeked; private boolean mClosing; protected boolean mTracking; private boolean mTouchSlopExceeded; @@ -125,7 +120,6 @@ public abstract class PanelViewController { private boolean mHandlingPointerUp; private ValueAnimator mHeightAnimator; - private ObjectAnimator mPeekAnimator; private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private FlingAnimationUtils mFlingAnimationUtils; private FlingAnimationUtils mFlingAnimationUtilsClosing; @@ -195,40 +189,6 @@ public abstract class PanelViewController { } } - private void runPeekAnimation(long duration, float peekHeight, boolean collapseWhenFinished) { - mPeekHeight = peekHeight; - if (DEBUG) logf("peek to height=%.1f", mPeekHeight); - if (mHeightAnimator != null) { - return; - } - if (mPeekAnimator != null) { - mPeekAnimator.cancel(); - } - mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight).setDuration( - duration); - mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - mPeekAnimator.addListener(new AnimatorListenerAdapter() { - private boolean mCancelled; - - @Override - public void onAnimationCancel(Animator animation) { - mCancelled = true; - } - - @Override - public void onAnimationEnd(Animator animation) { - mPeekAnimator = null; - if (!mCancelled && collapseWhenFinished) { - mView.postOnAnimation(mPostCollapseRunnable); - } - - } - }); - notifyExpandingStarted(); - mPeekAnimator.start(); - mJustPeeked = true; - } - protected AmbientState getAmbientState() { return mAmbientState; } @@ -336,8 +296,6 @@ public abstract class PanelViewController { } private void startOpening(MotionEvent event) { - runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(), - false /* collapseWhenFinished */); notifyBarPanelExpansionChanged(); maybeVibrateOnOpening(); @@ -375,10 +333,6 @@ public abstract class PanelViewController { return Math.abs(yDiff) >= Math.abs(xDiff); } - protected void startExpandingFromPeek() { - mStatusBar.handlePeekToExpandTransistion(); - } - protected void startExpandMotion(float newX, float newY, boolean startTracking, float expandedHeight) { if (!mHandlingPointerUp) { @@ -442,18 +396,6 @@ public abstract class PanelViewController { if (mUpdateFlingOnLayout) { mUpdateFlingVelocity = vel; } - } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking - && !mStatusBar.isBouncerShowing() - && !mKeyguardStateController.isKeyguardFadingAway()) { - long timePassed = SystemClock.uptimeMillis() - mDownTime; - if (timePassed < ViewConfiguration.getLongPressTimeout()) { - // Let's show the user that they can actually expand the panel - runPeekAnimation( - PEEK_ANIMATION_DURATION, getPeekHeight(), true /* collapseWhenFinished */); - } else { - // We need to collapse the panel since we peeked to the small height. - mView.postOnAnimation(mPostCollapseRunnable); - } } else if (!mStatusBar.isBouncerShowing() && !mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) { boolean expands = onEmptySpaceClick(mInitialTouchX); @@ -461,7 +403,6 @@ public abstract class PanelViewController { } mVelocityTracker.clear(); - mPeekTouching = false; } protected float getCurrentExpandVelocity() { @@ -582,7 +523,6 @@ public abstract class PanelViewController { protected void fling(float vel, boolean expand, float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) { - cancelPeek(); float target = expand ? getMaxPanelHeight() : 0; if (!expand) { mClosing = true; @@ -638,6 +578,12 @@ public abstract class PanelViewController { private boolean mCancelled; @Override + public void onAnimationStart(Animator animation) { + InteractionJankMonitor.getInstance() + .begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + } + + @Override public void onAnimationCancel(Animator animation) { mCancelled = true; } @@ -718,10 +664,6 @@ public abstract class PanelViewController { return; } - if (mPeekAnimator != null || mPeekTouching) { - return; - } - if (mTracking && !isTrackingBlocked()) { return; } @@ -884,20 +826,6 @@ public abstract class PanelViewController { } }; - public void cancelPeek() { - boolean cancelled = false; - if (mPeekAnimator != null) { - cancelled = true; - mPeekAnimator.cancel(); - } - - if (cancelled) { - // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also - // notify mBar that we might have closed ourselves. - notifyBarPanelExpansionChanged(); - } - } - public void expand(final boolean animate) { if (!isFullyCollapsed() && !isCollapsing()) { return; @@ -907,7 +835,6 @@ public abstract class PanelViewController { mAnimateAfterExpanding = animate; mUpdateFlingOnLayout = false; abortAnimations(); - cancelPeek(); if (mTracking) { onTrackingStopped(true /* expands */); // The panel is expanded after this call. } @@ -958,7 +885,6 @@ public abstract class PanelViewController { } private void abortAnimations() { - cancelPeek(); cancelHeightAnimator(); mView.removeCallbacks(mPostCollapseRunnable); mView.removeCallbacks(mFlingCollapseRunnable); @@ -976,7 +902,6 @@ public abstract class PanelViewController { if (mHeightAnimator != null || mTracking) { return; } - cancelPeek(); notifyExpandingStarted(); startUnlockHintAnimationPhase1(() -> { notifyExpandingFinished(); @@ -1079,7 +1004,7 @@ public abstract class PanelViewController { if (mBar != null) { mBar.panelExpansionChanged( mExpandedFraction, - mExpandedFraction > 0f || mPeekAnimator != null || mInstantExpanding + mExpandedFraction > 0f || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null); } @@ -1119,19 +1044,16 @@ public abstract class PanelViewController { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s" - + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s " + + " tracking=%s timeAnim=%s%s " + "touchDisabled=%s" + "]", this.getClass().getSimpleName(), getExpandedHeight(), getMaxPanelHeight(), - mClosing ? "T" : "f", mTracking ? "T" : "f", mJustPeeked ? "T" : "f", mPeekAnimator, - ((mPeekAnimator != null && mPeekAnimator.isStarted()) ? " (started)" : ""), - mHeightAnimator, + mClosing ? "T" : "f", mTracking ? "T" : "f", mHeightAnimator, ((mHeightAnimator != null && mHeightAnimator.isStarted()) ? " (started)" : ""), mTouchDisabled ? "T" : "f")); } public abstract void resetViews(boolean animate); - protected abstract float getPeekHeight(); /** * @return whether "Clear all" button will be visible when the panel is fully expanded @@ -1206,10 +1128,8 @@ public abstract class PanelViewController { mAnimatingOnDown = mHeightAnimator != null; mMinExpandHeight = 0.0f; mDownTime = SystemClock.uptimeMillis(); - if (mAnimatingOnDown && mClosing && !mHintAnimationRunning - || mPeekAnimator != null) { + if (mAnimatingOnDown && mClosing && !mHintAnimationRunning) { cancelHeightAnimator(); - cancelPeek(); mTouchSlopExceeded = true; return true; } @@ -1217,7 +1137,6 @@ public abstract class PanelViewController { mInitialTouchX = x; mTouchStartedInEmptyArea = !isInContentBounds(x, y); mTouchSlopExceeded = mTouchSlopExceededBeforeDown; - mJustPeeked = false; mMotionAborted = false; mPanelClosedOnDown = isFullyCollapsed(); mCollapsedAndHeadsUpOnDown = false; @@ -1296,8 +1215,6 @@ public abstract class PanelViewController { * We capture touch events here and update the expand height here in case according to * the users fingers. This also handles multi-touch. * - * If the user just clicks shortly, we show a quick peek of the shade. - * * Flinging is also enabled in order to open or close the shade. */ @@ -1317,25 +1234,22 @@ public abstract class PanelViewController { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); - mJustPeeked = false; mMinExpandHeight = 0.0f; mPanelClosedOnDown = isFullyCollapsed(); mHasLayoutedSinceDown = false; mUpdateFlingOnLayout = false; mMotionAborted = false; - mPeekTouching = mPanelClosedOnDown; mDownTime = SystemClock.uptimeMillis(); mTouchAboveFalsingThreshold = false; mCollapsedAndHeadsUpOnDown = isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp(); addMovement(event); if (!mGestureWaitForTouchSlop || (mHeightAnimator != null - && !mHintAnimationRunning) || mPeekAnimator != null) { + && !mHintAnimationRunning)) { mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning) - || mPeekAnimator != null || mTouchSlopExceededBeforeDown; + || mTouchSlopExceededBeforeDown; cancelHeightAnimator(); - cancelPeek(); onTrackingStarted(); } if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp() @@ -1375,7 +1289,7 @@ public abstract class PanelViewController { || mIgnoreXTouchSlop)) { mTouchSlopExceeded = true; if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) { - if (!mJustPeeked && mInitialOffsetOnTouch != 0f) { + if (mInitialOffsetOnTouch != 0f) { startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); h = 0; } @@ -1384,26 +1298,12 @@ public abstract class PanelViewController { } } float newHeight = Math.max(0, h + mInitialOffsetOnTouch); - if (newHeight > mPeekHeight) { - if (mPeekAnimator != null) { - mPeekAnimator.cancel(); - } - mJustPeeked = false; - } else if (mPeekAnimator == null && mJustPeeked) { - // The initial peek has finished, but we haven't dragged as far yet, lets - // speed it up by starting at the peek height. - mInitialOffsetOnTouch = mExpandedHeight; - mInitialTouchY = y; - mMinExpandHeight = mExpandedHeight; - mJustPeeked = false; - } newHeight = Math.max(newHeight, mMinExpandHeight); if (-h >= getFalsingThreshold()) { mTouchAboveFalsingThreshold = true; mUpwardsWhenThresholdReached = isDirectionUpwards(x, y); } - if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking) - && !isTrackingBlocked()) { + if ((!mGestureWaitForTouchSlop || mTracking) && !isTrackingBlocked()) { setExpandedHeightInternal(newHeight); } break; @@ -1412,11 +1312,14 @@ public abstract class PanelViewController { case MotionEvent.ACTION_CANCEL: addMovement(event); endMotionEvent(event, x, y, false /* forceCancel */); - InteractionJankMonitor monitor = InteractionJankMonitor.getInstance(); - if (event.getActionMasked() == MotionEvent.ACTION_UP) { - monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); - } else { - monitor.cancel(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + // mHeightAnimator is null, there is no remaining frame, ends instrumenting. + if (mHeightAnimator == null) { + InteractionJankMonitor monitor = InteractionJankMonitor.getInstance(); + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + } else { + monitor.cancel(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); + } } break; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index c09293115492..a952db2a6073 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -163,7 +163,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private final float mDefaultScrimAlpha; // Assuming the shade is expanded during initialization - private float mExpansionFraction = 1f; + private float mPanelExpansion = 1f; private float mQsExpansion; private boolean mQsBottomVisible; @@ -487,8 +487,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump if (isNaN(fraction)) { throw new IllegalArgumentException("Fraction should not be NaN"); } - if (mExpansionFraction != fraction) { - mExpansionFraction = fraction; + if (mPanelExpansion != fraction) { + mPanelExpansion = fraction; boolean relevantState = (mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD @@ -641,7 +641,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mBehindTint = Color.BLACK; } else { mBehindAlpha = backAlpha; - mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion); + if (mState == ScrimState.SHADE_LOCKED) { + // going from KEYGUARD to SHADE_LOCKED state + mNotificationsAlpha = getInterpolatedFraction(); + } else { + mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion); + } mBehindTint = backTint; } } @@ -805,7 +810,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } private float getInterpolatedFraction() { - float frac = mExpansionFraction; + float frac = mPanelExpansion; // let's start this 20% of the way down the screen frac = frac * 1.2f - 0.2f; if (frac <= 0) { @@ -1165,7 +1170,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump pw.print(" mDefaultScrimAlpha="); pw.println(mDefaultScrimAlpha); pw.print(" mExpansionFraction="); - pw.println(mExpansionFraction); + pw.println(mPanelExpansion); } public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index aaef739af8c4..bd17d00063d7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -209,7 +209,6 @@ import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.charging.WiredChargingRippleController; -import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -429,7 +428,7 @@ public class StatusBar extends SystemUI implements DemoMode, private NotificationsController mNotificationsController; private final OngoingCallController mOngoingCallController; private final SystemStatusAnimationScheduler mAnimationScheduler; - private final PrivacyDotViewController mDotViewController; + private final StatusBarLocationPublisher mStatusBarLocationPublisher; // expanded notifications // the sliding/resizing panel within the notification window @@ -799,7 +798,7 @@ public class StatusBar extends SystemUI implements DemoMode, WiredChargingRippleController chargingRippleAnimationController, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, - PrivacyDotViewController dotViewController, + StatusBarLocationPublisher locationPublisher, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController) { super(context); @@ -882,7 +881,7 @@ public class StatusBar extends SystemUI implements DemoMode, mChargingRippleAnimationController = chargingRippleAnimationController; mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; - mDotViewController = dotViewController; + mStatusBarLocationPublisher = locationPublisher; mFeatureFlags = featureFlags; mExpansionChangedListeners = new ArrayList<>(); @@ -1175,7 +1174,7 @@ public class StatusBar extends SystemUI implements DemoMode, new CollapsedStatusBarFragment( mOngoingCallController, mAnimationScheduler, - mDotViewController, + mStatusBarLocationPublisher, mNotificationIconAreaController), CollapsedStatusBarFragment.TAG) .commit(); @@ -3095,19 +3094,7 @@ public class StatusBar extends SystemUI implements DemoMode, } } - void handlePeekToExpandTransistion() { - try { - // consider the transition from peek to expanded to be a panel open, - // but not one that clears notification effects. - int notificationLoad = mNotificationsController.getActiveNotificationsCount(); - mBarService.onPanelRevealed(false, notificationLoad); - } catch (RemoteException ex) { - // Won't fail unless the world has ended. - } - } - // Visibility reporting - void handleVisibleToUserChangedImpl(boolean visibleToUser) { if (visibleToUser) { /* The LEDs are turned off when the notification panel is shown, even just a little bit. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt new file mode 100644 index 000000000000..4e5ecfe3f623 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.policy.CallbackController +import java.lang.ref.WeakReference +import javax.inject.Inject + +/** + * Publishes updates to the status bar's margins. + * + * While the status bar view consumes the entire width of the device, the status bar + * contents are laid out with margins for rounded corners, padding from the absolute + * edges, and potentially display cutouts in the corner. + */ +@SysUISingleton +class StatusBarLocationPublisher @Inject constructor() +: CallbackController<StatusBarMarginUpdatedListener> { + private val listeners = mutableSetOf<WeakReference<StatusBarMarginUpdatedListener>>() + + var marginLeft: Int = 0 + private set + var marginRight: Int = 0 + private set + + override fun addCallback(listener: StatusBarMarginUpdatedListener) { + listeners.add(WeakReference(listener)) + } + + override fun removeCallback(listener: StatusBarMarginUpdatedListener) { + var toRemove: WeakReference<StatusBarMarginUpdatedListener>? = null + for (l in listeners) { + if (l.get() == listener) { + toRemove = l + } + } + + if (toRemove != null) { + listeners.remove(toRemove) + } + } + + fun updateStatusBarMargin(left: Int, right: Int) { + marginLeft = left + marginRight = right + + notifyListeners() + } + + private fun notifyListeners() { + var listenerList: List<WeakReference<StatusBarMarginUpdatedListener>> + synchronized(this) { + listenerList = listeners.toList() + } + + listenerList.forEach { wrapper -> + if (wrapper.get() == null) { + listeners.remove(wrapper) + } + + wrapper.get()?.onStatusBarMarginUpdated(marginLeft, marginRight) + } + } +} + +interface StatusBarMarginUpdatedListener { + fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 66e1c2e1b571..ae11a74748cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -62,7 +62,6 @@ import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.charging.WiredChargingRippleController; -import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; @@ -91,6 +90,7 @@ import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; @@ -212,7 +212,7 @@ public interface StatusBarPhoneModule { WiredChargingRippleController chargingRippleAnimationController, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, - PrivacyDotViewController dotViewController, + StatusBarLocationPublisher locationPublisher, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController) { return new StatusBar( @@ -298,7 +298,7 @@ public interface StatusBarPhoneModule { chargingRippleAnimationController, ongoingCallController, animationScheduler, - dotViewController, + locationPublisher, featureFlags, keyguardUnlockAnimationController); } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java index b95545576e56..10c4a55ad240 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java @@ -675,7 +675,6 @@ public class BubblesManager implements Dumpable { } try { int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; - flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE; mBarService.onNotificationBubbleChanged(entry.getKey(), true, flags); } catch (RemoteException e) { Log.e(TAG, e.getMessage()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java index 60786f6afe99..1c3922a57368 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java @@ -29,8 +29,8 @@ import android.view.MotionEvent; import androidx.test.filters.SmallTest; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.DeviceConfigProxyFake; -import com.android.systemui.util.sensors.ProximitySensor; import org.junit.After; import org.junit.Before; @@ -149,8 +149,17 @@ public class ProximityClassifierTest extends ClassifierTest { motionEvent.recycle(); } - private ProximitySensor.ThresholdSensorEvent createSensorEvent( - boolean covered, long timestampMs) { - return new ProximitySensor.ThresholdSensorEvent(covered, timestampMs * NS_PER_MS); + private FalsingManager.ProximityEvent createSensorEvent(boolean covered, long timestampMs) { + return new FalsingManager.ProximityEvent() { + @Override + public boolean getCovered() { + return covered; + } + + @Override + public long getTimestampNs() { + return timestampMs * NS_PER_MS; + } + }; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 94252d2b8331..800daa1e96aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -17,7 +17,6 @@ package com.android.systemui.media import android.content.Intent -import android.content.res.ColorStateList import android.graphics.Color import android.graphics.drawable.GradientDrawable import android.graphics.drawable.RippleDrawable @@ -222,17 +221,6 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test - fun bindBackgroundColor() { - player.attachPlayer(holder) - val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(), - emptyList(), PACKAGE, session.getSessionToken(), null, device, true, null) - player.bindPlayer(state, PACKAGE) - val list = ArgumentCaptor.forClass(ColorStateList::class.java) - verify(view).setBackgroundTintList(list.capture()) - assertThat(list.value).isEqualTo(ColorStateList.valueOf(BG_COLOR)) - } - - @Test fun bindDevice() { player.attachPlayer(holder) val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index d86dfa5fa5f7..406f40c75735 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView import org.junit.Assert.assertNotNull @@ -73,6 +74,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle + @Mock + private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @Captor private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)> @JvmField @@ -90,7 +93,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { bypassController, mediaCarouselController, notificationLockscreenUserManager, - wakefulnessLifecycle) + wakefulnessLifecycle, + statusBarKeyguardViewManager) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN) setupHost(qsHost, MediaHierarchyManager.LOCATION_QS) @@ -98,7 +102,6 @@ class MediaHierarchyManagerTest : SysuiTestCase() { `when`(statusBarStateController.state).thenReturn(StatusBarState.SHADE) // We'll use the viewmanager to verify a few calls below, let's reset this. clearInvocations(mediaCarouselController) - } private fun setupHost(host: MediaHost, location: Int) { @@ -125,7 +128,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { observer.onStartedGoingToSleep() clearInvocations(mediaCarouselController) mediaHiearchyManager.qsExpansion = 0.0f - verify(mediaCarouselController, times(0)).onDesiredLocationChanged(ArgumentMatchers.anyInt(), + verify(mediaCarouselController, times(0)) + .onDesiredLocationChanged(ArgumentMatchers.anyInt(), any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java index cc322620eb57..0dd1f6816787 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java @@ -24,7 +24,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -59,6 +58,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.appwidget.IAppWidgetService; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.people.widget.PeopleSpaceWidgetManager; import com.android.systemui.people.widget.PeopleTileKey; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -73,6 +73,7 @@ import org.mockito.MockitoAnnotations; import java.util.List; import java.util.Map; +import java.util.Optional; @RunWith(AndroidTestingRunner.class) @SmallTest @@ -188,6 +189,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { private PackageManager mPackageManager; @Mock private NotificationEntryManager mNotificationEntryManager; + @Mock + private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; private Bundle mOptions; @@ -212,8 +215,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { when(resources.getConfiguration()).thenReturn(configuration); when(resources.getDisplayMetrics()).thenReturn(displayMetrics); when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); - when(mMockContentResolver.query(any(Uri.class), any(), anyString(), any(), - isNull())).thenReturn(mMockCursor); + when(mMockContentResolver.query(any(Uri.class), any(), any(), any(), + any())).thenReturn(mMockCursor); when(mMockContext.getString(R.string.birthday_status)).thenReturn( mContext.getString(R.string.birthday_status)); when(mMockContext.getString(R.string.basic_status)).thenReturn( @@ -236,7 +239,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { .build(); PeopleTileKey key = new PeopleTileKey(tile); PeopleSpaceTile actual = PeopleSpaceUtils - .augmentTileFromNotification(mContext, tile, key, mNotificationEntry1, 0); + .augmentTileFromNotification(mContext, tile, key, mNotificationEntry1, 0, + Optional.empty()); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2); assertThat(actual.getNotificationSender()).isEqualTo(null); @@ -275,7 +279,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { .build(); PeopleTileKey key = new PeopleTileKey(tile); PeopleSpaceTile actual = PeopleSpaceUtils - .augmentTileFromNotification(mContext, tile, key, notificationEntry, 0); + .augmentTileFromNotification(mContext, tile, key, notificationEntry, 0, + Optional.empty()); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2); assertThat(actual.getNotificationSender().toString()).isEqualTo("name"); @@ -291,7 +296,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { .build(); PeopleTileKey key = new PeopleTileKey(tile); PeopleSpaceTile actual = PeopleSpaceUtils - .augmentTileFromNotification(mContext, tile, key, mNotificationEntry3, 0); + .augmentTileFromNotification(mContext, tile, key, mNotificationEntry3, 0, + Optional.empty()); assertThat(actual.getNotificationContent()).isEqualTo(null); } @@ -308,10 +314,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT, new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson, mContext.getSystemService(LauncherApps.class)).build()); - PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager, + PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager, widgetIdToTile, widgetIdsArray); - verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + verify(mPeopleSpaceWidgetManager, never()).updateAppWidgetOptionsAndView( + eq(WIDGET_ID_WITH_SHORTCUT), any()); } @@ -328,10 +335,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson, mContext.getSystemService(LauncherApps.class)).setBirthdayText( mContext.getString(R.string.birthday_status)).build()); - PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager, + PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager, widgetIdToTile, widgetIdsArray); - verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView( + eq(WIDGET_ID_WITH_SHORTCUT), any()); } @@ -363,10 +371,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { new PeopleSpaceTile.Builder(mShortcutInfo, mContext.getSystemService(LauncherApps.class)).setBirthdayText( mContext.getString(R.string.birthday_status)).build()); - PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager, + PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager, widgetIdToTile, widgetIdsArray); - verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView( + eq(WIDGET_ID_WITH_SHORTCUT), any()); } @@ -375,6 +384,9 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT}; when(mMockCursor.moveToNext()).thenReturn(true, false, true, false); when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY); + when(mMockCursor.getInt(eq(TEST_COLUMN_INDEX + 1))).thenReturn(1); + when(mMockCursor.getColumnIndex(eq(ContactsContract.Contacts.STARRED))).thenReturn( + TEST_COLUMN_INDEX + 1); when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY) )).thenReturn(TEST_COLUMN_INDEX); @@ -383,10 +395,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { new PeopleSpaceTile.Builder(mShortcutInfo, mContext.getSystemService(LauncherApps.class)).setBirthdayText( mContext.getString(R.string.birthday_status)).build()); - PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager, + PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager, widgetIdToTile, widgetIdsArray); - verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView( + eq(WIDGET_ID_WITH_SHORTCUT), any()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java index 764cdee7e36d..228e5e8d481d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java @@ -21,13 +21,20 @@ import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY; import static android.app.people.ConversationStatus.ACTIVITY_GAME; import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY; import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE; +import static android.app.people.PeopleSpaceTile.BLOCK_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_CONTACTS; +import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_STARRED_CONTACTS; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH; +import static com.android.systemui.people.PeopleSpaceUtils.STARRED_CONTACT; +import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT; import static com.android.systemui.people.widget.AppWidgetOptionsHelper.OPTIONS_PEOPLE_TILE; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -53,6 +60,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.people.widget.PeopleTileKey; import org.junit.Before; import org.junit.Test; @@ -148,14 +156,14 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { TextView textView = mock(TextView.class); when(textView.getLineHeight()).thenReturn(16); when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null); - mPeopleTileViewHelper = new PeopleTileViewHelper(mContext, - PERSON_TILE, 0, mOptions); + mPeopleTileViewHelper = getPeopleTileViewHelper( + PERSON_TILE, mOptions); } @Test public void testCreateRemoteViewsWithLastInteractionTimeUnderOneDayHidden() { - RemoteViews views = new PeopleTileViewHelper(mContext, - PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + PERSON_TILE_WITHOUT_NOTIFICATION, mOptions).getViews(); View result = views.apply(mContext, null); // Not showing last interaction. @@ -165,8 +173,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + PERSON_TILE_WITHOUT_NOTIFICATION, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); // Not showing last interaction. @@ -178,8 +186,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { PeopleSpaceTile tileWithLastInteraction = PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setLastInteractionTimestamp( 123445L).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithLastInteraction, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithLastInteraction, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -197,8 +205,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithLastInteraction, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithLastInteraction, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show name over predefined icon. @@ -214,8 +222,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithLastInteraction, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithLastInteraction, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -240,8 +248,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { new ConversationStatus.Builder( PERSON_TILE_WITHOUT_NOTIFICATION.getId(), ACTIVITY_GAME).build())).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithAvailabilityAndNewStory, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithAvailabilityAndNewStory, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -257,8 +265,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithAvailabilityAndNewStory, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithAvailabilityAndNewStory, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show name rather than game type. @@ -274,8 +282,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithAvailabilityAndNewStory, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithAvailabilityAndNewStory, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -298,8 +306,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { NEW_STORY_WITH_AVAILABILITY, new ConversationStatus.Builder( PERSON_TILE_WITHOUT_NOTIFICATION.getId(), ACTIVITY_BIRTHDAY).build())).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -318,8 +326,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -336,8 +344,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -362,8 +370,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses( Arrays.asList(GAME_STATUS, NEW_STORY_WITH_AVAILABILITY)).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -381,8 +389,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -399,8 +407,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithStatusTemplate, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithStatusTemplate, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -420,14 +428,128 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { } @Test + public void testCreateRemoteViewsWithPackageSuspended() { + PeopleSpaceTile tile = PERSON_TILE.toBuilder() + .setIsPackageSuspended(true) + .build(); + RemoteViews views = getPeopleTileViewHelper( + tile, mOptions).getViews(); + View result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + } + + @Test + public void testCreateRemoteViewsWithUserQuieted() { + PeopleSpaceTile tile = PERSON_TILE.toBuilder() + .setIsUserQuieted(true) + .build(); + RemoteViews views = getPeopleTileViewHelper( + tile, mOptions).getViews(); + View result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + } + + @Test + public void testCreateRemoteViewsWithDndBlocking() { + PeopleSpaceTile tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(BLOCK_CONVERSATIONS) + .build(); + RemoteViews views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + View result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(BLOCK_CONVERSATIONS) + .setCanBypassDnd(true) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS) + .setIsImportantConversation(true) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_STARRED_CONTACTS) + .setContactAffinity(VALID_CONTACT) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_STARRED_CONTACTS) + .setContactAffinity(STARRED_CONTACT) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_CONTACTS) + .setContactAffinity(STARRED_CONTACT) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_CONTACTS) + .setContactAffinity(VALID_CONTACT) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + + tileWithDndBlocking = PERSON_TILE.toBuilder() + .setNotificationPolicyState(SHOW_CONTACTS) + .build(); + views = getPeopleTileViewHelper( + tileWithDndBlocking, mOptions).getViews(); + result = views.apply(mContext, null); + + assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout); + } + + @Test public void testCreateRemoteViewsWithMissedCallNotification() { PeopleSpaceTile tileWithMissedCallNotification = PERSON_TILE.toBuilder() .setNotificationDataUri(null) .setNotificationCategory(CATEGORY_MISSED_CALL) .setNotificationContent(MISSED_CALL) .build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithMissedCallNotification, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithMissedCallNotification, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -446,8 +568,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithMissedCallNotification, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithMissedCallNotification, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -463,8 +585,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithMissedCallNotification, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithMissedCallNotification, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -489,8 +611,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { .setNotificationDataUri(null) .setStatuses(Arrays.asList(GAME_STATUS, NEW_STORY_WITH_AVAILABILITY)).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -512,8 +634,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -531,8 +653,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -561,8 +683,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { .setNotificationDataUri(null) .setStatuses(Arrays.asList(GAME_STATUS, NEW_STORY_WITH_AVAILABILITY)).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -588,8 +710,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -607,8 +729,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -642,8 +764,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { .setStatuses(Arrays.asList(GAME_STATUS, NEW_STORY_WITH_AVAILABILITY)) .setMessagesCount(2).build(); - RemoteViews views = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews views = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View result = views.apply(mContext, null); TextView name = (TextView) result.findViewById(R.id.name); @@ -665,8 +787,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_medium) - 1); - RemoteViews smallView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews smallView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View smallResult = smallView.apply(mContext, null); // Show icon instead of name. @@ -684,8 +806,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_height_for_large)); - RemoteViews largeView = new PeopleTileViewHelper(mContext, - tileWithStatusAndNotification, 0, mOptions).getViews(); + RemoteViews largeView = getPeopleTileViewHelper( + tileWithStatusAndNotification, mOptions).getViews(); View largeResult = largeView.apply(mContext, null); name = (TextView) largeResult.findViewById(R.id.name); @@ -858,4 +980,9 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { return (int) (mContext.getResources().getDimension(dimenResourceId) / mContext.getResources().getDisplayMetrics().density); } + + private PeopleTileViewHelper getPeopleTileViewHelper(PeopleSpaceTile tile, Bundle options) { + return new PeopleTileViewHelper(mContext, tile, 0, options, + new PeopleTileKey(tile.getId(), 0, tile.getPackageName())); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java index 411fb02ba87a..f31f326c0c45 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java @@ -20,11 +20,32 @@ import static android.app.Notification.CATEGORY_MISSED_CALL; import static android.app.Notification.EXTRA_PEOPLE_LIST; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; +import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; +import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; +import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY; import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY; import static android.app.people.ConversationStatus.ACTIVITY_GAME; +import static android.app.people.PeopleSpaceTile.BLOCK_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_CONTACTS; +import static android.app.people.PeopleSpaceTile.SHOW_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS; +import static android.app.people.PeopleSpaceTile.SHOW_STARRED_CONTACTS; +import static android.content.Intent.ACTION_BOOT_COMPLETED; +import static android.content.Intent.ACTION_PACKAGES_SUSPENDED; import static android.content.PermissionChecker.PERMISSION_GRANTED; import static android.content.PermissionChecker.PERMISSION_HARD_DENIED; +import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE; import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING; import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID; @@ -73,6 +94,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.service.notification.ConversationChannelWrapper; import android.service.notification.StatusBarNotification; +import android.service.notification.ZenModeConfig; import android.testing.AndroidTestingRunner; import androidx.preference.PreferenceManager; @@ -89,6 +111,7 @@ import com.android.systemui.statusbar.notification.collection.NoManSimulator; import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; @@ -99,12 +122,14 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -158,6 +183,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { // Same contact uri. .setContactUri(URI) .build(); + private static final int ALL_SUPPRESSED_VISUAL_EFFECTS = SUPPRESSED_EFFECT_SCREEN_OFF + | SUPPRESSED_EFFECT_SCREEN_ON + | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT + | SUPPRESSED_EFFECT_AMBIENT + | SUPPRESSED_EFFECT_STATUS_BAR + | SUPPRESSED_EFFECT_BADGE + | SUPPRESSED_EFFECT_LIGHTS + | SUPPRESSED_EFFECT_PEEK + | SUPPRESSED_EFFECT_NOTIFICATION_LIST; + private ShortcutInfo mShortcutInfo; private NotificationEntry mNotificationEntry; @@ -182,9 +217,13 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { @Mock private PackageManager mPackageManager; @Mock - private INotificationManager mNotificationManager; + private INotificationManager mINotificationManager; @Mock private UserManager mUserManager; + @Mock + private NotificationManager mNotificationManager; + @Mock + private NotificationManager.Policy mNotificationPolicy; @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor; @@ -194,19 +233,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { private final NoManSimulator mNoMan = new NoManSimulator(); private final FakeSystemClock mClock = new FakeSystemClock(); - private PeopleSpaceWidgetProvider mProvider; + private final FakeExecutor mFakeExecutor = new FakeExecutor(mClock); @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mLauncherApps = mock(LauncherApps.class); mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager); - mManager = new PeopleSpaceWidgetManager(mContext); - mProvider = new PeopleSpaceWidgetProvider(); - mProvider.setPeopleSpaceWidgetManager(mManager); - mManager.setAppWidgetManager(mAppWidgetManager, mIPeopleManager, mPeopleManager, - mLauncherApps, mNotificationEntryManager, mPackageManager, true, mProvider, - mUserManager, mNotificationManager); + mManager = new PeopleSpaceWidgetManager(mContext, mAppWidgetManager, mIPeopleManager, + mPeopleManager, mLauncherApps, mNotificationEntryManager, mPackageManager, + mUserManager, mINotificationManager, mNotificationManager, mFakeExecutor); mManager.attach(mListenerService); verify(mListenerService).addNotificationHandler(mListenerCaptor.capture()); @@ -218,7 +254,19 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { addTileForWidget(PERSON_TILE_WITH_SAME_URI, WIDGET_ID_WITH_SAME_URI); when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT))) .thenReturn(new Bundle()); + when(mUserManager.isQuietModeEnabled(any())).thenReturn(false); + when(mPackageManager.isPackageSuspended(any())).thenReturn(false); + setFinalField("suppressedVisualEffects", ALL_SUPPRESSED_VISUAL_EFFECTS); + when(mNotificationPolicy.allowConversationsFrom()).thenReturn(CONVERSATION_SENDERS_ANYONE); + when(mNotificationPolicy.allowConversations()).thenReturn(false); + when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_ANYONE); + when(mNotificationPolicy.allowMessages()).thenReturn(false); + when(mNotificationManager.getNotificationPolicy()).thenReturn(mNotificationPolicy); + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_ALL); + int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT}; + when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray); when(mMockContext.getPackageName()).thenReturn(TEST_PACKAGE_A); when(mMockContext.getUserId()).thenReturn(0); @@ -242,7 +290,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( SHORTCUT_ID + 2, true, 1); - when(mNotificationManager.getConversations(anyBoolean())).thenReturn( + when(mINotificationManager.getConversations(anyBoolean())).thenReturn( new ParceledListSlice(Arrays.asList( newerNonImportantConversation, newerImportantConversation, olderImportantConversation))); @@ -280,7 +328,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( SHORTCUT_ID + 2, true, 1); - when(mNotificationManager.getConversations(anyBoolean())).thenReturn( + when(mINotificationManager.getConversations(anyBoolean())).thenReturn( new ParceledListSlice(Arrays.asList( newerNonImportantConversation, newerImportantConversation, olderImportantConversation))); @@ -306,7 +354,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( SHORTCUT_ID + 2, true, 1); - when(mNotificationManager.getConversations(anyBoolean())).thenReturn( + when(mINotificationManager.getConversations(anyBoolean())).thenReturn( new ParceledListSlice(Arrays.asList( newerNonImportantConversation, newerImportantConversation, olderImportantConversation))); @@ -1027,8 +1075,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners() throws Exception { addSecondWidgetForPersonTile(); - mProvider.onUpdate(mContext, mAppWidgetManager, - new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT}); + mManager.updateWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT}); // Delete only one widget for the conversation. mManager.deleteWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT}); @@ -1050,7 +1097,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS)); // Delete all widgets for the conversation. - mProvider.onDeleted(mContext, new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT}); + mManager.deleteWidgets(new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT}); // Check deleted storage. SharedPreferences secondWidgetSp = mContext.getSharedPreferences( @@ -1154,7 +1201,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A)); when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel); PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); - PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key); + PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT); assertThat(tile.getId()).isEqualTo(key.getShortcutId()); } @@ -1162,7 +1209,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { public void testGetPeopleTileFromPersistentStorageNoConversation() throws RemoteException { when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null); PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); - PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key); + PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT); assertThat(tile).isNull(); } @@ -1195,18 +1242,25 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { @Test public void testAugmentTileFromNotifications() { + clearStorage(); + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo(null); PeopleSpaceTile tile = new PeopleSpaceTile .Builder(SHORTCUT_ID, "userName", ICON, new Intent()) .setPackageName(TEST_PACKAGE_A) .setUserHandle(new UserHandle(0)) .build(); + PeopleTileKey key = new PeopleTileKey(tile); PeopleSpaceTile actual = mManager.augmentTileFromNotifications(tile, key, EMPTY_STRING, - Map.of(new PeopleTileKey(mNotificationEntry), - new HashSet<>(Collections.singleton(mNotificationEntry)))); + Map.of(new PeopleTileKey(mNotificationEntry), + new HashSet<>(Collections.singleton(mNotificationEntry))), + Optional.of(WIDGET_ID_WITH_SHORTCUT)); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1); + assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo( + URI.toString()); } @Test @@ -1221,7 +1275,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { PeopleSpaceTile actual = mManager .augmentTileFromNotifications(tile, key, EMPTY_STRING, Map.of(new PeopleTileKey(mNotificationEntry), - new HashSet<>(Collections.singleton(mNotificationEntry)))); + new HashSet<>(Collections.singleton(mNotificationEntry))), + Optional.empty()); assertThat(actual.getNotificationContent()).isEqualTo(null); } @@ -1238,7 +1293,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { .thenReturn(List.of(mNotificationEntry)); PeopleSpaceTile actual = - mManager.augmentTileFromNotificationEntryManager(tile); + mManager.augmentTileFromNotificationEntryManager(tile, + Optional.of(WIDGET_ID_WITH_SHORTCUT)); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1); @@ -1246,6 +1302,202 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { .getVisibleNotifications(); } + @Test + public void testUpdateWidgetsOnStateChange() { + mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + Bundle bundle = mBundleArgumentCaptor.getValue(); + PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.isPackageSuspended()).isFalse(); + assertThat(tile.isUserQuieted()).isFalse(); + assertThat(tile.canBypassDnd()).isFalse(); + assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS); + verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + any()); + } + + @Test + public void testUpdateWidgetsOnStateChangeWithUserQuieted() { + when(mUserManager.isQuietModeEnabled(any())).thenReturn(true); + + mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + Bundle bundle = mBundleArgumentCaptor.getValue(); + PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.isPackageSuspended()).isFalse(); + assertThat(tile.isUserQuieted()).isTrue(); + assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeWithPackageSuspended() throws Exception { + when(mPackageManager.isPackageSuspended(any())).thenReturn(true); + + mManager.updateWidgetsOnStateChange(ACTION_PACKAGES_SUSPENDED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + Bundle bundle = mBundleArgumentCaptor.getValue(); + PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.isPackageSuspended()).isTrue(); + assertThat(tile.isUserQuieted()).isFalse(); + assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeNotInDnd() { + int expected = 0; + mManager.updateWidgetsOnStateChange(NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllConversations() { + int expected = 0; + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_PRIORITY); + when(mNotificationPolicy.allowConversations()).thenReturn(true); + setFinalField("priorityConversationSenders", CONVERSATION_SENDERS_ANYONE); + + mManager.updateWidgetsOnStateChange(NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowOnlyImportantConversations() { + int expected = 0; + // Only allow important conversations. + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_PRIORITY); + when(mNotificationPolicy.allowConversations()).thenReturn(true); + setFinalField("priorityConversationSenders", CONVERSATION_SENDERS_IMPORTANT); + + mManager.updateWidgetsOnStateChange(NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo( + expected | SHOW_IMPORTANT_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowNoConversations() { + int expected = 0; + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_PRIORITY); + when(mNotificationPolicy.allowConversations()).thenReturn(false); + + mManager.updateWidgetsOnStateChange(NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | BLOCK_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowNoConversationsAllowContactMessages() { + int expected = 0; + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_PRIORITY); + when(mNotificationPolicy.allowConversations()).thenReturn(false); + when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_CONTACT); + when(mNotificationPolicy.allowMessages()).thenReturn(true); + + mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONTACTS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowNoConversationsAllowStarredContactMessages() { + int expected = 0; + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_PRIORITY); + when(mNotificationPolicy.allowConversations()).thenReturn(false); + when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_STAR); + when(mNotificationPolicy.allowMessages()).thenReturn(true); + + mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_STARRED_CONTACTS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowAlarmsOnly() { + int expected = 0; + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_ALARMS); + + mManager.updateWidgetsOnStateChange(NotificationManager + .ACTION_INTERRUPTION_FILTER_CHANGED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | BLOCK_CONVERSATIONS); + } + + @Test + public void testUpdateWidgetsOnStateChangeAllowVisualEffectsAndAllowAlarmsOnly() { + int expected = 0; + // If we show visuals, but just only make sounds for alarms, still show content in tiles. + when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn( + INTERRUPTION_FILTER_ALARMS); + setFinalField("suppressedVisualEffects", SUPPRESSED_EFFECT_FULL_SCREEN_INTENT + | SUPPRESSED_EFFECT_AMBIENT); + + mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED); + + verify(mAppWidgetManager, times(1)) + .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), + mBundleArgumentCaptor.capture()); + PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE); + assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS); + } + + private void setFinalField(String fieldName, int value) { + try { + Field field = NotificationManager.Policy.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(mNotificationPolicy, value); + } catch (Exception e) { + } + } + /** * Adds another widget for {@code PERSON_TILE} with widget ID: {@code * SECOND_WIDGET_ID_WITH_SHORTCUT}. diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 5d29f520e8a9..e85e19fbd9b8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -21,6 +21,8 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE; +import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME; import static android.view.View.GONE; import static android.view.View.VISIBLE; @@ -150,9 +152,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { private ShadeController mShadeController; @Mock private ConversationIconFactory mIconFactory; - @Mock(answer = Answers.RETURNS_SELF) - private PriorityOnboardingDialogController.Builder mBuilder; - private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider = () -> mBuilder; @Mock private Notification.BubbleMetadata mBubbleMetadata; private Handler mTestHandler; @@ -236,8 +235,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { when(mMockINotificationManager.getConsolidatedNotificationPolicy()) .thenReturn(mock(NotificationManager.Policy.class)); - when(mBuilder.build()).thenReturn(mock(PriorityOnboardingDialogController.class)); - when(mPeopleSpaceWidgetManager.requestPinAppWidget(any(), any())).thenReturn(true); } @@ -258,7 +255,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -285,7 +281,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -340,7 +335,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -368,7 +362,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -395,7 +388,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -433,7 +425,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -464,7 +455,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -493,7 +483,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -523,7 +512,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, false, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -551,7 +539,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -582,7 +569,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -616,7 +602,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -626,6 +611,110 @@ public class NotificationConversationInfoTest extends SysuiTestCase { assertThat(((TextView) view.findViewById(R.id.default_summary)).getText()).isEqualTo( mContext.getString(R.string.notification_channel_summary_default_with_bubbles, "App Name")); + assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText()) + .isEqualTo(mContext.getString( + R.string.notification_channel_summary_priority_bubble)); + } + + @Test + public void testBindNotification_priorityDnd() throws Exception { + NotificationManager.Policy policy = new NotificationManager.Policy( + PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE); + when(mMockINotificationManager.getConsolidatedNotificationPolicy()) + .thenReturn(policy); + when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); + mConversationChannel.setImportance(IMPORTANCE_HIGH); + mConversationChannel.setImportantConversation(false); + mConversationChannel.setAllowBubbles(false); + mNotificationInfo.bindNotification( + -1, + mShortcutManager, + mMockPackageManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + null, + null, + null, + mIconFactory, + mContext, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager), + mShadeController); + assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText()) + .isEqualTo(mContext.getString( + R.string.notification_channel_summary_priority_dnd)); + } + + @Test + public void testBindNotification_priorityBaseline() throws Exception { + when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); + mConversationChannel.setImportance(IMPORTANCE_HIGH); + mConversationChannel.setImportantConversation(false); + mConversationChannel.setAllowBubbles(false); + mNotificationInfo.bindNotification( + -1, + mShortcutManager, + mMockPackageManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + null, + null, + null, + mIconFactory, + mContext, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager), + mShadeController); + assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText()) + .isEqualTo(mContext.getString( + R.string.notification_channel_summary_priority_baseline)); + } + + @Test + public void testBindNotification_priorityDndAndBubble() throws Exception { + NotificationManager.Policy policy = new NotificationManager.Policy( + PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE); + when(mMockINotificationManager.getConsolidatedNotificationPolicy()) + .thenReturn(policy); + + when(mMockINotificationManager.getBubblePreferenceForPackage(anyString(), anyInt())) + .thenReturn(BUBBLE_PREFERENCE_ALL); + when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); + mConversationChannel.setImportance(IMPORTANCE_HIGH); + mConversationChannel.setImportantConversation(false); + mConversationChannel.setAllowBubbles(true); + mNotificationInfo.bindNotification( + -1, + mShortcutManager, + mMockPackageManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + mBubbleMetadata, + null, + null, + mIconFactory, + mContext, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager), + mShadeController); + assertThat(((TextView) mNotificationInfo.findViewById(R.id.priority_summary)).getText()) + .isEqualTo(mContext.getString( + R.string.notification_channel_summary_priority_all)); } @Test @@ -649,7 +738,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -696,7 +784,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -742,7 +829,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -789,7 +875,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -829,7 +914,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -868,7 +952,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -911,7 +994,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -944,7 +1026,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -976,7 +1057,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1015,7 +1095,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1054,7 +1133,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1092,7 +1170,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1129,7 +1206,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1157,7 +1233,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1168,97 +1243,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase { } @Test - public void testSelectPriorityPresentsOnboarding_firstTime() { - // GIVEN pref is false - Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, false); - - // GIVEN the priority onboarding screen is present - PriorityOnboardingDialogController.Builder b = - mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF); - PriorityOnboardingDialogController controller = - mock(PriorityOnboardingDialogController.class); - when(b.build()).thenReturn(controller); - - // GIVEN the user is changing conversation settings - mNotificationInfo.bindNotification( - -1, - mShortcutManager, - mMockPackageManager, - mPeopleSpaceWidgetManager, - mMockINotificationManager, - mOnUserInteractionCallback, - TEST_PACKAGE_NAME, - mNotificationChannel, - mEntry, - mBubbleMetadata, - null, - null, - mIconFactory, - mContext, - () -> b, - true, - mTestHandler, - mTestHandler, null, Optional.of(mBubblesManager), - mShadeController); - - // WHEN user clicks "priority" - mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE); - verify(controller, never()).show(); - - // and then done - mNotificationInfo.findViewById(R.id.done).performClick(); - - // THEN the user is presented with the priority onboarding screen - verify(controller, atLeastOnce()).show(); - } - - @Test - public void testSelectPriorityDoesNotShowOnboarding_secondTime() { - //WHEN pref is true - Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true); - - PriorityOnboardingDialogController.Builder b = - mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF); - PriorityOnboardingDialogController controller = - mock(PriorityOnboardingDialogController.class); - when(b.build()).thenReturn(controller); - - mNotificationInfo.bindNotification( - -1, - mShortcutManager, - mMockPackageManager, - mPeopleSpaceWidgetManager, - mMockINotificationManager, - mOnUserInteractionCallback, - TEST_PACKAGE_NAME, - mNotificationChannel, - mEntry, - mBubbleMetadata, - null, - null, - mIconFactory, - mContext, - () -> b, - true, - mTestHandler, - mTestHandler, null, Optional.of(mBubblesManager), - mShadeController); - - // WHEN user clicks "priority" - mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE); - verify(controller, never()).show(); - - // and then done - mNotificationInfo.findViewById(R.id.done).performClick(); - - // THEN the user is presented with the priority onboarding screen - verify(controller, never()).show(); - } - - @Test public void testSelectPriorityRequestsPinPeopleTile() { - //WHEN pref is true and channel is default importance - Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true); + //WHEN channel is default importance mNotificationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( -1, @@ -1275,7 +1261,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1293,9 +1278,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testSelectDefaultDoesNotRequestPinPeopleTile() { - //WHEN pref is true - Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true); - mNotificationInfo.bindNotification( -1, mShortcutManager, @@ -1311,7 +1293,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), @@ -1329,8 +1310,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testSelectPriority_AlreadyPriority_DoesNotRequestPinPeopleTile() { - //WHEN pref is true and channel is priority - Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING_IN_S, true); mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH); mConversationChannel.setImportance(IMPORTANCE_HIGH); mConversationChannel.setImportantConversation(true); @@ -1350,7 +1329,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase { null, mIconFactory, mContext, - mBuilderProvider, true, mTestHandler, mTestHandler, null, Optional.of(mBubblesManager), 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 bfce2a568c78..9f537f5b6afc 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 @@ -139,9 +139,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase { @Mock private BubblesManager mBubblesManager; @Mock private ShadeController mShadeController; @Mock private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; - @Mock(answer = Answers.RETURNS_SELF) - private PriorityOnboardingDialogController.Builder mBuilder; - private Provider<PriorityOnboardingDialogController.Builder> mProvider = () -> mBuilder; @Mock private AssistantFeedbackController mAssistantFeedbackController; @Before @@ -163,7 +160,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider, mINotificationManager, mNotificationEntryManager, mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker, - mProvider, mAssistantFeedbackController, Optional.of(mBubblesManager), + mAssistantFeedbackController, Optional.of(mBubblesManager), new UiEventLoggerFake(), mOnUserInteractionCallback, mShadeController); mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer, mCheckSaveListener, mOnSettingsClickListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java index a01e0b1c3e3a..f485b465e486 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java @@ -38,7 +38,6 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; @@ -57,7 +56,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private StatusBarStateController mStatusBarStateController; private OngoingCallController mOngoingCallController; private SystemStatusAnimationScheduler mAnimationScheduler; - private PrivacyDotViewController mDotViewController; + private StatusBarLocationPublisher mLocationPublisher; public CollapsedStatusBarFragmentTest() { super(CollapsedStatusBarFragment.class); @@ -224,12 +223,12 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { protected Fragment instantiate(Context context, String className, Bundle arguments) { mOngoingCallController = mock(OngoingCallController.class); mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); - mDotViewController = mock(PrivacyDotViewController.class); + mLocationPublisher = mock(StatusBarLocationPublisher.class); setUpNotificationIconAreaController(); return new CollapsedStatusBarFragment( mOngoingCallController, mAnimationScheduler, - mDotViewController, + mLocationPublisher, mMockNotificationAreaController); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index b6eb4923ee4a..f98f00cd9187 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -20,6 +20,7 @@ import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE; import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT; import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; @@ -165,7 +166,7 @@ public class ScrimControllerTest extends SysuiTestCase { endAnimation(mScrimInFront); endAnimation(mScrimForBubble); - Assert.assertEquals("Animators did not finish", + assertEquals("Animators did not finish", mAnimatorListener.getNumStarts(), mAnimatorListener.getNumEnds()); } @@ -422,7 +423,7 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.AOD); finishAnimationsImmediately(); mScrimController.setAodFrontScrimAlpha(0.3f); - Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f); + assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f); Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f); } @@ -601,13 +602,13 @@ public class ScrimControllerTest extends SysuiTestCase { )); // Front scrim should be transparent - Assert.assertEquals(ScrimController.TRANSPARENT, + assertEquals(ScrimController.TRANSPARENT, mScrimInFront.getViewAlpha(), 0.0f); // Back scrim should be visible - Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA, + assertEquals(ScrimController.BUSY_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.0f); // Bubble scrim should be visible - Assert.assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA, + assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA, mScrimForBubble.getViewAlpha(), 0.0f); } @@ -615,15 +616,15 @@ public class ScrimControllerTest extends SysuiTestCase { public void scrimStateCallback() { mScrimController.transitionTo(ScrimState.UNLOCKED); finishAnimationsImmediately(); - Assert.assertEquals(mScrimState, ScrimState.UNLOCKED); + assertEquals(mScrimState, ScrimState.UNLOCKED); mScrimController.transitionTo(ScrimState.BOUNCER); finishAnimationsImmediately(); - Assert.assertEquals(mScrimState, ScrimState.BOUNCER); + assertEquals(mScrimState, ScrimState.BOUNCER); mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED); finishAnimationsImmediately(); - Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED); + assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED); } @Test @@ -638,13 +639,13 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setPanelExpansion(1.0f); finishAnimationsImmediately(); - Assert.assertEquals("Scrim alpha should change after setPanelExpansion", + assertEquals("Scrim alpha should change after setPanelExpansion", mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f); mScrimController.setPanelExpansion(0f); finishAnimationsImmediately(); - Assert.assertEquals("Scrim alpha should change after setPanelExpansion", + assertEquals("Scrim alpha should change after setPanelExpansion", mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f); } @@ -698,7 +699,7 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setExpansionAffectsAlpha(false); mScrimController.setPanelExpansion(0.8f); verifyZeroInteractions(mScrimBehind); - Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha " + assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha " + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f); mScrimController.setExpansionAffectsAlpha(true); @@ -801,9 +802,9 @@ public class ScrimControllerTest extends SysuiTestCase { } }); finishAnimationsImmediately(); - Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]); - Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]); - Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]); + assertEquals("onStart called in wrong order", 1, callOrder[0]); + assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]); + assertEquals("onFinished called in wrong order", 3, callOrder[2]); } @Test @@ -911,7 +912,7 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.UNLOCKED); finishAnimationsImmediately(); - Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back", + assertEquals("Scrim expansion opacity wasn't conserved when transitioning back", expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f); } @@ -981,7 +982,7 @@ public class ScrimControllerTest extends SysuiTestCase { } mScrimController.transitionTo(state); finishAnimationsImmediately(); - Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state, + assertEquals("Should be clickable unless AOD or PULSING, was: " + state, mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state), mScrimBehind.isClickable()); } @@ -1035,9 +1036,9 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setQsPosition(0, 300); finishAnimationsImmediately(); - Assert.assertEquals("Behind scrim should be opaque", + assertEquals("Behind scrim should be opaque", mScrimBehind.getViewAlpha(), 1, 0.0); - Assert.assertEquals("Notifications scrim should be opaque", + assertEquals("Notifications scrim should be opaque", mNotificationsScrim.getViewAlpha(), 1, 0.0); } @@ -1093,6 +1094,40 @@ public class ScrimControllerTest extends SysuiTestCase { mNotificationsScrim, TRANSPARENT)); } + @Test + public void testNotificationScrimVisible_afterOpeningShadeFromLockscreen() { + mScrimController.setPanelExpansion(1); + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); + finishAnimationsImmediately(); + + assertScrimAlpha(Map.of( + mScrimBehind, OPAQUE, + mNotificationsScrim, OPAQUE)); + } + + @Test + public void testNotificationTransparency_followsPanelExpansionInShadeLockedState() { + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); + + assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.8f); + assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.2f); + } + + @Test + public void testNotificationTransparency_inKeyguardState() { + mScrimController.transitionTo(ScrimState.KEYGUARD); + + assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.8f); + assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f); + } + + private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) { + mScrimController.setPanelExpansion(expansion); + finishAnimationsImmediately(); + // alpha is not changing linearly thus 0.2 of leeway when asserting + assertEquals(expectedAlpha, mNotificationsScrim.getViewAlpha(), 0.2); + } + private void assertScrimTinted(Map<ScrimView, Boolean> scrimToTint) { scrimToTint.forEach((scrim, hasTint) -> assertScrimTint(scrim, hasTint)); } @@ -1101,7 +1136,7 @@ public class ScrimControllerTest extends SysuiTestCase { String message = "Tint test failed at state " + mScrimController.getState() + " with scrim: " + getScrimName(scrim) + " and tint: " + Integer.toHexString(scrim.getTint()); - Assert.assertEquals(message, hasTint, scrim.getTint() != Color.TRANSPARENT); + assertEquals(message, hasTint, scrim.getTint() != Color.TRANSPARENT); } private String getScrimName(ScrimView scrim) { @@ -1146,13 +1181,13 @@ public class ScrimControllerTest extends SysuiTestCase { } else { visibility = TRANSPARENT; } - Assert.assertEquals("Invalid visibility.", + assertEquals("Invalid visibility.", visibility /* expected */, mScrimVisibility); } private void assertScrimAlpha(ScrimView scrim, int expectedAlpha) { - Assert.assertEquals("Unexpected " + getScrimName(scrim) + " scrim alpha: " + assertEquals("Unexpected " + getScrimName(scrim) + " scrim alpha: " + scrim.getViewAlpha(), expectedAlpha != TRANSPARENT /* expected */, scrim.getViewAlpha() > TRANSPARENT /* actual */); 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 545e2e08ec07..b2487e8e2444 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 @@ -115,7 +115,6 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.charging.WiredChargingRippleController; -import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryListener; @@ -267,7 +266,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private WiredChargingRippleController mWiredChargingRippleController; @Mock private OngoingCallController mOngoingCallController; @Mock private SystemStatusAnimationScheduler mAnimationScheduler; - @Mock private PrivacyDotViewController mDotViewController; + @Mock private StatusBarLocationPublisher mLocationPublisher; @Mock private FeatureFlags mFeatureFlags; @Mock private IWallpaperManager mWallpaperManager; @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @@ -437,7 +436,7 @@ public class StatusBarTest extends SysuiTestCase { mWiredChargingRippleController, mOngoingCallController, mAnimationScheduler, - mDotViewController, + mLocationPublisher, mFeatureFlags, mKeyguardUnlockAnimationController); when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class), diff --git a/services/Android.bp b/services/Android.bp index 2281a159f6f7..1dd219264575 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -190,13 +190,13 @@ droidstubs { defaults: ["services-stubs-default"], check_api: { current: { - api_file: "api/non-updatable-current.txt", - removed_api_file: "api/non-updatable-removed.txt", + api_file: "api/current.txt", + removed_api_file: "api/removed.txt", }, api_lint: { enabled: true, new_since: ":android-non-updatable.api.system-server.latest", - baseline_file: "api/non-updatable-lint-baseline.txt", + baseline_file: "api/lint-baseline.txt", }, }, dists: [ diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 61de53a2a483..7403af7605bc 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -16,6 +16,9 @@ package com.android.server.accessibility; +import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; +import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; + import android.annotation.MainThread; import android.content.Context; import android.graphics.Region; @@ -557,12 +560,16 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo MagnificationGestureHandler magnificationGestureHandler; if (mAms.getMagnificationMode(displayId) == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { - magnificationGestureHandler = new WindowMagnificationGestureHandler(displayContext, + final Context uiContext = displayContext.createWindowContext( + TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */); + magnificationGestureHandler = new WindowMagnificationGestureHandler(uiContext, mAms.getWindowMagnificationMgr(), mAms.getMagnificationController(), detectControlGestures, triggerable, displayId); } else { - magnificationGestureHandler = new FullScreenMagnificationGestureHandler(displayContext, + final Context uiContext = displayContext.createWindowContext( + TYPE_MAGNIFICATION_OVERLAY, null /* options */); + magnificationGestureHandler = new FullScreenMagnificationGestureHandler(uiContext, mAms.getFullScreenMagnificationController(), mAms.getMagnificationController(), detectControlGestures, triggerable, new WindowMagnificationPromptController(displayContext, mUserId), displayId); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java index 2434e2ca0b54..f7d1b9a311ba 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java @@ -34,6 +34,7 @@ import static java.util.Arrays.copyOfRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UiContext; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -139,7 +140,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH private PointerCoords[] mTempPointerCoords; private PointerProperties[] mTempPointerProperties; - public FullScreenMagnificationGestureHandler(Context context, + public FullScreenMagnificationGestureHandler(@UiContext Context context, FullScreenMagnificationController fullScreenMagnificationController, Callback callback, boolean detectTripleTap, diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java index 07f22dcb2c95..c5495d98226e 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java @@ -19,6 +19,7 @@ package com.android.server.accessibility.magnification; import static java.lang.Math.abs; import android.annotation.NonNull; +import android.annotation.UiContext; import android.content.Context; import android.os.Handler; import android.util.Log; @@ -63,8 +64,8 @@ class PanningScalingHandler extends private boolean mScaling; private boolean mEnable; - PanningScalingHandler(Context context, float maxScale, float minScale, boolean blockScroll, - @NonNull MagnificationDelegate magnificationDelegate) { + PanningScalingHandler(@UiContext Context context, float maxScale, float minScale, + boolean blockScroll, @NonNull MagnificationDelegate magnificationDelegate) { mDisplayId = context.getDisplayId(); mMaxScale = maxScale; mMinScale = minScale; diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java index fa3406217fa8..4fb9a03b8ac1 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java @@ -24,6 +24,7 @@ import static java.util.Arrays.asList; import static java.util.Arrays.copyOfRange; import android.annotation.Nullable; +import android.annotation.UiContext; import android.content.Context; import android.graphics.Point; import android.provider.Settings; @@ -86,7 +87,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl private final Context mContext; private final Point mTempPoint = new Point(); - public WindowMagnificationGestureHandler(Context context, + public WindowMagnificationGestureHandler(@UiContext Context context, WindowMagnificationManager windowMagnificationMgr, Callback callback, boolean detectTripleTap, boolean detectShortcutTrigger, int displayId) { @@ -342,7 +343,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl */ private final boolean mDetectTripleTap; - DetectingState(Context context, boolean detectTripleTap) { + DetectingState(@UiContext Context context, boolean detectTripleTap) { mDetectTripleTap = detectTripleTap; final MultiTap multiTap = new MultiTap(context, mDetectTripleTap ? 3 : 1, mDetectTripleTap diff --git a/services/api/Android.bp b/services/api/Android.bp index bbc8c72b2eef..ee7d49fc99c8 100644 --- a/services/api/Android.bp +++ b/services/api/Android.bp @@ -24,12 +24,12 @@ package { filegroup { name: "non-updatable-system-server-current.txt", - srcs: ["non-updatable-current.txt"], + srcs: ["current.txt"], visibility: ["//frameworks/base/api"], } filegroup { name: "non-updatable-system-server-removed.txt", - srcs: ["non-updatable-removed.txt"], + srcs: ["removed.txt"], visibility: ["//frameworks/base/api"], } diff --git a/services/api/current.txt b/services/api/current.txt index a0b1e3349e77..475dcf5eb20e 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -1,57 +1,4 @@ // Signature format: 2.0 -package com.android.permission.persistence { - - public interface RuntimePermissionsPersistence { - method @NonNull public static com.android.permission.persistence.RuntimePermissionsPersistence createInstance(); - method public void deleteForUser(@NonNull android.os.UserHandle); - method @Nullable public com.android.permission.persistence.RuntimePermissionsState readForUser(@NonNull android.os.UserHandle); - method public void writeForUser(@NonNull com.android.permission.persistence.RuntimePermissionsState, @NonNull android.os.UserHandle); - } - - public final class RuntimePermissionsState { - ctor public RuntimePermissionsState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>); - method @Nullable public String getFingerprint(); - method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getPackagePermissions(); - method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getSharedUserPermissions(); - method public int getVersion(); - field public static final int NO_VERSION = -1; // 0xffffffff - } - - public static final class RuntimePermissionsState.PermissionState { - ctor public RuntimePermissionsState.PermissionState(@NonNull String, boolean, int); - method public int getFlags(); - method @NonNull public String getName(); - method public boolean isGranted(); - } - -} - -package com.android.role { - - public interface RoleManagerLocal { - method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRolesAndHolders(int); - } - -} - -package com.android.role.persistence { - - public interface RolesPersistence { - method @NonNull public static com.android.role.persistence.RolesPersistence createInstance(); - method public void deleteForUser(@NonNull android.os.UserHandle); - method @Nullable public com.android.role.persistence.RolesState readForUser(@NonNull android.os.UserHandle); - method public void writeForUser(@NonNull com.android.role.persistence.RolesState, @NonNull android.os.UserHandle); - } - - public final class RolesState { - ctor public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>); - method @Nullable public String getPackagesHash(); - method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRoles(); - method public int getVersion(); - } - -} - package com.android.server { public final class LocalManagerRegistry { diff --git a/services/api/lint-baseline.txt b/services/api/lint-baseline.txt index e985ddb5352b..b46d21edd44c 100644 --- a/services/api/lint-baseline.txt +++ b/services/api/lint-baseline.txt @@ -1,4 +1,8 @@ // Baseline format: 1.0 +NotCloseable: com.android.server.wifi.SupplicantManager: + Classes that release resources (stop()) should implement AutoClosable and CloseGuard: class com.android.server.wifi.SupplicantManager + + ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder): Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder)} ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder, boolean): diff --git a/services/api/non-updatable-current.txt b/services/api/non-updatable-current.txt deleted file mode 100644 index 475dcf5eb20e..000000000000 --- a/services/api/non-updatable-current.txt +++ /dev/null @@ -1,71 +0,0 @@ -// Signature format: 2.0 -package com.android.server { - - public final class LocalManagerRegistry { - method public static <T> void addManager(@NonNull Class<T>, @NonNull T); - method @Nullable public static <T> T getManager(@NonNull Class<T>); - } - - public abstract class SystemService { - ctor public SystemService(@NonNull android.content.Context); - method @NonNull public final android.content.Context getContext(); - method public boolean isUserSupported(@NonNull com.android.server.SystemService.TargetUser); - method public void onBootPhase(int); - method public abstract void onStart(); - method public void onUserStarting(@NonNull com.android.server.SystemService.TargetUser); - method public void onUserStopped(@NonNull com.android.server.SystemService.TargetUser); - method public void onUserStopping(@NonNull com.android.server.SystemService.TargetUser); - method public void onUserSwitching(@Nullable com.android.server.SystemService.TargetUser, @NonNull com.android.server.SystemService.TargetUser); - method public void onUserUnlocked(@NonNull com.android.server.SystemService.TargetUser); - method public void onUserUnlocking(@NonNull com.android.server.SystemService.TargetUser); - method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder); - method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder, boolean); - field public static final int PHASE_ACTIVITY_MANAGER_READY = 550; // 0x226 - field public static final int PHASE_BOOT_COMPLETED = 1000; // 0x3e8 - field public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520; // 0x208 - field public static final int PHASE_LOCK_SETTINGS_READY = 480; // 0x1e0 - field public static final int PHASE_SYSTEM_SERVICES_READY = 500; // 0x1f4 - field public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600; // 0x258 - field public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // 0x64 - } - - public static final class SystemService.TargetUser { - method @NonNull public android.os.UserHandle getUserHandle(); - } - -} - -package com.android.server.am { - - public interface ActivityManagerLocal { - method public boolean canStartForegroundService(int, int, @NonNull String); - } - -} - -package com.android.server.role { - - public interface RoleServicePlatformHelper { - method @NonNull public String computePackageStateHash(int); - method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getLegacyRoleState(int); - } - -} - -package com.android.server.stats { - - public final class StatsHelper { - method public static void sendStatsdReadyBroadcast(@NonNull android.content.Context); - } - -} - -package com.android.server.wifi { - - public class SupplicantManager { - method public static void start(); - method public static void stop(); - } - -} - diff --git a/services/api/non-updatable-lint-baseline.txt b/services/api/non-updatable-lint-baseline.txt deleted file mode 100644 index b46d21edd44c..000000000000 --- a/services/api/non-updatable-lint-baseline.txt +++ /dev/null @@ -1,9 +0,0 @@ -// Baseline format: 1.0 -NotCloseable: com.android.server.wifi.SupplicantManager: - Classes that release resources (stop()) should implement AutoClosable and CloseGuard: class com.android.server.wifi.SupplicantManager - - -ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder): - Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder)} -ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder, boolean): - Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder,boolean)} diff --git a/services/api/non-updatable-removed.txt b/services/api/non-updatable-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/services/api/non-updatable-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 816c50dde2a8..76a6c0eecd3e 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -1133,7 +1133,7 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP * @param handler to use for postponed calculations. */ public abstract void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int optional, @Checksum.Type int required, + @Checksum.TypeMask int optional, @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler); diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java index 906702866889..047aae772f44 100644 --- a/services/core/java/com/android/server/IntentResolver.java +++ b/services/core/java/com/android/server/IntentResolver.java @@ -839,33 +839,45 @@ public abstract class IntentResolver<F, R extends Object> { } }; + // Method to take the snapshot of an F. + protected F snapshot(F f) { + return f; + } + // Helper method to copy some of the maps. - private static <E> void copyInto(ArrayMap<String, E[]> l, ArrayMap<String, E[]> r) { + protected void copyInto(ArrayMap<String, F[]> l, ArrayMap<String, F[]> r) { final int end = r.size(); + l.clear(); l.ensureCapacity(end); for (int i = 0; i < end; i++) { - final E[] val = r.valueAt(i); + final F[] val = r.valueAt(i); final String key = r.keyAt(i); - l.put(key, Arrays.copyOf(val, val.length)); + final F[] newval = Arrays.copyOf(val, val.length); + for (int j = 0; j < newval.length; j++) { + newval[j] = snapshot(newval[j]); + } + l.put(key, newval); + } + } + + protected void copyInto(ArraySet<F> l, ArraySet<F> r) { + l.clear(); + final int end = r.size(); + l.ensureCapacity(end); + for (int i = 0; i < end; i++) { + l.append(snapshot(r.valueAt(i))); } } // Make <this> a copy of <orig>. The presumption is that <this> is empty but all // arrays are cleared out explicitly, just to be sure. protected void copyFrom(IntentResolver orig) { - mFilters.clear(); - mFilters.addAll(orig.mFilters); - mTypeToFilter.clear(); + copyInto(mFilters, orig.mFilters); copyInto(mTypeToFilter, orig.mTypeToFilter); - mBaseTypeToFilter.clear(); copyInto(mBaseTypeToFilter, orig.mBaseTypeToFilter); - mWildTypeToFilter.clear(); copyInto(mWildTypeToFilter, orig.mWildTypeToFilter); - mSchemeToFilter.clear(); copyInto(mSchemeToFilter, orig.mSchemeToFilter); - mActionToFilter.clear(); copyInto(mActionToFilter, orig.mActionToFilter); - mTypedActionToFilter.clear(); copyInto(mTypedActionToFilter, orig.mTypedActionToFilter); } diff --git a/services/core/java/com/android/server/WatchedIntentResolver.java b/services/core/java/com/android/server/WatchedIntentResolver.java index e514f3c6fd59..0831c36d2bf6 100644 --- a/services/core/java/com/android/server/WatchedIntentResolver.java +++ b/services/core/java/com/android/server/WatchedIntentResolver.java @@ -19,10 +19,13 @@ package com.android.server; import android.annotation.NonNull; import android.annotation.Nullable; +import com.android.server.pm.WatchedIntentFilter; +import com.android.server.utils.Snappable; import com.android.server.utils.Watchable; import com.android.server.utils.WatchableImpl; import com.android.server.utils.Watcher; +import java.util.ArrayList; import java.util.List; /** @@ -31,9 +34,9 @@ import java.util.List; * @param <R> The resolver type. * {@hide} */ -public abstract class WatchedIntentResolver<F, R extends Object> +public abstract class WatchedIntentResolver<F extends Watchable, R extends Object> extends IntentResolver<F, R> - implements Watchable { + implements Watchable, Snappable { /** * Watchable machinery @@ -78,6 +81,13 @@ public abstract class WatchedIntentResolver<F, R extends Object> mWatchable.dispatchChange(what); } + private final Watcher mWatcher = new Watcher() { + @Override + public void onChange(@Nullable Watchable what) { + dispatchChange(what); + } + }; + /** * Notify listeners that this object has changed. */ @@ -88,17 +98,20 @@ public abstract class WatchedIntentResolver<F, R extends Object> @Override public void addFilter(F f) { super.addFilter(f); + f.registerObserver(mWatcher); onChanged(); } @Override public void removeFilter(F f) { + f.unregisterObserver(mWatcher); super.removeFilter(f); onChanged(); } @Override protected void removeFilterInternal(F f) { + f.unregisterObserver(mWatcher); super.removeFilterInternal(f); onChanged(); } @@ -109,4 +122,17 @@ public abstract class WatchedIntentResolver<F, R extends Object> super.sortResults(results); onChanged(); } + + /** + * @see IntentResolver#findFilters(IntentFilter) + */ + public ArrayList<F> findFilters(WatchedIntentFilter matching) { + return super.findFilters(matching.getIntentFilter()); + } + + // Make <this> a copy of <orig>. The presumption is that <this> is empty but all + // arrays are cleared out explicitly, just to be sure. + protected void copyFrom(WatchedIntentResolver orig) { + super.copyFrom(orig); + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9aedf1504df5..d526ebc8e581 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -14831,7 +14831,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new IllegalArgumentException("null fd"); } - synchronized (mProcLock) { + synchronized (this) { ProcessRecord proc = findProcessLOSP(process, userId, "dumpHeap"); IApplicationThread thread; if (proc == null || (thread = proc.getThread()) == null) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 6765ad02efa9..cc98abfc17f2 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -135,6 +135,7 @@ import com.android.server.pm.dex.DexManager; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.WindowManagerService; +import com.android.server.wm.WindowProcessController; import dalvik.system.VMRuntime; @@ -4626,6 +4627,7 @@ public final class ProcessList { @GuardedBy(anyOf = {"mService", "mProcLock"}) void updateApplicationInfoLOSP(List<String> packagesToUpdate, int userId, boolean updateFrameworkRes) { + final ArrayList<WindowProcessController> targetProcesses = new ArrayList<>(); for (int i = mLruProcesses.size() - 1; i >= 0; i--) { final ProcessRecord app = mLruProcesses.get(i); if (app.getThread() == null) { @@ -4646,6 +4648,7 @@ public final class ProcessList { if (ai.packageName.equals(app.info.packageName)) { app.info = ai; } + targetProcesses.add(app.getWindowProcessController()); } } catch (RemoteException e) { Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s", @@ -4654,6 +4657,9 @@ public final class ProcessList { } }); } + + mService.mActivityTaskManager.updateAssetConfiguration( + updateFrameworkRes ? null : targetProcesses); } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index b7ef10a5d45d..d2c6c6c620dd 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -56,6 +56,7 @@ import android.os.ShellCallback; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.KeyValueListParser; import android.util.Slog; @@ -180,9 +181,14 @@ public final class GameManagerService extends IGameManagerService.Stub { break; } case POPULATE_GAME_MODE_SETTINGS: { + // Scan all game packages and re-enforce the configured compat mode overrides + // as the DeviceConfig may have be wiped/since last reboot and we can't risk + // having overrides configured for packages that no longer have any DeviceConfig + // and thus any way to escape compat mode. removeMessages(POPULATE_GAME_MODE_SETTINGS, msg.obj); - loadDeviceConfigLocked(); - break; + final int userId = (int) msg.obj; + final String[] packageNames = getInstalledGamePackageNames(userId); + updateConfigsForUser(userId, packageNames); } } } @@ -198,28 +204,8 @@ public final class GameManagerService extends IGameManagerService.Stub { @Override public void onPropertiesChanged(Properties properties) { - synchronized (mDeviceConfigLock) { - for (final String packageName : properties.getKeyset()) { - try { - // Check if the package is installed before caching it. - mPackageManager.getPackageInfo(packageName, 0); - final GamePackageConfiguration config = - GamePackageConfiguration.fromProperties(packageName, properties); - if (config.isValid()) { - putConfig(config); - } else { - // This means that we received a bad config, or the config was deleted. - Slog.i(TAG, "Removing config for: " + packageName); - mConfigs.remove(packageName); - disableCompatScale(packageName); - } - } catch (PackageManager.NameNotFoundException e) { - if (DEBUG) { - Slog.v(TAG, "Package name not found", e); - } - } - } - } + final String[] packageNames = properties.getKeyset().toArray(new String[0]); + updateConfigsForUser(mContext.getUserId(), packageNames); } @Override @@ -228,80 +214,166 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - private static class GameModeConfiguration { - public static final String TAG = "GameManagerService_GameModeConfiguration"; - public static final String MODE_KEY = "mode"; - public static final String SCALING_KEY = "downscaleFactor"; + /** + * GamePackageConfiguration manages all game mode config details for its associated package. + */ + @VisibleForTesting + public class GamePackageConfiguration { + public static final String TAG = "GameManagerService_GamePackageConfiguration"; - private final @GameMode int mGameMode; - private final String mScaling; + /** + * Metadata that can be included in the app manifest to allow/disallow any window manager + * downscaling interventions. Default value is TRUE. + */ + public static final String METADATA_WM_ALLOW_DOWNSCALE = + "com.android.graphics.intervention.wm.allowDownscale"; - private GameModeConfiguration(@NonNull int gameMode, - @NonNull String scaling) { - mGameMode = gameMode; - mScaling = scaling; - } + /** + * Metadata that needs to be included in the app manifest to OPT-IN to PERFORMANCE mode. + * This means the app will assume full responsibility for the experience provided by this + * mode and the system will enable no window manager downscaling. + * Default value is FALSE + */ + public static final String METADATA_PERFORMANCE_MODE_ENABLE = + "com.android.app.gamemode.performance.enabled"; - public static GameModeConfiguration fromKeyValueListParser(KeyValueListParser parser) { - return new GameModeConfiguration( - parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED), - parser.getString(SCALING_KEY, "1.0") - ); - } + /** + * Metadata that needs to be included in the app manifest to OPT-IN to BATTERY mode. + * This means the app will assume full responsibility for the experience provided by this + * mode and the system will enable no window manager downscaling. + * Default value is FALSE + */ + public static final String METADATA_BATTERY_MODE_ENABLE = + "com.android.app.gamemode.battery.enabled"; - public int getGameMode() { - return mGameMode; - } + private final String mPackageName; + private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs; + private boolean mPerfModeOptedIn; + private boolean mBatteryModeOptedIn; + private boolean mAllowDownscale; - public String getScaling() { - return mScaling; + GamePackageConfiguration(String packageName, int userId) { + mPackageName = packageName; + mModeConfigs = new ArrayMap<>(); + try { + final ApplicationInfo ai = mPackageManager.getApplicationInfoAsUser(packageName, + PackageManager.GET_META_DATA, userId); + if (ai.metaData != null) { + mPerfModeOptedIn = ai.metaData.getBoolean(METADATA_PERFORMANCE_MODE_ENABLE); + mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE); + mAllowDownscale = ai.metaData.getBoolean(METADATA_WM_ALLOW_DOWNSCALE, true); + } else { + mPerfModeOptedIn = false; + mBatteryModeOptedIn = false; + mAllowDownscale = true; + } + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, "Failed to get package metadata", e); + } + final String configString = DeviceConfig.getProperty( + DeviceConfig.NAMESPACE_GAME_OVERLAY, packageName); + if (configString != null) { + final String[] gameModeConfigStrings = configString.split(":"); + for (String gameModeConfigString : gameModeConfigStrings) { + try { + final KeyValueListParser parser = new KeyValueListParser(','); + parser.setString(gameModeConfigString); + addModeConfig(new GameModeConfiguration(parser)); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Invalid config string"); + } + } + } } - public boolean isValid() { - return (mGameMode == GameManager.GAME_MODE_PERFORMANCE - || mGameMode == GameManager.GAME_MODE_BATTERY) && getCompatChangeId() != 0; - } + /** + * GameModeConfiguration contains all the values for all the interventions associated with + * a game mode. + */ + @VisibleForTesting + public class GameModeConfiguration { + public static final String TAG = "GameManagerService_GameModeConfiguration"; + public static final String MODE_KEY = "mode"; + public static final String SCALING_KEY = "downscaleFactor"; + public static final String DEFAULT_SCALING = "1.0"; + + private final @GameMode int mGameMode; + private final String mScaling; + + GameModeConfiguration(KeyValueListParser parser) { + mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED); + mScaling = !mAllowDownscale || isGameModeOptedIn(mGameMode) + ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING); + } - public String toString() { - return "[Game Mode:" + mGameMode + ",Scaling:" + mScaling + "]"; - } + public int getGameMode() { + return mGameMode; + } - public long getCompatChangeId() { - switch (mScaling) { - case "0.5": - return DOWNSCALE_50; - case "0.6": - return DOWNSCALE_60; - case "0.7": - return DOWNSCALE_70; - case "0.8": - return DOWNSCALE_80; - case "0.9": - return DOWNSCALE_90; + public String getScaling() { + return mScaling; } - return 0; - } - } - private static class GamePackageConfiguration { - public static final String TAG = "GameManagerService_GamePackageConfiguration"; + public boolean isValid() { + return (mGameMode == GameManager.GAME_MODE_PERFORMANCE + || mGameMode == GameManager.GAME_MODE_BATTERY) + && (!mAllowDownscale || getCompatChangeId() != 0); + } - private final String mPackageName; - private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs; + /** + * @hide + */ + public String toString() { + return "[Game Mode:" + mGameMode + ",Scaling:" + mScaling + "]"; + } - private GamePackageConfiguration(String packageName) { - mPackageName = packageName; - mModeConfigs = new ArrayMap<>(); + /** + * Get the corresponding compat change id for the current scaling string. + */ + public long getCompatChangeId() { + switch (mScaling) { + case "0.5": + return DOWNSCALE_50; + case "0.6": + return DOWNSCALE_60; + case "0.7": + return DOWNSCALE_70; + case "0.8": + return DOWNSCALE_80; + case "0.9": + return DOWNSCALE_90; + } + return 0; + } } public String getPackageName() { return mPackageName; } + /** + * Gets whether a package has opted into a game mode via its manifest. + * + * @return True if the app package has specified in its metadata either: + * "com.android.app.gamemode.performance.enabled" or + * "com.android.app.gamemode.battery.enabled" with a value of "true" + */ + public boolean isGameModeOptedIn(@GameMode int gameMode) { + return (mBatteryModeOptedIn && gameMode == GameManager.GAME_MODE_BATTERY) + || (mPerfModeOptedIn && gameMode == GameManager.GAME_MODE_PERFORMANCE); + } + public @GameMode int[] getAvailableGameModes() { - if (mModeConfigs.keySet().size() > 0) { - return mModeConfigs.keySet().stream() - .mapToInt(Integer::intValue).toArray(); + ArraySet<Integer> modeSet = new ArraySet<>(mModeConfigs.keySet()); + if (mBatteryModeOptedIn) { + modeSet.add(GameManager.GAME_MODE_BATTERY); + } + if (mPerfModeOptedIn) { + modeSet.add(GameManager.GAME_MODE_PERFORMANCE); + } + if (modeSet.size() > 0) { + modeSet.add(GameManager.GAME_MODE_STANDARD); + return modeSet.stream().mapToInt(Integer::intValue).toArray(); } return new int[]{GameManager.GAME_MODE_UNSUPPORTED}; } @@ -327,30 +399,8 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - /** - * Create a new instance from a package name and DeviceConfig.Properties instance - */ - public static GamePackageConfiguration fromProperties(String key, - Properties properties) { - final GamePackageConfiguration packageConfig = new GamePackageConfiguration(key); - final String configString = properties.getString(key, ""); - final String[] gameModeConfigStrings = configString.split(":"); - for (String gameModeConfigString : gameModeConfigStrings) { - try { - final KeyValueListParser parser = new KeyValueListParser(','); - parser.setString(gameModeConfigString); - final GameModeConfiguration config = - GameModeConfiguration.fromKeyValueListParser(parser); - packageConfig.addModeConfig(config); - } catch (IllegalArgumentException e) { - Slog.e(TAG, "Invalid config string"); - } - } - return packageConfig; - } - public boolean isValid() { - return mModeConfigs.size() > 0; + return mModeConfigs.size() > 0 || mBatteryModeOptedIn || mPerfModeOptedIn; } public String toString() { @@ -534,8 +584,6 @@ public final class GameManagerService extends IGameManagerService.Stub { @VisibleForTesting void onBootCompleted() { Slog.d(TAG, "onBootCompleted"); - final Message msg = mHandler.obtainMessage(POPULATE_GAME_MODE_SETTINGS); - mHandler.sendMessage(msg); } void onUserStarting(int userId) { @@ -549,6 +597,9 @@ public final class GameManagerService extends IGameManagerService.Stub { mSettings.put(userId, userSettings); userSettings.readPersistentDataLocked(); } + final Message msg = mHandler.obtainMessage(POPULATE_GAME_MODE_SETTINGS); + msg.obj = userId; + mHandler.sendMessage(msg); } void onUserStopping(int userId) { @@ -562,24 +613,14 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - void loadDeviceConfigLocked() { - final List<PackageInfo> packages = mPackageManager.getInstalledPackages(0); - final String[] packageNames = packages.stream().map(e -> e.packageName) - .toArray(String[]::new); - synchronized (mDeviceConfigLock) { - final Properties properties = DeviceConfig.getProperties( - DeviceConfig.NAMESPACE_GAME_OVERLAY, packageNames); - for (String key : properties.getKeyset()) { - final GamePackageConfiguration config = - GamePackageConfiguration.fromProperties(key, properties); - putConfig(config); - } - } - } - - private void disableCompatScale(String packageName) { + /** + * @hide + */ + @VisibleForTesting + public void disableCompatScale(String packageName) { final long uid = Binder.clearCallingIdentity(); try { + Slog.i(TAG, "Disabling downscale for " + packageName); final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>(); overrides.put(DOWNSCALED, COMPAT_DISABLED); final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig( @@ -597,6 +638,7 @@ public final class GameManagerService extends IGameManagerService.Stub { private void enableCompatScale(String packageName, long scaleId) { final long uid = Binder.clearCallingIdentity(); try { + Slog.i(TAG, "Enabling downscale: " + scaleId + " for " + packageName); final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>(); overrides.put(DOWNSCALED, COMPAT_ENABLED); overrides.put(DOWNSCALE_50, COMPAT_DISABLED); @@ -622,21 +664,25 @@ public final class GameManagerService extends IGameManagerService.Stub { if (gameMode == GameManager.GAME_MODE_STANDARD || gameMode == GameManager.GAME_MODE_UNSUPPORTED) { disableCompatScale(packageName); - Slog.v(TAG, "Disabling downscale"); + return; + } + final GamePackageConfiguration packageConfig = mConfigs.get(packageName); + if (packageConfig == null) { + disableCompatScale(packageName); + Slog.v(TAG, "Package configuration not found for " + packageName); return; } if (DEBUG) { Slog.v(TAG, dumpDeviceConfigs()); } - final GamePackageConfiguration packageConfig = mConfigs.get(packageName); - if (packageConfig == null) { - Slog.w(TAG, "Package configuration not found for " + packageName); + if (packageConfig.isGameModeOptedIn(gameMode)) { + disableCompatScale(packageName); return; } - final GameModeConfiguration modeConfig = packageConfig.getGameModeConfiguration( - gameMode); + final GamePackageConfiguration.GameModeConfiguration modeConfig = + packageConfig.getGameModeConfiguration(gameMode); if (modeConfig == null) { - Slog.w(TAG, "Game mode " + gameMode + " not found for " + packageName); + Slog.i(TAG, "Game mode " + gameMode + " not found for " + packageName); return; } long scaleId = modeConfig.getCompatChangeId(); @@ -645,23 +691,64 @@ public final class GameManagerService extends IGameManagerService.Stub { + packageName); return; } - Slog.i(TAG, "Enabling downscale: " + scaleId + " for " + packageName); + enableCompatScale(packageName, scaleId); } } - private void putConfig(GamePackageConfiguration config) { - if (config.isValid()) { - if (DEBUG) { - Slog.i(TAG, "Adding config: " + config.toString()); + /** + * @hide + */ + @VisibleForTesting + public void updateConfigsForUser(int userId, String ...packageNames) { + try { + synchronized (mDeviceConfigLock) { + for (String packageName : packageNames) { + GamePackageConfiguration config = + new GamePackageConfiguration(packageName, userId); + if (config.isValid()) { + if (DEBUG) { + Slog.i(TAG, "Adding config: " + config.toString()); + } + mConfigs.put(packageName, config); + } else { + Slog.w(TAG, "Invalid package config for " + + config.getPackageName() + ":" + config.toString()); + mConfigs.remove(packageName); + } + } } - mConfigs.put(config.getPackageName(), config); - } else { - Slog.w(TAG, "Invalid package config for " - + config.getPackageName() + ":" + config.toString()); + for (String packageName : packageNames) { + synchronized (mLock) { + if (mSettings.containsKey(userId)) { + GameManagerSettings userSettings = mSettings.get(userId); + updateCompatModeDownscale(packageName, + userSettings.getGameModeLocked(packageName)); + } + } + } + } catch (Exception e) { + Slog.e(TAG, "Failed to update compat modes for user: " + userId); } } + private String[] getInstalledGamePackageNames(int userId) { + final List<PackageInfo> packages = + mPackageManager.getInstalledPackagesAsUser(0, userId); + return packages.stream().filter(e -> e.applicationInfo != null && e.applicationInfo.category + == ApplicationInfo.CATEGORY_GAME) + .map(e -> e.packageName) + .toArray(String[]::new); + } + + /** + * @hide + */ + @VisibleForTesting + public GamePackageConfiguration getConfig(String packageName) { + return mConfigs.get(packageName); + } + private void registerPackageReceiver() { final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(ACTION_PACKAGE_ADDED); @@ -677,16 +764,7 @@ public final class GameManagerService extends IGameManagerService.Stub { switch (intent.getAction()) { case ACTION_PACKAGE_ADDED: case ACTION_PACKAGE_CHANGED: - synchronized (mDeviceConfigLock) { - Properties properties = DeviceConfig.getProperties( - DeviceConfig.NAMESPACE_GAME_OVERLAY, packageName); - for (String key : properties.getKeyset()) { - GamePackageConfiguration config = - GamePackageConfiguration.fromProperties(key, - properties); - putConfig(config); - } - } + updateConfigsForUser(mContext.getUserId(), packageName); break; case ACTION_PACKAGE_REMOVED: disableCompatScale(packageName); diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java index 63b41b789280..e9b61b3ab7fb 100644 --- a/services/core/java/com/android/server/appop/DiscreteRegistry.java +++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java @@ -69,18 +69,47 @@ import java.util.Date; import java.util.List; /** - * This class manages information about recent accesses to ops for - * permission usage timeline. + * This class manages information about recent accesses to ops for permission usage timeline. * - * The timeline history is kept for limited time (initial default is 24 hours) and - * discarded after that. + * The discrete history is kept for limited time (initial default is 24 hours, set in + * {@link DiscreteRegistry#sDiscreteHistoryCutoff) and discarded after that. + * + * Discrete history is quantized to reduce resources footprint. By default quantization is set to + * one minute in {@link DiscreteRegistry#sDiscreteHistoryQuantization}. All access times are aligned + * to the closest quantized time. All durations (except -1, meaning no duration) are rounded up to + * the closest quantized interval. + * + * When data is queried through API, events are deduplicated and for every time quant there can + * be only one {@link AppOpsManager.AttributedOpEntry}. Each entry contains information about + * different accesses which happened in specified time quant - across dimensions of + * {@link AppOpsManager.UidState} and {@link AppOpsManager.OpFlags}. For each dimension + * it is only possible to know if at least one access happened in the time quant. * * Every time state is saved (default is 30 minutes), memory state is dumped to a * new file and memory state is cleared. Files older than time limit are deleted * during the process. * * When request comes in, files are read and requested information is collected - * and delivered. + * and delivered. Information is cached in memory until the next state save (up to 30 minutes), to + * avoid reading disk if more API calls come in a quick succession. + * + * THREADING AND LOCKING: + * For in-memory transactions this class relies on {@link DiscreteRegistry#mInMemoryLock}. It is + * assumed that the same lock is used for in-memory transactions in {@link AppOpsService}, + * {@link HistoricalRegistry}, and {@link DiscreteRegistry}. + * {@link DiscreteRegistry#recordDiscreteAccess(int, String, int, String, int, int, long, long)} + * must only be called while holding this lock. + * {@link DiscreteRegistry#mOnDiskLock} is used when disk transactions are performed. + * It is very important to release {@link DiscreteRegistry#mInMemoryLock} as soon as possible, as + * no AppOps related transactions across the system can be performed while it is held. + * + * INITIALIZATION: We can initialize persistence only after the system is ready + * as we need to check the optional configuration override from the settings + * database which is not initialized at the time the app ops service is created. This class + * relies on {@link HistoricalRegistry} for controlling that no calls are allowed until then. All + * outside calls are going through {@link HistoricalRegistry}, where + * {@link HistoricalRegistry#isPersistenceInitializedMLocked()} check is done. + * */ final class DiscreteRegistry { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 08a7d9e38d96..0840e75823b5 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -123,7 +123,7 @@ import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL; import android.Manifest; import android.Manifest.permission; -import android.annotation.CallbackExecutor; +import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -492,7 +492,7 @@ public class NotificationManagerService extends SystemService { private DeviceIdleManager mDeviceIdleManager; private IUriGrantsManager mUgm; private UriGrantsManagerInternal mUgmInternal; - private RoleObserver mRoleObserver; + private volatile RoleObserver mRoleObserver; private UserManager mUm; private IPlatformCompat mPlatformCompat; private ShortcutHelper mShortcutHelper; @@ -629,6 +629,8 @@ public class NotificationManagerService extends SystemService { static class Archive { final SparseArray<Boolean> mEnabled; final int mBufferSize; + final Object mBufferLock = new Object(); + @GuardedBy("mBufferLock") final LinkedList<Pair<StatusBarNotification, Integer>> mBuffer; public Archive(int size) { @@ -651,14 +653,16 @@ public class NotificationManagerService extends SystemService { if (!mEnabled.get(sbn.getNormalizedUserId(), false)) { return; } - if (mBuffer.size() == mBufferSize) { - mBuffer.removeFirst(); - } + synchronized (mBufferLock) { + if (mBuffer.size() == mBufferSize) { + mBuffer.removeFirst(); + } - // We don't want to store the heavy bits of the notification in the archive, - // but other clients in the system process might be using the object, so we - // store a (lightened) copy. - mBuffer.addLast(new Pair<>(sbn.cloneLight(), reason)); + // We don't want to store the heavy bits of the notification in the archive, + // but other clients in the system process might be using the object, so we + // store a (lightened) copy. + mBuffer.addLast(new Pair<>(sbn.cloneLight(), reason)); + } } public Iterator<Pair<StatusBarNotification, Integer>> descendingIterator() { @@ -666,27 +670,31 @@ public class NotificationManagerService extends SystemService { } public StatusBarNotification[] getArray(int count, boolean includeSnoozed) { - if (count == 0) count = mBufferSize; - List<StatusBarNotification> a = new ArrayList(); - Iterator<Pair<StatusBarNotification, Integer>> iter = descendingIterator(); - int i=0; - while (iter.hasNext() && i < count) { - Pair<StatusBarNotification, Integer> pair = iter.next(); - if (pair.second != REASON_SNOOZED || includeSnoozed) { - i++; - a.add(pair.first); + synchronized (mBufferLock) { + if (count == 0) count = mBufferSize; + List<StatusBarNotification> a = new ArrayList(); + Iterator<Pair<StatusBarNotification, Integer>> iter = descendingIterator(); + int i = 0; + while (iter.hasNext() && i < count) { + Pair<StatusBarNotification, Integer> pair = iter.next(); + if (pair.second != REASON_SNOOZED || includeSnoozed) { + i++; + a.add(pair.first); + } } + return a.toArray(new StatusBarNotification[a.size()]); } - return a.toArray(new StatusBarNotification[a.size()]); } public void updateHistoryEnabled(@UserIdInt int userId, boolean enabled) { mEnabled.put(userId, enabled); if (!enabled) { - for (int i = mBuffer.size() - 1; i >= 0; i--) { - if (userId == mBuffer.get(i).first.getNormalizedUserId()) { - mBuffer.remove(i); + synchronized (mBufferLock) { + for (int i = mBuffer.size() - 1; i >= 0; i--) { + if (userId == mBuffer.get(i).first.getNormalizedUserId()) { + mBuffer.remove(i); + } } } } @@ -695,15 +703,18 @@ public class NotificationManagerService extends SystemService { // Remove notifications with the specified user & channel ID. public void removeChannelNotifications(String pkg, @UserIdInt int userId, String channelId) { - Iterator<Pair<StatusBarNotification, Integer>> bufferIter = mBuffer.iterator(); - while (bufferIter.hasNext()) { - final Pair<StatusBarNotification, Integer> pair = bufferIter.next(); - if (pair.first != null - && userId == pair.first.getNormalizedUserId() - && pkg != null && pkg.equals(pair.first.getPackageName()) - && pair.first.getNotification() != null - && Objects.equals(channelId, pair.first.getNotification().getChannelId())) { - bufferIter.remove(); + synchronized (mBufferLock) { + Iterator<Pair<StatusBarNotification, Integer>> bufferIter = descendingIterator(); + while (bufferIter.hasNext()) { + final Pair<StatusBarNotification, Integer> pair = bufferIter.next(); + if (pair.first != null + && userId == pair.first.getNormalizedUserId() + && pkg != null && pkg.equals(pair.first.getPackageName()) + && pair.first.getNotification() != null + && Objects.equals(channelId, + pair.first.getNotification().getChannelId())) { + bufferIter.remove(); + } } } } @@ -2640,6 +2651,11 @@ public class NotificationManagerService extends SystemService { @Override public void onBootPhase(int phase) { + onBootPhase(phase, Looper.getMainLooper()); + } + + @VisibleForTesting + void onBootPhase(int phase, Looper mainLooper) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { // no beeping until we're basically done booting mSystemReady = true; @@ -2649,9 +2665,11 @@ public class NotificationManagerService extends SystemService { mAudioManagerInternal = getLocalService(AudioManagerInternal.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mZenModeHelper.onSystemReady(); - mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class), - mPackageManager, getContext().getMainExecutor()); - mRoleObserver.init(); + RoleObserver roleObserver = new RoleObserver(getContext(), + getContext().getSystemService(RoleManager.class), + mPackageManager, mainLooper); + roleObserver.init(); + mRoleObserver = roleObserver; LauncherApps launcherApps = (LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE); mShortcutHelper = new ShortcutHelper(launcherApps, mShortcutListener, getLocalService( @@ -10677,26 +10695,40 @@ public class NotificationManagerService extends SystemService { // Role name : user id : list of approved packages private ArrayMap<String, ArrayMap<Integer, ArraySet<String>>> mNonBlockableDefaultApps; + /** + * Writes should be pretty rare (only when default browser changes) and reads are done + * during activity start code-path, so we're optimizing for reads. This means this set is + * immutable once written and we'll recreate the set every time there is a role change and + * then assign that new set to the volatile below, so reads can be done without needing to + * hold a lock. Every write is done on the main-thread, so write atomicity is guaranteed. + * + * Didn't use unmodifiable set to enforce immutability to avoid iterating via iterators. + */ + private volatile ArraySet<Integer> mTrampolineExemptUids = new ArraySet<>(); + private final RoleManager mRm; private final IPackageManager mPm; private final Executor mExecutor; + private final Looper mMainLooper; - RoleObserver(@NonNull RoleManager roleManager, - @NonNull IPackageManager pkgMgr, - @NonNull @CallbackExecutor Executor executor) { + RoleObserver(Context context, @NonNull RoleManager roleManager, + @NonNull IPackageManager pkgMgr, @NonNull Looper mainLooper) { mRm = roleManager; mPm = pkgMgr; - mExecutor = executor; + mExecutor = context.getMainExecutor(); + mMainLooper = mainLooper; } + /** Should be called from the main-thread. */ + @MainThread public void init() { - List<UserInfo> users = mUm.getUsers(); + List<UserHandle> users = mUm.getUserHandles(/* excludeDying */ true); mNonBlockableDefaultApps = new ArrayMap<>(); for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) { final ArrayMap<Integer, ArraySet<String>> userToApprovedList = new ArrayMap<>(); mNonBlockableDefaultApps.put(NON_BLOCKABLE_DEFAULT_ROLES[i], userToApprovedList); for (int j = 0; j < users.size(); j++) { - Integer userId = users.get(j).getUserHandle().getIdentifier(); + Integer userId = users.get(j).getIdentifier(); ArraySet<String> approvedForUserId = new ArraySet<>(mRm.getRoleHoldersAsUser( NON_BLOCKABLE_DEFAULT_ROLES[i], UserHandle.of(userId))); ArraySet<Pair<String, Integer>> approvedAppUids = new ArraySet<>(); @@ -10707,7 +10739,7 @@ public class NotificationManagerService extends SystemService { mPreferencesHelper.updateDefaultApps(userId, null, approvedAppUids); } } - + updateTrampolineExemptUidsForUsers(users.toArray(new UserHandle[0])); mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); } @@ -10716,6 +10748,11 @@ public class NotificationManagerService extends SystemService { return mNonBlockableDefaultApps.get(role).get(userId).contains(pkg); } + @VisibleForTesting + public boolean isUidExemptFromTrampolineRestrictions(int uid) { + return mTrampolineExemptUids.contains(uid); + } + /** * Convert the assistant-role holder into settings. The rest of the system uses the * settings. @@ -10725,6 +10762,12 @@ public class NotificationManagerService extends SystemService { */ @Override public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { + onRoleHoldersChangedForNonBlockableDefaultApps(roleName, user); + onRoleHoldersChangedForTrampolines(roleName, user); + } + + private void onRoleHoldersChangedForNonBlockableDefaultApps(@NonNull String roleName, + @NonNull UserHandle user) { // we only care about a couple of the roles they'll tell us about boolean relevantChange = false; for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) { @@ -10772,6 +10815,41 @@ public class NotificationManagerService extends SystemService { // write of the notification policy xml for this change } + private void onRoleHoldersChangedForTrampolines(@NonNull String roleName, + @NonNull UserHandle user) { + if (!RoleManager.ROLE_BROWSER.equals(roleName)) { + return; + } + updateTrampolineExemptUidsForUsers(user); + } + + private void updateTrampolineExemptUidsForUsers(UserHandle... users) { + Preconditions.checkState(mMainLooper.isCurrentThread()); + ArraySet<Integer> oldUids = mTrampolineExemptUids; + ArraySet<Integer> newUids = new ArraySet<>(); + // Add the uids from previous set for the users that we won't update. + for (int i = 0, n = oldUids.size(); i < n; i++) { + int uid = oldUids.valueAt(i); + UserHandle user = UserHandle.of(UserHandle.getUserId(uid)); + if (!ArrayUtils.contains(users, user)) { + newUids.add(uid); + } + } + // Now lookup the new uids for the users that we want to update. + for (int i = 0, n = users.length; i < n; i++) { + UserHandle user = users[i]; + for (String pkg : mRm.getRoleHoldersAsUser(RoleManager.ROLE_BROWSER, user)) { + int uid = getUidForPackage(pkg, user.getIdentifier()); + if (uid != -1) { + newUids.add(uid); + } else { + Slog.e(TAG, "Bad uid (-1) for browser package " + pkg); + } + } + } + mTrampolineExemptUids = newUids; + } + private int getUidForPackage(String pkg, int userId) { try { return mPm.getPackageUid(pkg, MATCH_ALL, userId); @@ -10936,7 +11014,7 @@ public class NotificationManagerService extends SystemService { } String logcatMessage = "Indirect notification activity start (trampoline) from " + packageName; - if (CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid)) { + if (blockTrampoline(uid)) { // Post toast() call to mHandler to offload PM lookup from the activity start path mHandler.post(() -> toast(packageName, uid)); Slog.e(TAG, logcatMessage + " blocked"); @@ -10947,6 +11025,13 @@ public class NotificationManagerService extends SystemService { } } + private boolean blockTrampoline(int uid) { + if (mRoleObserver != null && mRoleObserver.isUidExemptFromTrampolineRestrictions(uid)) { + return false; + } + return CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid); + } + @Override public boolean canCloseSystemDialogs(Collection<IBinder> tokens, int uid) { // If the start is allowed via notification, we allow the app to close system dialogs diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java index afce23fe7647..28511070fc8e 100644 --- a/services/core/java/com/android/server/pm/ApkChecksums.java +++ b/services/core/java/com/android/server/pm/ApkChecksums.java @@ -303,8 +303,8 @@ public class ApkChecksums { * @param onChecksumsReadyListener to receive the resulting checksums */ public static void getChecksums(List<Pair<String, File>> filesToChecksum, - @Checksum.Type int optional, - @Checksum.Type int required, + @Checksum.TypeMask int optional, + @Checksum.TypeMask int required, @Nullable String installerPackageName, @Nullable Certificate[] trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, @@ -331,7 +331,7 @@ public class ApkChecksums { private static void processRequiredChecksums(List<Pair<String, File>> filesToChecksum, List<Map<Integer, ApkChecksum>> result, - @Checksum.Type int required, + @Checksum.TypeMask int required, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, @NonNull Injector injector, long startTime) { @@ -382,7 +382,7 @@ public class ApkChecksums { * @param checksums resulting checksums */ private static void getAvailableApkChecksums(String split, File file, - @Checksum.Type int types, + @Checksum.TypeMask int types, @Nullable String installerPackageName, @Nullable Certificate[] trustedInstallers, Map<Integer, ApkChecksum> checksums, @@ -415,7 +415,7 @@ public class ApkChecksums { } private static void getInstallerChecksums(String split, File file, - @Checksum.Type int types, + @Checksum.TypeMask int types, @Nullable String installerPackageName, @Nullable Certificate[] trustedInstallers, Map<Integer, ApkChecksum> checksums, @@ -523,7 +523,7 @@ public class ApkChecksums { * Whether the file is available for checksumming or we need to wait. */ private static boolean needToWait(File file, - @Checksum.Type int types, + @Checksum.TypeMask int types, Map<Integer, ApkChecksum> checksums, @NonNull Injector injector) throws IOException { if (!isRequired(TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, types, checksums) @@ -564,7 +564,7 @@ public class ApkChecksums { * @param checksums resulting checksums */ private static void getRequiredApkChecksums(String split, File file, - @Checksum.Type int types, + @Checksum.TypeMask int types, Map<Integer, ApkChecksum> checksums) { final String filePath = file.getAbsolutePath(); @@ -596,7 +596,7 @@ public class ApkChecksums { } private static boolean isRequired(@Checksum.Type int type, - @Checksum.Type int types, Map<Integer, ApkChecksum> checksums) { + @Checksum.TypeMask int types, Map<Integer, ApkChecksum> checksums) { if ((types & type) == 0) { return false; } diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index 1d556fec31ea..dde9f822ac76 100644 --- a/services/core/java/com/android/server/pm/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/ComponentResolver.java @@ -59,6 +59,9 @@ import com.android.server.IntentResolver; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator; import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.utils.Snappable; +import com.android.server.utils.SnapshotCache; +import com.android.server.utils.WatchableImpl; import java.io.PrintWriter; import java.util.ArrayList; @@ -72,12 +75,19 @@ import java.util.Set; import java.util.function.Function; /** Resolves all Android component types [activities, services, providers and receivers]. */ -public class ComponentResolver { +public class ComponentResolver + extends WatchableImpl + implements Snappable { private static final boolean DEBUG = false; private static final String TAG = "PackageManager"; private static final boolean DEBUG_FILTERS = false; private static final boolean DEBUG_SHOW_INFO = false; + // Convenience function to report that this object has changed. + private void onChanged() { + dispatchChange(this); + } + /** * The set of all protected actions [i.e. those actions for which a high priority * intent filter is disallowed]. @@ -158,27 +168,27 @@ public class ComponentResolver { * would be able to hold its lock while checking the package setting state.</li> * </ol> */ - private final Object mLock; + private final PackageManagerTracedLock mLock; /** All available activities, for your resolving pleasure. */ @GuardedBy("mLock") - private final ActivityIntentResolver mActivities = new ActivityIntentResolver(); + private final ActivityIntentResolver mActivities; /** All available providers, for your resolving pleasure. */ @GuardedBy("mLock") - private final ProviderIntentResolver mProviders = new ProviderIntentResolver(); + private final ProviderIntentResolver mProviders; /** All available receivers, for your resolving pleasure. */ @GuardedBy("mLock") - private final ActivityIntentResolver mReceivers = new ReceiverIntentResolver(); + private final ReceiverIntentResolver mReceivers; /** All available services, for your resolving pleasure. */ @GuardedBy("mLock") - private final ServiceIntentResolver mServices = new ServiceIntentResolver(); + private final ServiceIntentResolver mServices; /** Mapping from provider authority [first directory in content URI codePath) to provider. */ @GuardedBy("mLock") - private final ArrayMap<String, ParsedProvider> mProvidersByAuthority = new ArrayMap<>(); + private final ArrayMap<String, ParsedProvider> mProvidersByAuthority; /** Whether or not processing protected filters should be deferred. */ private boolean mDeferProtectedFilters = true; @@ -200,12 +210,57 @@ public class ComponentResolver { ComponentResolver(UserManagerService userManager, PackageManagerInternal packageManagerInternal, - Object lock) { + PackageManagerTracedLock lock) { sPackageManagerInternal = packageManagerInternal; sUserManager = userManager; mLock = lock; + + mActivities = new ActivityIntentResolver(); + mProviders = new ProviderIntentResolver(); + mReceivers = new ReceiverIntentResolver(); + mServices = new ServiceIntentResolver(); + mProvidersByAuthority = new ArrayMap<>(); + mDeferProtectedFilters = true; + + mSnapshot = new SnapshotCache<ComponentResolver>(this, this) { + @Override + public ComponentResolver createSnapshot() { + return new ComponentResolver(mSource); + }}; + } + + // Copy constructor used in creating snapshots. + private ComponentResolver(ComponentResolver orig) { + // Do not set the static variables that are set in the default constructor. Do + // create a new object for the lock. The snapshot is read-only, so a lock is not + // strictly required. However, the current code is simpler if the lock exists, + // but does not contend with any outside class. + // TODO: make the snapshot lock-free + mLock = new PackageManagerTracedLock(); + + mActivities = new ActivityIntentResolver(orig.mActivities); + mProviders = new ProviderIntentResolver(orig.mProviders); + mReceivers = new ReceiverIntentResolver(orig.mReceivers); + mServices = new ServiceIntentResolver(orig.mServices); + mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority); + mDeferProtectedFilters = orig.mDeferProtectedFilters; + mProtectedFilters = (mProtectedFilters == null) + ? null + : new ArrayList<>(orig.mProtectedFilters); + + mSnapshot = null; } + final SnapshotCache<ComponentResolver> mSnapshot; + + /** + * Create a snapshot. + */ + public ComponentResolver snapshot() { + return mSnapshot.snapshot(); + } + + /** Returns the given activity */ @Nullable @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @@ -474,6 +529,7 @@ public class ComponentResolver { addReceiversLocked(pkg, chatty); addProvidersLocked(pkg, chatty); addServicesLocked(pkg, chatty); + onChanged(); } // expect single setupwizard package final String setupWizardPackage = ArrayUtils.firstOrNull( @@ -489,6 +545,7 @@ public class ComponentResolver { final List<ParsedActivity> systemActivities = disabledPkg != null ? disabledPkg.getActivities() : null; adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage); + onChanged(); } } @@ -496,6 +553,7 @@ public class ComponentResolver { void removeAllComponents(AndroidPackage pkg, boolean chatty) { synchronized (mLock) { removeAllComponentsLocked(pkg, chatty); + onChanged(); } } @@ -504,51 +562,54 @@ public class ComponentResolver { * all of the filters defined on the /system partition and know the special components. */ void fixProtectedFilterPriorities() { - if (!mDeferProtectedFilters) { - return; - } - mDeferProtectedFilters = false; + synchronized (mLock) { + if (!mDeferProtectedFilters) { + return; + } + mDeferProtectedFilters = false; - if (mProtectedFilters == null || mProtectedFilters.size() == 0) { - return; - } - final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters = - mProtectedFilters; - mProtectedFilters = null; + if (mProtectedFilters == null || mProtectedFilters.size() == 0) { + return; + } + final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters = + mProtectedFilters; + mProtectedFilters = null; - // expect single setupwizard package - final String setupWizardPackage = ArrayUtils.firstOrNull( + // expect single setupwizard package + final String setupWizardPackage = ArrayUtils.firstOrNull( sPackageManagerInternal.getKnownPackageNames( - PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); - - if (DEBUG_FILTERS && setupWizardPackage == null) { - Slog.i(TAG, "No setup wizard;" - + " All protected intents capped to priority 0"); - } - for (int i = protectedFilters.size() - 1; i >= 0; --i) { - final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i); - ParsedMainComponent component = pair.first; - ParsedIntentInfo filter = pair.second; - String packageName = component.getPackageName(); - String className = component.getClassName(); - if (packageName.equals(setupWizardPackage)) { + PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); + + if (DEBUG_FILTERS && setupWizardPackage == null) { + Slog.i(TAG, "No setup wizard;" + + " All protected intents capped to priority 0"); + } + for (int i = protectedFilters.size() - 1; i >= 0; --i) { + final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i); + ParsedMainComponent component = pair.first; + ParsedIntentInfo filter = pair.second; + String packageName = component.getPackageName(); + String className = component.getClassName(); + if (packageName.equals(setupWizardPackage)) { + if (DEBUG_FILTERS) { + Slog.i(TAG, "Found setup wizard;" + + " allow priority " + filter.getPriority() + ";" + + " package: " + packageName + + " activity: " + className + + " priority: " + filter.getPriority()); + } + // skip setup wizard; allow it to keep the high priority filter + continue; + } if (DEBUG_FILTERS) { - Slog.i(TAG, "Found setup wizard;" - + " allow priority " + filter.getPriority() + ";" + Slog.i(TAG, "Protected action; cap priority to 0;" + " package: " + packageName + " activity: " + className - + " priority: " + filter.getPriority()); + + " origPrio: " + filter.getPriority()); } - // skip setup wizard; allow it to keep the high priority filter - continue; - } - if (DEBUG_FILTERS) { - Slog.i(TAG, "Protected action; cap priority to 0;" - + " package: " + packageName - + " activity: " + className - + " origPrio: " + filter.getPriority()); + filter.setPriority(0); } - filter.setPriority(0); + onChanged(); } } @@ -1181,9 +1242,20 @@ public class ComponentResolver { private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<? extends ParsedComponent, ParsedIntentInfo>, R> extends IntentResolver<F, R> { - private ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>(); + private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>(); private boolean mIsUpdatingMimeGroup = false; + // Default constructor + MimeGroupsAwareIntentResolver() { + } + + // Copy constructor used in creating snapshots + MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) { + copyFrom(orig); + copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter); + mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup; + } + @Override public void addFilter(F f) { IntentFilter intentFilter = getIntentFilter(f); @@ -1282,6 +1354,17 @@ public class ComponentResolver { private static class ActivityIntentResolver extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> { + // Default constructor + ActivityIntentResolver() { + } + + // Copy constructor used in creating snapshots + ActivityIntentResolver(ActivityIntentResolver orig) { + super(orig); + mActivities.putAll(orig.mActivities); + mFlags = orig.mFlags; + } + @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -1330,7 +1413,7 @@ public class ComponentResolver { return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } - private void addActivity(ParsedActivity a, String type, + protected void addActivity(ParsedActivity a, String type, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) { mActivities.put(a.getComponentName(), a); if (DEBUG_SHOW_INFO) { @@ -1354,7 +1437,7 @@ public class ComponentResolver { } } - private void removeActivity(ParsedActivity a, String type) { + protected void removeActivity(ParsedActivity a, String type) { mActivities.remove(a.getComponentName()); if (DEBUG_SHOW_INFO) { Log.v(TAG, " " + type + ":"); @@ -1567,8 +1650,11 @@ public class ComponentResolver { return pkg.getActivities(); } - // Keys are String (activity class name), values are Activity. - private final ArrayMap<ComponentName, ParsedActivity> mActivities = + // Keys are String (activity class name), values are Activity. This attribute is + // protected because it is accessed directly from ComponentResolver. That works + // even if the attribute is private, but fails for subclasses of + // ActivityIntentResolver. + protected final ArrayMap<ComponentName, ParsedActivity> mActivities = new ArrayMap<>(); private int mFlags; } @@ -1576,6 +1662,15 @@ public class ComponentResolver { // Both receivers and activities share a class, but point to different get methods private static final class ReceiverIntentResolver extends ActivityIntentResolver { + // Default constructor + ReceiverIntentResolver() { + } + + // Copy constructor used in creating snapshots + ReceiverIntentResolver(ReceiverIntentResolver orig) { + super(orig); + } + @Override protected List<ParsedActivity> getResolveList(AndroidPackage pkg) { return pkg.getReceivers(); @@ -1584,6 +1679,17 @@ public class ComponentResolver { private static final class ProviderIntentResolver extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> { + // Default constructor + ProviderIntentResolver() { + } + + // Copy constructor used in creating snapshots + ProviderIntentResolver(ProviderIntentResolver orig) { + super(orig); + mProviders.putAll(orig.mProviders); + mFlags = orig.mFlags; + } + @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -1829,6 +1935,17 @@ public class ComponentResolver { private static final class ServiceIntentResolver extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> { + // Default constructor + ServiceIntentResolver() { + } + + // Copy constructor used in creating snapshots + ServiceIntentResolver(ServiceIntentResolver orig) { + copyFrom(orig); + mServices.putAll(orig.mServices); + mFlags = orig.mFlags; + } + @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -2213,11 +2330,16 @@ public class ComponentResolver { * @return true if any intent filters were changed due to this update */ boolean updateMimeGroup(String packageName, String group) { - boolean hasChanges = mActivities.updateMimeGroup(packageName, group); - hasChanges |= mProviders.updateMimeGroup(packageName, group); - hasChanges |= mReceivers.updateMimeGroup(packageName, group); - hasChanges |= mServices.updateMimeGroup(packageName, group); - + boolean hasChanges = false; + synchronized (mLock) { + hasChanges |= mActivities.updateMimeGroup(packageName, group); + hasChanges |= mProviders.updateMimeGroup(packageName, group); + hasChanges |= mReceivers.updateMimeGroup(packageName, group); + hasChanges |= mServices.updateMimeGroup(packageName, group); + if (hasChanges) { + onChanged(); + } + } return hasChanges; } } diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java index 7c19d90e4ede..f5910fa3143c 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java @@ -24,6 +24,7 @@ import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import com.android.internal.util.XmlUtils; +import com.android.server.utils.SnapshotCache; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -35,7 +36,7 @@ import java.io.IOException; * If an {@link Intent} matches the {@link CrossProfileIntentFilter}, then activities in the user * {@link #mTargetUserId} can access it. */ -class CrossProfileIntentFilter extends IntentFilter { +class CrossProfileIntentFilter extends WatchedIntentFilter { private static final String ATTR_TARGET_USER_ID = "targetUserId"; private static final String ATTR_FLAGS = "flags"; private static final String ATTR_OWNER_PACKAGE = "ownerPackage"; @@ -48,12 +49,41 @@ class CrossProfileIntentFilter extends IntentFilter { final String mOwnerPackage; // packageName of the app. final int mFlags; + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<CrossProfileIntentFilter> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<CrossProfileIntentFilter>(this, this) { + @Override + public CrossProfileIntentFilter createSnapshot() { + CrossProfileIntentFilter s = new CrossProfileIntentFilter(mSource); + s.seal(); + return s; + }}; + } + CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int targetUserId, int flags) { super(filter); mTargetUserId = targetUserId; mOwnerPackage = ownerPackage; mFlags = flags; + mSnapshot = makeCache(); + } + + CrossProfileIntentFilter(WatchedIntentFilter filter, String ownerPackage, int targetUserId, + int flags) { + this(filter.mFilter, ownerPackage, targetUserId, flags); + } + + // Copy constructor used only to create a snapshot. + private CrossProfileIntentFilter(CrossProfileIntentFilter f) { + super(f); + mTargetUserId = f.mTargetUserId; + mOwnerPackage = f.mOwnerPackage; + mFlags = f.mFlags; + mSnapshot = new SnapshotCache.Sealed(); } public int getTargetUserId() { @@ -72,6 +102,7 @@ class CrossProfileIntentFilter extends IntentFilter { mTargetUserId = parser.getAttributeInt(null, ATTR_TARGET_USER_ID, UserHandle.USER_NULL); mOwnerPackage = getStringFromXml(parser, ATTR_OWNER_PACKAGE, ""); mFlags = parser.getAttributeInt(null, ATTR_FLAGS, 0); + mSnapshot = makeCache(); int outerDepth = parser.getDepth(); String tagName = parser.getName(); @@ -94,7 +125,7 @@ class CrossProfileIntentFilter extends IntentFilter { } } if (tagName.equals(ATTR_FILTER)) { - readFromXml(parser); + mFilter.readFromXml(parser); } else { String msg = "Missing element under " + TAG + ": " + ATTR_FILTER + " at " + parser.getPositionDescription(); @@ -103,7 +134,8 @@ class CrossProfileIntentFilter extends IntentFilter { } } - String getStringFromXml(TypedXmlPullParser parser, String attribute, String defaultValue) { + private String getStringFromXml(TypedXmlPullParser parser, String attribute, + String defaultValue) { String value = parser.getAttributeValue(null, attribute); if (value == null) { String msg = "Missing element under " + TAG +": " + attribute + " at " + @@ -120,7 +152,7 @@ class CrossProfileIntentFilter extends IntentFilter { serializer.attributeInt(null, ATTR_FLAGS, mFlags); serializer.attribute(null, ATTR_OWNER_PACKAGE, mOwnerPackage); serializer.startTag(null, ATTR_FILTER); - super.writeToXml(serializer); + mFilter.writeToXml(serializer); serializer.endTag(null, ATTR_FILTER); } @@ -135,4 +167,8 @@ class CrossProfileIntentFilter extends IntentFilter { && mOwnerPackage.equals(other.mOwnerPackage) && mFlags == other.mFlags; } + + public CrossProfileIntentFilter snapshot() { + return mSnapshot.snapshot(); + } } diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java index 791a1057d112..792753860358 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java @@ -21,6 +21,7 @@ import android.content.IntentFilter; import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; +import com.android.server.utils.SnapshotCache; import java.util.List; @@ -47,7 +48,34 @@ class CrossProfileIntentResolver @Override protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) { - return input; + return input.getIntentFilter(); + } + + CrossProfileIntentResolver() { + mSnapshot = makeCache(); + } + + // Take the snapshot of F + protected CrossProfileIntentFilter snapshot(CrossProfileIntentFilter f) { + return (f == null) ? null : f.snapshot(); + } + + // Copy constructor used only to create a snapshot. + private CrossProfileIntentResolver(CrossProfileIntentResolver f) { + copyFrom(f); + mSnapshot = new SnapshotCache.Sealed(); + } + + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<CrossProfileIntentResolver> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<CrossProfileIntentResolver>(this, this) { + @Override + public CrossProfileIntentResolver createSnapshot() { + return new CrossProfileIntentResolver(mSource); + }}; } /** @@ -56,8 +84,6 @@ class CrossProfileIntentResolver * @return A snapshot of the current object. */ public CrossProfileIntentResolver snapshot() { - CrossProfileIntentResolver result = new CrossProfileIntentResolver(); - result.copyFrom(this); - return result; + return mSnapshot.snapshot(); } } diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java index a32e107d9e73..c58128a3c9b1 100644 --- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java +++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java @@ -43,7 +43,7 @@ final class DefaultCrossProfileIntentFilter { } /** The intent filter that's used */ - public final IntentFilter filter; + public final WatchedIntentFilter filter; /** * The flags related to the forwarding, e.g. @@ -66,7 +66,7 @@ final class DefaultCrossProfileIntentFilter { */ public final boolean letsPersonalDataIntoProfile; - private DefaultCrossProfileIntentFilter(IntentFilter filter, int flags, + private DefaultCrossProfileIntentFilter(WatchedIntentFilter filter, int flags, @Direction int direction, boolean letsPersonalDataIntoProfile) { this.filter = requireNonNull(filter); this.flags = flags; @@ -75,7 +75,7 @@ final class DefaultCrossProfileIntentFilter { } static final class Builder { - private IntentFilter mFilter = new IntentFilter(); + private WatchedIntentFilter mFilter = new WatchedIntentFilter(); private int mFlags; private @Direction int mDirection; private boolean mLetsPersonalDataIntoProfile; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index dad37f40babb..db2b166aac63 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -134,6 +134,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTi import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive; import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures; +import static com.android.server.pm.parsing.PackageInfoUtils.checkUseInstalledOrHidden; import android.Manifest; import android.annotation.AppIdInt; @@ -1481,7 +1482,9 @@ public class PackageManagerService extends IPackageManager.Stub // Internal interface for permission manager private final PermissionManagerServiceInternal mPermissionManager; + @Watched private final ComponentResolver mComponentResolver; + // List of packages names to keep cached, even if they are uninstalled for all users private List<String> mKeepUninstalledPackages; @@ -1825,6 +1828,7 @@ public class PackageManagerService extends IPackageManager.Stub public final ApplicationInfo androidApplication; public final String appPredictionServicePackage; public final AppsFilter appsFilter; + public final ComponentResolver componentResolver; public final PackageManagerService service; Snapshot(int type) { @@ -1850,6 +1854,7 @@ public class PackageManagerService extends IPackageManager.Stub : new ApplicationInfo(mAndroidApplication); appPredictionServicePackage = mAppPredictionServicePackage; appsFilter = mAppsFilter.snapshot(); + componentResolver = mComponentResolver.snapshot(); } else if (type == Snapshot.LIVE) { settings = mSettings; isolatedOwners = mIsolatedOwners; @@ -1866,6 +1871,7 @@ public class PackageManagerService extends IPackageManager.Stub androidApplication = mAndroidApplication; appPredictionServicePackage = mAppPredictionServicePackage; appsFilter = mAppsFilter; + componentResolver = mComponentResolver; } else { throw new IllegalArgumentException(); } @@ -1955,8 +1961,8 @@ public class PackageManagerService extends IPackageManager.Stub int callingUid); ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent, String resolvedType, int flags, int sourceUserId); - ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter, int sourceUserId, - int targetUserId); + ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter, + int sourceUserId, int targetUserId); ResolveInfo queryCrossProfileIntents(List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType, int flags, int sourceUserId, boolean matchInCurrentProfile); @@ -2113,6 +2119,7 @@ public class PackageManagerService extends IPackageManager.Stub mInstantAppRegistry = args.instantAppRegistry; mLocalAndroidApplication = args.androidApplication; mAppsFilter = args.appsFilter; + mComponentResolver = args.componentResolver; mAppPredictionServicePackage = args.appPredictionServicePackage; @@ -2123,7 +2130,6 @@ public class PackageManagerService extends IPackageManager.Stub mContext = args.service.mContext; mInjector = args.service.mInjector; mApexManager = args.service.mApexManager; - mComponentResolver = args.service.mComponentResolver; mInstantAppResolverConnection = args.service.mInstantAppResolverConnection; mDefaultAppProvider = args.service.mDefaultAppProvider; mDomainVerificationManager = args.service.mDomainVerificationManager; @@ -2510,8 +2516,8 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a); AndroidPackage pkg = a == null ? null : mPackages.get(a.getPackageName()); + PackageSetting ps = a == null ? null : mSettings.getPackageLPr(a.getPackageName()); if (pkg != null && mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) { - PackageSetting ps = mSettings.getPackageLPr(component.getPackageName()); if (ps == null) return null; if (shouldFilterApplicationLocked( ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) { @@ -2521,8 +2527,8 @@ public class PackageManagerService extends IPackageManager.Stub a, flags, ps.readUserState(userId), userId, ps); } if (resolveComponentName().equals(component)) { - return PackageParser.generateActivityInfo( - mResolveActivity, flags, new PackageUserState(), userId); + return generateDelegateActivityInfo(pkg, ps, new PackageUserState(), + mResolveActivity, flags, userId); } return null; } @@ -2859,8 +2865,8 @@ public class PackageManagerService extends IPackageManager.Stub } if (result == null) { result = new CrossProfileDomainInfo(); - result.resolveInfo = createForwardingResolveInfoUnchecked(new IntentFilter(), - sourceUserId, parentUserId); + result.resolveInfo = createForwardingResolveInfoUnchecked( + new WatchedIntentFilter(), sourceUserId, parentUserId); } result.highestApprovalLevel = Math.max(mDomainVerificationManager @@ -3168,8 +3174,8 @@ public class PackageManagerService extends IPackageManager.Stub return result; } final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo); - ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo( - instantAppInstallerActivity(), 0, ps.readUserState(userId), userId); + ephemeralInstaller.activityInfo = generateDelegateActivityInfo(ps.getPkg(), ps, + ps.readUserState(userId), instantAppInstallerActivity(), 0 /*flags*/, userId); ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; // add a non-generic filter @@ -3253,7 +3259,7 @@ public class PackageManagerService extends IPackageManager.Stub ai.flags = ps.pkgFlags; ai.privateFlags = ps.pkgPrivateFlags; pi.applicationInfo = - PackageParser.generateApplicationInfo(ai, flags, state, userId); + PackageInfoUtils.generateApplicationInfo(p, flags, state, userId, ps); if (DEBUG_PACKAGE_INFO) Log.v(TAG, "ps.pkg is n/a for [" + ps.name + "]. Provides a minimum info."); @@ -3369,6 +3375,19 @@ public class PackageManagerService extends IPackageManager.Stub return getInstalledPackagesBody(flags, userId, callingUid); } + private static ActivityInfo generateDelegateActivityInfo(@Nullable AndroidPackage pkg, + @Nullable PackageSetting ps, @NonNull PackageUserState state, + @Nullable ActivityInfo activity, int flags, int userId) { + if (activity == null || pkg == null + || !checkUseInstalledOrHidden(pkg, ps, state, flags)) { + return null; + } + final ActivityInfo info = new ActivityInfo(activity); + info.applicationInfo = + PackageInfoUtils.generateApplicationInfo(pkg, flags, state, userId, ps); + return info; + } + public ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId, int callingUid) { // writer @@ -3455,15 +3474,15 @@ public class PackageManagerService extends IPackageManager.Stub for (int i = resultTargetUser.size() - 1; i >= 0; i--) { if ((resultTargetUser.get(i).activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SUSPENDED) == 0) { - return createForwardingResolveInfoUnchecked(filter, sourceUserId, - targetUserId); + return createForwardingResolveInfoUnchecked(filter, + sourceUserId, targetUserId); } } } return null; } - public ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter, + public ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter, int sourceUserId, int targetUserId) { ResolveInfo forwardingResolveInfo = new ResolveInfo(); final long ident = Binder.clearCallingIdentity(); @@ -3493,7 +3512,7 @@ public class PackageManagerService extends IPackageManager.Stub forwardingResolveInfo.preferredOrder = 0; forwardingResolveInfo.match = 0; forwardingResolveInfo.isDefault = true; - forwardingResolveInfo.filter = filter; + forwardingResolveInfo.filter = new IntentFilter(filter.getIntentFilter()); forwardingResolveInfo.targetUserId = targetUserId; return forwardingResolveInfo; } @@ -5693,8 +5712,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int optional, - @Checksum.Type int required, @Nullable List trustedInstallers, + @Checksum.TypeMask int optional, + @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId) { requestChecksumsInternal(packageName, includeSplits, optional, required, trustedInstallers, onChecksumsReadyListener, userId, mInjector.getBackgroundExecutor(), @@ -5702,7 +5721,7 @@ public class PackageManagerService extends IPackageManager.Stub } private void requestChecksumsInternal(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int optional, @Checksum.Type int required, + @Checksum.TypeMask int optional, @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler) { @@ -6130,6 +6149,7 @@ public class PackageManagerService extends IPackageManager.Stub mInstantAppRegistry.registerObserver(mWatcher); mSettings.registerObserver(mWatcher); mIsolatedOwners.registerObserver(mWatcher); + mComponentResolver.registerObserver(mWatcher); // If neither "build" attribute is true then this may be a mockito test, and verification // can fail as a false positive. Watchable.verifyWatchedAttributes(this, mWatcher, !(mIsEngBuild || mIsUserDebugBuild)); @@ -9443,6 +9463,15 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void setLastChosenActivity(Intent intent, String resolvedType, int flags, IntentFilter filter, int match, ComponentName activity) { + setLastChosenActivity(intent, resolvedType, flags, + new WatchedIntentFilter(filter), match, activity); + } + + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public void setLastChosenActivity(Intent intent, String resolvedType, int flags, + WatchedIntentFilter filter, int match, ComponentName activity) { if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return; } @@ -9463,7 +9492,7 @@ public class PackageManagerService extends IPackageManager.Stub findPreferredActivityNotLocked( intent, resolvedType, flags, query, 0, false, true, false, userId); // Add the new activity as the last chosen for this filter - addPreferredActivityInternal(filter, match, null, activity, false, userId, + addPreferredActivity(filter, match, null, activity, false, userId, "Setting last chosen", false); } @@ -10181,12 +10210,6 @@ public class PackageManagerService extends IPackageManager.Stub resolvedType, flags, sourceUserId); } - private ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter, - int sourceUserId, int targetUserId) { - return liveComputer().createForwardingResolveInfoUnchecked(filter, - sourceUserId, targetUserId); - } - @Override public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics, String[] specificTypes, Intent intent, @@ -16463,7 +16486,7 @@ public class PackageManagerService extends IPackageManager.Stub return new ParceledListSlice<IntentFilter>(result) { @Override protected void writeElement(IntentFilter parcelable, Parcel dest, int callFlags) { - // IntentFilter has final Parcelable methods, so redirect to the subclass + // WatchedIntentFilter has final Parcelable methods, so redirect to the subclass ((ParsedIntentInfo) parcelable).writeIntentInfoToParcel(dest, callFlags); } @@ -21950,11 +21973,14 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity, int userId, boolean removeExisting) { - addPreferredActivityInternal(filter, match, set, activity, true, userId, + addPreferredActivity(new WatchedIntentFilter(filter), match, set, activity, true, userId, "Adding preferred", removeExisting); } - private void addPreferredActivityInternal(IntentFilter filter, int match, + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public void addPreferredActivity(WatchedIntentFilter filter, int match, ComponentName[] set, ComponentName activity, boolean always, int userId, String opname, boolean removeExisting) { // writer @@ -22020,6 +22046,15 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity, int userId) { + replacePreferredActivity(new WatchedIntentFilter(filter), match, + set, activity, userId); + } + + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public void replacePreferredActivity(WatchedIntentFilter filter, int match, + ComponentName[] set, ComponentName activity, int userId) { if (filter.countActions() != 1) { throw new IllegalArgumentException( "replacePreferredActivity expects filter to have only 1 action."); @@ -22092,7 +22127,7 @@ public class PackageManagerService extends IPackageManager.Stub } } } - addPreferredActivityInternal(filter, match, set, activity, true, userId, + addPreferredActivity(filter, match, set, activity, true, userId, "Replacing preferred", false); } @@ -22199,6 +22234,22 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int getPreferredActivities(List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { + List<WatchedIntentFilter> temp = + WatchedIntentFilter.toWatchedIntentFilterList(outFilters); + final int result = getPreferredActivitiesInternal( + temp, outActivities, packageName); + outFilters.clear(); + for (int i = 0; i < temp.size(); i++) { + outFilters.add(temp.get(i).getIntentFilter()); + } + return result; + } + + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public int getPreferredActivitiesInternal(List<WatchedIntentFilter> outFilters, + List<ComponentName> outActivities, String packageName) { if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return 0; } @@ -22215,7 +22266,7 @@ public class PackageManagerService extends IPackageManager.Stub || (pa.mPref.mComponent.getPackageName().equals(packageName) && pa.mPref.mAlways)) { if (outFilters != null) { - outFilters.add(new IntentFilter(pa)); + outFilters.add(new WatchedIntentFilter(pa.getIntentFilter())); } if (outActivities != null) { outActivities.add(pa.mPref.mComponent); @@ -22231,6 +22282,14 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity, int userId) { + addPersistentPreferredActivity(new WatchedIntentFilter(filter), activity, userId); + } + + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public void addPersistentPreferredActivity(WatchedIntentFilter filter, ComponentName activity, + int userId) { int callingUid = Binder.getCallingUid(); if (callingUid != Process.SYSTEM_UID) { throw new SecurityException( @@ -22474,6 +22533,15 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage, int sourceUserId, int targetUserId, int flags) { + addCrossProfileIntentFilter(new WatchedIntentFilter(intentFilter), ownerPackage, + sourceUserId, targetUserId, flags); + } + + /** + * Variant that takes a {@link WatchedIntentFilter} + */ + public void addCrossProfileIntentFilter(WatchedIntentFilter intentFilter, String ownerPackage, + int sourceUserId, int targetUserId, int flags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); int callingUid = Binder.getCallingUid(); @@ -22603,8 +22671,8 @@ public class PackageManagerService extends IPackageManager.Stub return liveComputer().getHomeIntent(); } - private IntentFilter getHomeFilter() { - IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN); + private WatchedIntentFilter getHomeFilter() { + WatchedIntentFilter filter = new WatchedIntentFilter(Intent.ACTION_MAIN); filter.addCategory(Intent.CATEGORY_HOME); filter.addCategory(Intent.CATEGORY_DEFAULT); return filter; @@ -23604,7 +23672,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt( mContext.getContentResolver(), android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1; - PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled); + ParsingPackageUtils.setCompatibilityModeEnabled(compatibilityModeEnabled); if (DEBUG_SETTINGS) { Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); @@ -26019,18 +26087,29 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String[] getNamesForUids(int[] uids) throws RemoteException { - if (uids == null || uids.length == 0) { - return null; - } - final String[] names = PackageManagerService.this.getNamesForUids(uids); - final String[] results = (names != null) ? names : new String[uids.length]; - // massage results so they can be parsed by the native binder - for (int i = results.length - 1; i >= 0; --i) { - if (results[i] == null) { - results[i] = ""; + String[] names = null; + String[] results = null; + try { + if (uids == null || uids.length == 0) { + return null; } + names = PackageManagerService.this.getNamesForUids(uids); + results = (names != null) ? names : new String[uids.length]; + // massage results so they can be parsed by the native binder + for (int i = results.length - 1; i >= 0; --i) { + if (results[i] == null) { + results[i] = ""; + } + } + return results; + } catch (Throwable t) { + // STOPSHIP(186558987): revert addition of try/catch/log + Slog.e(TAG, "uids: " + Arrays.toString(uids)); + Slog.e(TAG, "names: " + Arrays.toString(names)); + Slog.e(TAG, "results: " + Arrays.toString(results)); + Slog.e(TAG, "throwing exception", t); + throw t; } - return results; } // NB: this differentiates between preloads and sideloads @@ -27225,7 +27304,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void requestChecksums(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int optional, @Checksum.Type int required, + @Checksum.TypeMask int optional, @Checksum.TypeMask int required, @Nullable List trustedInstallers, @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler) { diff --git a/services/core/java/com/android/server/pm/PersistentPreferredActivity.java b/services/core/java/com/android/server/pm/PersistentPreferredActivity.java index a015456f1485..ad3950c906ef 100644 --- a/services/core/java/com/android/server/pm/PersistentPreferredActivity.java +++ b/services/core/java/com/android/server/pm/PersistentPreferredActivity.java @@ -23,13 +23,14 @@ import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import com.android.internal.util.XmlUtils; +import com.android.server.utils.SnapshotCache; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -class PersistentPreferredActivity extends IntentFilter { +class PersistentPreferredActivity extends WatchedIntentFilter { private static final String ATTR_NAME = "name"; // component name private static final String ATTR_FILTER = "filter"; // filter private static final String ATTR_SET_BY_DPM = "set-by-dpm"; // set by DPM @@ -41,10 +42,38 @@ class PersistentPreferredActivity extends IntentFilter { final ComponentName mComponent; final boolean mIsSetByDpm; + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<PersistentPreferredActivity> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<PersistentPreferredActivity>(this, this) { + @Override + public PersistentPreferredActivity createSnapshot() { + PersistentPreferredActivity s = new PersistentPreferredActivity(mSource); + s.seal(); + return s; + }}; + } + PersistentPreferredActivity(IntentFilter filter, ComponentName activity, boolean isSetByDpm) { super(filter); mComponent = activity; mIsSetByDpm = isSetByDpm; + mSnapshot = makeCache(); + } + + PersistentPreferredActivity(WatchedIntentFilter filter, ComponentName activity, + boolean isSetByDpm) { + this(filter.mFilter, activity, isSetByDpm); + } + + // Copy constructor used only to create a snapshot + private PersistentPreferredActivity(PersistentPreferredActivity f) { + super(f); + mComponent = f.mComponent; + mIsSetByDpm = f.mIsSetByDpm; + mSnapshot = new SnapshotCache.Sealed(); } PersistentPreferredActivity(TypedXmlPullParser parser) @@ -79,27 +108,36 @@ class PersistentPreferredActivity extends IntentFilter { } } if (tagName.equals(ATTR_FILTER)) { - readFromXml(parser); + mFilter.readFromXml(parser); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Missing element filter at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); } + mSnapshot = makeCache(); } public void writeToXml(TypedXmlSerializer serializer) throws IOException { serializer.attribute(null, ATTR_NAME, mComponent.flattenToShortString()); serializer.attributeBoolean(null, ATTR_SET_BY_DPM, mIsSetByDpm); serializer.startTag(null, ATTR_FILTER); - super.writeToXml(serializer); + mFilter.writeToXml(serializer); serializer.endTag(null, ATTR_FILTER); } + public IntentFilter getIntentFilter() { + return mFilter; + } + @Override public String toString() { return "PersistentPreferredActivity{0x" + Integer.toHexString(System.identityHashCode(this)) + " " + mComponent.flattenToShortString() + ", mIsSetByDpm=" + mIsSetByDpm + "}"; } + + public PersistentPreferredActivity snapshot() { + return mSnapshot.snapshot(); + } } diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java index 2b11a4297835..bfddaea0dd75 100644 --- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java +++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java @@ -21,6 +21,7 @@ import android.content.IntentFilter; import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; +import com.android.server.utils.SnapshotCache; public class PersistentPreferredIntentResolver extends WatchedIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity> @@ -32,7 +33,7 @@ public class PersistentPreferredIntentResolver @Override protected IntentFilter getIntentFilter(@NonNull PersistentPreferredActivity input) { - return input; + return input.getIntentFilter(); } @Override @@ -40,14 +41,40 @@ public class PersistentPreferredIntentResolver return packageName.equals(filter.mComponent.getPackageName()); } + public PersistentPreferredIntentResolver() { + super(); + mSnapshot = makeCache(); + } + + // Take the snapshot of F + protected PersistentPreferredActivity snapshot(PersistentPreferredActivity f) { + return (f == null) ? null : f.snapshot(); + } + + // Copy constructor used only to create a snapshot. + private PersistentPreferredIntentResolver(PersistentPreferredIntentResolver f) { + copyFrom(f); + mSnapshot = new SnapshotCache.Sealed(); + } + + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<PersistentPreferredIntentResolver> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<PersistentPreferredIntentResolver>(this, this) { + @Override + public PersistentPreferredIntentResolver createSnapshot() { + return new PersistentPreferredIntentResolver(mSource); + }}; + } + /** * Return a snapshot of the current object. The snapshot is a read-only copy suitable * for read-only methods. * @return A snapshot of the current object. */ public PersistentPreferredIntentResolver snapshot() { - PersistentPreferredIntentResolver result = new PersistentPreferredIntentResolver(); - result.copyFrom(this); - return result; + return mSnapshot.snapshot(); } } diff --git a/services/core/java/com/android/server/pm/PreferredActivity.java b/services/core/java/com/android/server/pm/PreferredActivity.java index 4e1dcb27111d..5bc915f2c1c4 100644 --- a/services/core/java/com/android/server/pm/PreferredActivity.java +++ b/services/core/java/com/android/server/pm/PreferredActivity.java @@ -23,32 +23,62 @@ import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import com.android.internal.util.XmlUtils; +import com.android.server.utils.SnapshotCache; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.io.PrintWriter; -class PreferredActivity extends IntentFilter implements PreferredComponent.Callbacks { +class PreferredActivity extends WatchedIntentFilter implements PreferredComponent.Callbacks { private static final String TAG = "PreferredActivity"; private static final boolean DEBUG_FILTERS = false; final PreferredComponent mPref; + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<PreferredActivity> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<PreferredActivity>(this, this) { + @Override + public PreferredActivity createSnapshot() { + PreferredActivity s = new PreferredActivity(mSource); + s.seal(); + return s; + }}; + } + PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity, boolean always) { super(filter); mPref = new PreferredComponent(this, match, set, activity, always); + mSnapshot = makeCache(); + } + + PreferredActivity(WatchedIntentFilter filter, int match, ComponentName[] set, + ComponentName activity, boolean always) { + this(filter.mFilter, match, set, activity, always); + } + + // Copy constructor used only to create a snapshot + private PreferredActivity(PreferredActivity f) { + super(f); + mPref = f.mPref; + mSnapshot = new SnapshotCache.Sealed(); } PreferredActivity(TypedXmlPullParser parser) throws XmlPullParserException, IOException { mPref = new PreferredComponent(this, parser); + mSnapshot = makeCache(); } public void writeToXml(TypedXmlSerializer serializer, boolean full) throws IOException { mPref.writeToXml(serializer, full); serializer.startTag(null, "filter"); - super.writeToXml(serializer); + mFilter.writeToXml(serializer); serializer.endTag(null, "filter"); } @@ -58,7 +88,7 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb if (DEBUG_FILTERS) { Log.i(TAG, "Starting to parse filter..."); } - readFromXml(parser); + mFilter.readFromXml(parser); if (DEBUG_FILTERS) { Log.i(TAG, "Finished filter: depth=" + parser.getDepth() + " tag=" + parser.getName()); @@ -71,9 +101,17 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb return true; } + public void dumpPref(PrintWriter out, String prefix, PreferredActivity filter) { + mPref.dump(out, prefix, filter); + } + @Override public String toString() { return "PreferredActivity{0x" + Integer.toHexString(System.identityHashCode(this)) + " " + mPref.mComponent.flattenToShortString() + "}"; } + + public PreferredActivity snapshot() { + return mSnapshot.snapshot(); + } } diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java index 10a6b3f69fde..0aca6eec25fc 100644 --- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java +++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java @@ -21,6 +21,7 @@ import android.content.IntentFilter; import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; +import com.android.server.utils.SnapshotCache; import java.io.PrintWriter; import java.util.ArrayList; @@ -46,7 +47,7 @@ public class PreferredIntentResolver @Override protected IntentFilter getIntentFilter(@NonNull PreferredActivity input) { - return input; + return input.getIntentFilter(); } public boolean shouldAddPreferredActivity(PreferredActivity pa) { @@ -69,14 +70,40 @@ public class PreferredIntentResolver return true; } + public PreferredIntentResolver() { + super(); + mSnapshot = makeCache(); + } + + // Take the snapshot of F + protected PreferredActivity snapshot(PreferredActivity f) { + return (f == null) ? null : f.snapshot(); + } + + // Copy constructor used only to create a snapshot. + private PreferredIntentResolver(PreferredIntentResolver f) { + copyFrom(f); + mSnapshot = new SnapshotCache.Sealed(); + } + + // The cache for snapshots, so they are not rebuilt if the base object has not + // changed. + final SnapshotCache<PreferredIntentResolver> mSnapshot; + + private SnapshotCache makeCache() { + return new SnapshotCache<PreferredIntentResolver>(this, this) { + @Override + public PreferredIntentResolver createSnapshot() { + return new PreferredIntentResolver(mSource); + }}; + } + /** * Return a snapshot of the current object. The snapshot is a read-only copy suitable * for read-only methods. * @return A snapshot of the current object. */ public PreferredIntentResolver snapshot() { - PreferredIntentResolver result = new PreferredIntentResolver(); - result.copyFrom(this); - return result; + return mSnapshot.snapshot(); } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index b985229d3116..1b8eee3925a5 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3026,8 +3026,9 @@ public final class Settings implements Watchable, Snappable { = ps.pkg.getPreferredActivityFilters(); for (int i=0; i<intents.size(); i++) { Pair<String, ParsedIntentInfo> pair = intents.get(i); - applyDefaultPreferredActivityLPw(pmInternal, pair.second, new ComponentName( - ps.name, pair.first), userId); + applyDefaultPreferredActivityLPw(pmInternal, + new WatchedIntentFilter(pair.second), + new ComponentName(ps.name, pair.first), userId); } } } @@ -3097,7 +3098,7 @@ public final class Settings implements Watchable, Snappable { } static void removeFilters(@NonNull PreferredIntentResolver pir, - @NonNull IntentFilter filter, @NonNull List<PreferredActivity> existing) { + @NonNull WatchedIntentFilter filter, @NonNull List<PreferredActivity> existing) { if (PackageManagerService.DEBUG_PREFERRED) { Slog.i(TAG, existing.size() + " preferred matches for:"); filter.dump(new LogPrinter(Log.INFO, TAG), " "); @@ -3112,8 +3113,8 @@ public final class Settings implements Watchable, Snappable { } } - private void applyDefaultPreferredActivityLPw( - PackageManagerInternal pmInternal, IntentFilter tmpPa, ComponentName cn, int userId) { + private void applyDefaultPreferredActivityLPw(PackageManagerInternal pmInternal, + WatchedIntentFilter tmpPa, ComponentName cn, int userId) { // The initial preferences only specify the target activity // component and intent-filter, not the set of matches. So we // now need to query for the matches to build the correct @@ -3284,7 +3285,7 @@ public final class Settings implements Watchable, Snappable { haveNonSys = null; } if (haveAct && haveNonSys == null) { - IntentFilter filter = new IntentFilter(); + WatchedIntentFilter filter = new WatchedIntentFilter(); if (intent.getAction() != null) { filter.addAction(intent.getAction()); } diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 3dfb835eeb45..1bd9e5eedb84 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -319,7 +319,7 @@ class ShortcutPackage extends ShortcutPackageItem { } final Icon icon = si.getIcon(); if (icon != null && icon.getType() != Icon.TYPE_BITMAP - && icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) { + && icon.getType() != Icon.TYPE_ADAPTIVE_BITMAP) { continue; } if (icon == null && !si.hasIconFile()) { diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java index 61f51e36202c..b89dbdc863e0 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java +++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java @@ -417,7 +417,7 @@ public class PackageInfoUtils { * Returns true if the package is installed and not hidden, or if the caller * explicitly wanted all uninstalled and hidden packages as well. */ - private static boolean checkUseInstalledOrHidden(AndroidPackage pkg, + public static boolean checkUseInstalledOrHidden(AndroidPackage pkg, PackageSetting pkgSetting, PackageUserState state, @PackageManager.PackageInfoFlags int flags) { // Returns false if the package is hidden system app until installed. diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index f0c96e18930a..32ad702ceff5 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -31,6 +31,7 @@ import android.telecom.DefaultDialerManager; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; import android.util.IntArray; import android.util.Slog; @@ -44,6 +45,9 @@ import com.android.server.SystemService; import com.android.server.pm.UserManagerService; import com.android.server.pm.permission.LegacyPermissionManagerInternal; +import java.util.ArrayList; +import java.util.List; + /** * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup * to run in the system-server process so once it is loaded into memory it will stay running. @@ -208,13 +212,23 @@ public class TelecomLoaderService extends SystemService { return null; } } + SubscriptionManager subscriptionManager = + mContext.getSystemService(SubscriptionManager.class); + if (subscriptionManager == null) { + return null; + } TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); - PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId); - if (phoneAccount != null) { - return new String[]{phoneAccount.getComponentName().getPackageName()}; + List<String> packages = new ArrayList<>(); + int[] subIds = subscriptionManager.getActiveSubscriptionIdList(); + for (int subId : subIds) { + PhoneAccountHandle phoneAccount = + telecomManager.getSimCallManagerForSubscription(subId); + if (phoneAccount != null) { + packages.add(phoneAccount.getComponentName().getPackageName()); + } } - return null; + return packages.toArray(new String[] {}); }); } diff --git a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java index c8c828f10ad3..27b50d892144 100644 --- a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java +++ b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java @@ -89,8 +89,6 @@ public final class MetricsTimeZoneDetectorState { @Nullable TelephonyTimeZoneSuggestion latestTelephonySuggestion, @Nullable GeolocationTimeZoneSuggestion latestGeolocationSuggestion) { - // TODO(b/172934905) Add logic to canonicalize the time zone IDs to Android's preferred IDs - // so that the ordinals will match even when the ID is not identical, just equivalent. int deviceTimeZoneIdOrdinal = tzIdOrdinalGenerator.ordinal(Objects.requireNonNull(deviceTimeZoneId)); MetricsTimeZoneSuggestion latestObfuscatedManualSuggestion = diff --git a/services/core/java/com/android/server/timezonedetector/OrdinalGenerator.java b/services/core/java/com/android/server/timezonedetector/OrdinalGenerator.java index a448773c40d5..50875308db7d 100644 --- a/services/core/java/com/android/server/timezonedetector/OrdinalGenerator.java +++ b/services/core/java/com/android/server/timezonedetector/OrdinalGenerator.java @@ -15,9 +15,12 @@ */ package com.android.server.timezonedetector; +import android.annotation.NonNull; import android.util.ArraySet; import java.util.List; +import java.util.Objects; +import java.util.function.Function; /** * A helper class that turns a set of objects into ordinal values, i.e. each object is offered @@ -30,11 +33,19 @@ import java.util.List; class OrdinalGenerator<T> { private final ArraySet<T> mKnownIds = new ArraySet<>(); + private final @NonNull Function<T, T> mCanonicalizationFunction; + + OrdinalGenerator(@NonNull Function<T, T> canonicalizationFunction) { + mCanonicalizationFunction = Objects.requireNonNull(canonicalizationFunction); + } + int ordinal(T object) { - int ordinal = mKnownIds.indexOf(object); + T canonical = mCanonicalizationFunction.apply(object); + + int ordinal = mKnownIds.indexOf(canonical); if (ordinal < 0) { ordinal = mKnownIds.size(); - mKnownIds.add(object); + mKnownIds.add(canonical); } return ordinal; } diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneCanonicalizer.java b/services/core/java/com/android/server/timezonedetector/TimeZoneCanonicalizer.java new file mode 100644 index 000000000000..bdbf60712008 --- /dev/null +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneCanonicalizer.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezonedetector; + +import com.android.i18n.timezone.TimeZoneFinder; + +import java.util.function.Function; + +/** + * Returns preferred time zone ID if {@code timeZoneId} was deprecated. For example, returns + * America/Nuuk for America/Godthab. + */ +final class TimeZoneCanonicalizer implements Function<String, String> { + @Override + public String apply(String timeZoneId) { + String canonicialZoneId = TimeZoneFinder.getInstance().getCountryZonesFinder() + .findCanonicalTimeZoneId(timeZoneId); + + return canonicialZoneId == null ? timeZoneId : canonicialZoneId; + } +} diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java index c34a7d37ba24..ab2a88b44a87 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java @@ -383,7 +383,8 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat bestQualifiedTelephonySuggestion == null ? null : bestQualifiedTelephonySuggestion.suggestion; // A new generator is created each time: we don't want / require consistency. - OrdinalGenerator<String> tzIdOrdinalGenerator = new OrdinalGenerator<>(); + OrdinalGenerator<String> tzIdOrdinalGenerator = + new OrdinalGenerator<>(new TimeZoneCanonicalizer()); return MetricsTimeZoneDetectorState.create( tzIdOrdinalGenerator, getConfigurationInternal(currentUserId), diff --git a/services/core/java/com/android/server/utils/SnapshotCache.java b/services/core/java/com/android/server/utils/SnapshotCache.java index f0fb8b25b402..b4b8835ac026 100644 --- a/services/core/java/com/android/server/utils/SnapshotCache.java +++ b/services/core/java/com/android/server/utils/SnapshotCache.java @@ -57,6 +57,15 @@ public abstract class SnapshotCache<T> extends Watcher{ } /** + * A private constructor that sets fields to null and mSealed to true. This supports + * the Sealed subclass. + */ + public SnapshotCache() { + mSource = null; + mSealed = true; + } + + /** * Notify the object that the source object has changed. If the local object is sealed then * IllegalStateException is thrown. Otherwise, the cache is cleared. */ @@ -93,4 +102,25 @@ public abstract class SnapshotCache<T> extends Watcher{ * @return A snapshot */ public abstract T createSnapshot(); + + /** + * A snapshot cache suitable for sealed snapshots. Attempting to retrieve the + * snapshot will throw an UnsupportedOperationException. + * @param <T> the type of object being cached. This is needed for compilation only. It + * has no effect on execution. + */ + public static class Sealed<T> extends SnapshotCache<T> { + /** + * Create a sealed SnapshotCache that cannot be used to create new snapshots. + */ + public Sealed() { + } + /** + * Provide a concrete implementation of createSnapshot() that throws + * UnsupportedOperationException. + */ + public T createSnapshot() { + throw new UnsupportedOperationException("cannot snapshot a sealed snaphot"); + } + } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 6a1b1069f57c..8f3702ac1a5e 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -91,6 +91,7 @@ import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE; import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED; import static android.content.res.Configuration.EMPTY; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -6618,9 +6619,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void onCancelFixedRotationTransform(int originalDisplayRotation) { - if (this != mDisplayContent.getLastOrientationSource() - || getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED) { - // Only need to handle the activity that should be rotated with display. + if (this != mDisplayContent.getLastOrientationSource()) { + // This activity doesn't affect display rotation. + return; + } + final int requestedOrientation = getRequestedConfigurationOrientation(); + if (requestedOrientation != ORIENTATION_UNDEFINED + && requestedOrientation != mDisplayContent.getConfiguration().orientation) { + // Only need to handle the activity that can be rotated with display or the activity + // has requested the same orientation. return; } @@ -6858,6 +6865,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void resolveOverrideConfiguration(Configuration newParentConfiguration) { + final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration(); + if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED + && newParentConfiguration.assetsSeq > requestedOverrideConfig.assetsSeq) { + requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED; + } super.resolveOverrideConfiguration(newParentConfiguration); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); if (isFixedRotationTransforming()) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index e249e674a174..c6a66c573ada 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -472,6 +472,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** Current sequencing integer of the configuration, for skipping old configurations. */ private int mConfigurationSeq; + + /** Current sequencing integer of the asset changes, for skipping old resources overlays. */ + private int mGlobalAssetsSeq; + // To cache the list of supported system locales private String[] mSupportedSystemLocales = null; @@ -4129,6 +4133,35 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return changes; } + private int increaseAssetConfigurationSeq() { + mGlobalAssetsSeq = Math.max(++mGlobalAssetsSeq, 1); + return mGlobalAssetsSeq; + } + + /** + * Update the asset configuration and increase the assets sequence number. + * @param processes the processes that needs to update the asset configuration, if none + * updates the global configuration for all processes. + */ + public void updateAssetConfiguration(List<WindowProcessController> processes) { + synchronized (mGlobalLock) { + final int assetSeq = increaseAssetConfigurationSeq(); + + // Update the global configuration if the no target processes + if (processes == null) { + Configuration newConfig = new Configuration(); + newConfig.assetsSeq = assetSeq; + updateConfiguration(newConfig); + return; + } + + for (int i = processes.size() - 1; i >= 0; i--) { + final WindowProcessController wpc = processes.get(i); + wpc.updateAssetConfiguration(assetSeq); + } + } + } + void startLaunchPowerMode(@PowerModeReason int reason) { if (mPowerManagerInternal == null) return; mPowerManagerInternal.setPowerMode(Mode.LAUNCH, true); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 9aabdac58f69..2c592d00f90c 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2258,7 +2258,6 @@ class Task extends WindowContainer<WindowContainer> { mTmpPrevBounds.set(getBounds()); final boolean wasInMultiWindowMode = inMultiWindowMode(); final boolean wasInPictureInPicture = inPinnedWindowingMode(); - final int oldOrientation = getOrientation(); super.onConfigurationChanged(newParentConfig); // Only need to update surface size here since the super method will handle updating // surface position. @@ -2301,11 +2300,6 @@ class Task extends WindowContainer<WindowContainer> { mForceNotOrganized = false; } - // Report orientation change such as changing from freeform to fullscreen. - if (oldOrientation != getOrientation()) { - onDescendantOrientationChanged(this); - } - saveLaunchingStateIfNeeded(); final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */); if (taskOrgChanged) { diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 4dc60070d6ec..d59654949a27 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -130,6 +130,12 @@ public class WindowManagerShellCommand extends ShellCommand { return runResetLetterboxStyle(pw); case "set-sandbox-display-apis": return runSandboxDisplayApis(pw); + case "set-multi-window-config": + return runSetMultiWindowConfig(); + case "get-multi-window-config": + return runGetMultiWindowConfig(pw); + case "reset-multi-window-config": + return runResetMultiWindowConfig(); case "reset": return runReset(pw); case "disable-blur": @@ -815,6 +821,80 @@ public class WindowManagerShellCommand extends ShellCommand { return 0; } + private int runSetMultiWindowConfig() { + if (peekNextArg() == null) { + getErrPrintWriter().println("Error: No arguments provided."); + } + int result = 0; + while (peekNextArg() != null) { + String arg = getNextArg(); + switch (arg) { + case "--supportsNonResizable": + result += runSetSupportsNonResizableMultiWindow(); + break; + case "--respectsActivityMinWidthHeight": + result += runSetRespectsActivityMinWidthHeightMultiWindow(); + break; + default: + getErrPrintWriter().println( + "Error: Unrecognized multi window option: " + arg); + return -1; + } + } + return result == 0 ? 0 : -1; + } + + private int runSetSupportsNonResizableMultiWindow() { + final String arg = getNextArg(); + if (!arg.equals("-1") && !arg.equals("0") && !arg.equals("1")) { + getErrPrintWriter().println("Error: a config value of [-1, 0, 1] must be provided as" + + " an argument for supportsNonResizableMultiWindow"); + return -1; + } + final int configValue = Integer.parseInt(arg); + synchronized (mInternal.mAtmService.mGlobalLock) { + mInternal.mAtmService.mSupportsNonResizableMultiWindow = configValue; + } + return 0; + } + + private int runSetRespectsActivityMinWidthHeightMultiWindow() { + final String arg = getNextArg(); + if (!arg.equals("-1") && !arg.equals("0") && !arg.equals("1")) { + getErrPrintWriter().println("Error: a config value of [-1, 0, 1] must be provided as" + + " an argument for respectsActivityMinWidthHeightMultiWindow"); + return -1; + } + final int configValue = Integer.parseInt(arg); + synchronized (mInternal.mAtmService.mGlobalLock) { + mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow = configValue; + } + return 0; + } + + private int runGetMultiWindowConfig(PrintWriter pw) { + synchronized (mInternal.mAtmService.mGlobalLock) { + pw.println("Supports non-resizable in multi window: " + + mInternal.mAtmService.mSupportsNonResizableMultiWindow); + pw.println("Respects activity min width/height in multi window: " + + mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow); + } + return 0; + } + + private int runResetMultiWindowConfig() { + final int supportsNonResizable = mInternal.mContext.getResources().getInteger( + com.android.internal.R.integer.config_supportsNonResizableMultiWindow); + final int respectsActivityMinWidthHeight = mInternal.mContext.getResources().getInteger( + com.android.internal.R.integer.config_respectsActivityMinWidthHeightMultiWindow); + synchronized (mInternal.mAtmService.mGlobalLock) { + mInternal.mAtmService.mSupportsNonResizableMultiWindow = supportsNonResizable; + mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow = + respectsActivityMinWidthHeight; + } + return 0; + } + private void resetLetterboxStyle() { synchronized (mInternal.mGlobalLock) { mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio(); @@ -879,6 +959,9 @@ public class WindowManagerShellCommand extends ShellCommand { // set-sandbox-display-apis mInternal.setSandboxDisplayApis(displayId, /* sandboxDisplayApis= */ true); + // set-multi-window-config + runResetMultiWindowConfig(); + pw.println("Reset all settings for displayId=" + displayId); return 0; } @@ -916,6 +999,7 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" Size Compat Mode."); printLetterboxHelp(pw); + printMultiWindowConfigHelp(pw); pw.println(" reset [-d DISPLAY_ID]"); pw.println(" Reset all override settings."); @@ -969,4 +1053,31 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" get-letterbox-style"); pw.println(" Prints letterbox style configuration."); } + + private void printMultiWindowConfigHelp(PrintWriter pw) { + pw.println(" set-multi-window-config"); + pw.println(" Sets options to determine if activity should be shown in multi window:"); + pw.println(" --supportsNonResizable [configValue]"); + pw.println(" Whether the device supports non-resizable activity in multi window."); + pw.println(" -1: The device doesn't support non-resizable in multi window."); + pw.println(" 0: The device supports non-resizable in multi window only if"); + pw.println(" this is a large screen device."); + pw.println(" 1: The device always supports non-resizable in multi window."); + pw.println(" --respectsActivityMinWidthHeight [configValue]"); + pw.println(" Whether the device checks the activity min width/height to determine "); + pw.println(" if it can be shown in multi window."); + pw.println(" -1: The device ignores the activity min width/height when determining"); + pw.println(" if it can be shown in multi window."); + pw.println(" 0: If this is a small screen, the device compares the activity min"); + pw.println(" width/height with the min multi window modes dimensions"); + pw.println(" the device supports to determine if the activity can be shown in"); + pw.println(" multi window."); + pw.println(" 1: The device always compare the activity min width/height with the"); + pw.println(" min multi window dimensions the device supports to determine if"); + pw.println(" the activity can be shown in multi window."); + pw.println(" get-multi-window-config"); + pw.println(" Prints values of the multi window config options."); + pw.println(" reset-multi-window-config"); + pw.println(" Resets overrides to default values of the multi window config options."); + } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index bac1ab1264ab..26cfbdf80681 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED; import static android.os.Build.VERSION_CODES.Q; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; @@ -1318,6 +1319,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio @Override void resolveOverrideConfiguration(Configuration newParentConfig) { + final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration(); + if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED + && newParentConfig.assetsSeq > requestedOverrideConfig.assetsSeq) { + requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED; + } super.resolveOverrideConfiguration(newParentConfig); final Configuration resolvedConfig = getResolvedOverrideConfiguration(); // Make sure that we don't accidentally override the activity type. @@ -1396,6 +1402,28 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mHasPendingConfigurationChange; } + void updateAssetConfiguration(int assetSeq) { + // Update the process override configuration directly if the process configuration will + // not be override from its activities. + if (!mHasActivities || !mIsActivityConfigOverrideAllowed) { + Configuration overrideConfig = new Configuration(getRequestedOverrideConfiguration()); + overrideConfig.assetsSeq = assetSeq; + onRequestedOverrideConfigurationChanged(overrideConfig); + return; + } + + // Otherwise, we can just update the activity override configuration. + for (int i = mActivities.size() - 1; i >= 0; i--) { + ActivityRecord r = mActivities.get(i); + Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration()); + overrideConfig.assetsSeq = assetSeq; + r.onRequestedOverrideConfigurationChanged(overrideConfig); + if (r.mVisibleRequested) { + r.ensureActivityConfiguration(0, true); + } + } + } + /** * This is called for sending {@link android.app.servertransaction.LaunchActivityItem}. * The caller must call {@link #setLastReportedConfiguration} if the delivered configuration diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 074eeb942377..9de50585bf67 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -7244,6 +7244,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); + checkAllUsersAreAffiliatedWithDevice(); mInjector.binderWithCleanCallingIdentity( () -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo)); } @@ -15736,6 +15737,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); + checkAllUsersAreAffiliatedWithDevice(); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_GLOBAL_PRIVATE_DNS); switch (mode) { diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index 5299547fef67..36c0a677f43a 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -398,6 +398,15 @@ static long elapsedMcs(Duration start, Duration end) { return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count(); } +static uint64_t elapsedUsSinceMonoTs(uint64_t monoTsUs) { + timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) { + return 0; + } + uint64_t nowUs = now.tv_sec * 1000000LL + now.tv_nsec / 1000; + return nowUs - monoTsUs; +} + void IncrementalService::onDump(int fd) { dprintf(fd, "Incremental is %s\n", incfs::enabled() ? "ENABLED" : "DISABLED"); dprintf(fd, "IncFs features: 0x%x\n", int(mIncFs->features())); @@ -415,6 +424,8 @@ void IncrementalService::onDump(int fd) { } else { dprintf(fd, " mountId: %d\n", mnt.mountId); dprintf(fd, " root: %s\n", mnt.root.c_str()); + const auto metricsInstanceName = path::basename(ifs->root); + dprintf(fd, " metrics instance name: %s\n", path::c_str(metricsInstanceName).get()); dprintf(fd, " nextStorageDirNo: %d\n", mnt.nextStorageDirNo.load()); dprintf(fd, " flags: %d\n", int(mnt.flags)); if (mnt.startLoadingTs.time_since_epoch() == Clock::duration::zero()) { @@ -444,6 +455,45 @@ void IncrementalService::onDump(int fd) { dprintf(fd, " kind: %s\n", toString(bind.kind)); } dprintf(fd, " }\n"); + + dprintf(fd, " incfsMetrics: {\n"); + const auto incfsMetrics = mIncFs->getMetrics(metricsInstanceName); + if (incfsMetrics) { + dprintf(fd, " readsDelayedMin: %d\n", incfsMetrics.value().readsDelayedMin); + dprintf(fd, " readsDelayedMinUs: %lld\n", + (long long)incfsMetrics.value().readsDelayedMinUs); + dprintf(fd, " readsDelayedPending: %d\n", + incfsMetrics.value().readsDelayedPending); + dprintf(fd, " readsDelayedPendingUs: %lld\n", + (long long)incfsMetrics.value().readsDelayedPendingUs); + dprintf(fd, " readsFailedHashVerification: %d\n", + incfsMetrics.value().readsFailedHashVerification); + dprintf(fd, " readsFailedOther: %d\n", incfsMetrics.value().readsFailedOther); + dprintf(fd, " readsFailedTimedOut: %d\n", + incfsMetrics.value().readsFailedTimedOut); + } else { + dprintf(fd, " Metrics not available. Errno: %d\n", errno); + } + dprintf(fd, " }\n"); + + const auto lastReadError = mIncFs->getLastReadError(ifs->control); + const auto errorNo = errno; + dprintf(fd, " lastReadError: {\n"); + if (lastReadError) { + if (lastReadError->timestampUs == 0) { + dprintf(fd, " No read errors.\n"); + } else { + dprintf(fd, " fileId: %s\n", + IncFsWrapper::toString(lastReadError->id).c_str()); + dprintf(fd, " time: %llu microseconds ago\n", + (unsigned long long)elapsedUsSinceMonoTs(lastReadError->timestampUs)); + dprintf(fd, " blockIndex: %d\n", lastReadError->block); + dprintf(fd, " errno: %d\n", lastReadError->errorNo); + } + } else { + dprintf(fd, " Info not available. Errno: %d\n", errorNo); + } + dprintf(fd, " }\n"); } dprintf(fd, " }\n"); } @@ -582,7 +632,7 @@ StorageId IncrementalService::createStorage(std::string_view mountPoint, if (!mkdirOrLog(path::join(backing, ".incomplete"), 0777)) { return kInvalidStorageId; } - auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel); + auto status = mVold->mountIncFs(backing, mountTarget, 0, mountKey, &controlParcel); if (!status.isOk()) { LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8(); return kInvalidStorageId; @@ -1590,9 +1640,10 @@ void IncrementalService::mountExistingImages( bool IncrementalService::mountExistingImage(std::string_view root) { auto mountTarget = path::join(root, constants().mount); const auto backing = path::join(root, constants().backing); + std::string mountKey(path::basename(path::dirname(mountTarget))); IncrementalFileSystemControlParcel controlParcel; - auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel); + auto status = mVold->mountIncFs(backing, mountTarget, 0, mountKey, &controlParcel); if (!status.isOk()) { LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8(); return false; diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp index 0755a22ab2ea..68a28b25b2a4 100644 --- a/services/incremental/ServiceWrappers.cpp +++ b/services/incremental/ServiceWrappers.cpp @@ -43,8 +43,9 @@ public: ~RealVoldService() = default; binder::Status mountIncFs( const std::string& backingPath, const std::string& targetDir, int32_t flags, + const std::string& sysfsName, os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final { - return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return); + return mInterface->mountIncFs(backingPath, targetDir, flags, sysfsName, _aidl_return); } binder::Status unmountIncFs(const std::string& dir) const final { return mInterface->unmountIncFs(dir); @@ -261,6 +262,12 @@ public: return cb(control, id); }); } + std::optional<Metrics> getMetrics(std::string_view sysfsName) const final { + return incfs::getMetrics(sysfsName); + } + std::optional<LastReadError> getLastReadError(const Control& control) const final { + return incfs::getLastReadError(control); + } }; static JNIEnv* getOrAttachJniEnv(JavaVM* jvm); diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h index 78e9589e63ff..c0ef7ba5c85b 100644 --- a/services/incremental/ServiceWrappers.h +++ b/services/incremental/ServiceWrappers.h @@ -51,6 +51,7 @@ public: virtual ~VoldServiceWrapper() = default; virtual binder::Status mountIncFs( const std::string& backingPath, const std::string& targetDir, int32_t flags, + const std::string& sysfsName, os::incremental::IncrementalFileSystemControlParcel* result) const = 0; virtual binder::Status unmountIncFs(const std::string& dir) const = 0; virtual binder::Status bindMount(const std::string& sourceDir, @@ -79,6 +80,8 @@ public: using UniqueFd = incfs::UniqueFd; using WaitResult = incfs::WaitResult; using Features = incfs::Features; + using Metrics = incfs::Metrics; + using LastReadError = incfs::LastReadError; using ExistingMountCallback = android::base::function_ref< void(std::string_view root, std::string_view backingDir, @@ -124,6 +127,8 @@ public: const = 0; virtual ErrorCode forEachFile(const Control& control, FileCallback cb) const = 0; virtual ErrorCode forEachIncompleteFile(const Control& control, FileCallback cb) const = 0; + virtual std::optional<Metrics> getMetrics(std::string_view sysfsName) const = 0; + virtual std::optional<LastReadError> getLastReadError(const Control& control) const = 0; }; class AppOpsManagerWrapper { diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp index 68586a89ff07..da7f0db5efc1 100644 --- a/services/incremental/test/IncrementalServiceTest.cpp +++ b/services/incremental/test/IncrementalServiceTest.cpp @@ -49,9 +49,9 @@ namespace android::os::incremental { class MockVoldService : public VoldServiceWrapper { public: - MOCK_CONST_METHOD4(mountIncFs, + MOCK_CONST_METHOD5(mountIncFs, binder::Status(const std::string& backingPath, const std::string& targetDir, - int32_t flags, + int32_t flags, const std::string& sysfsName, IncrementalFileSystemControlParcel* _aidl_return)); MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir)); MOCK_CONST_METHOD2(bindMount, @@ -62,16 +62,16 @@ public: bool, bool)); void mountIncFsFails() { - ON_CALL(*this, mountIncFs(_, _, _, _)) + ON_CALL(*this, mountIncFs(_, _, _, _, _)) .WillByDefault( Return(binder::Status::fromExceptionCode(1, String8("failed to mount")))); } void mountIncFsInvalidControlParcel() { - ON_CALL(*this, mountIncFs(_, _, _, _)) + ON_CALL(*this, mountIncFs(_, _, _, _, _)) .WillByDefault(Invoke(this, &MockVoldService::getInvalidControlParcel)); } void mountIncFsSuccess() { - ON_CALL(*this, mountIncFs(_, _, _, _)) + ON_CALL(*this, mountIncFs(_, _, _, _, _)) .WillByDefault(Invoke(this, &MockVoldService::incFsSuccess)); } void bindMountFails() { @@ -93,12 +93,14 @@ public: } binder::Status getInvalidControlParcel(const std::string& imagePath, const std::string& targetDir, int32_t flags, + const std::string& sysfsName, IncrementalFileSystemControlParcel* _aidl_return) { _aidl_return = {}; return binder::Status::ok(); } binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir, - int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) { + int32_t flags, const std::string& sysfsName, + IncrementalFileSystemControlParcel* _aidl_return) { _aidl_return->pendingReads.reset(base::unique_fd(dup(STDIN_FILENO))); _aidl_return->cmd.reset(base::unique_fd(dup(STDIN_FILENO))); _aidl_return->log.reset(base::unique_fd(dup(STDIN_FILENO))); @@ -414,6 +416,8 @@ public: const std::vector<PerUidReadTimeouts>& perUidReadTimeouts)); MOCK_CONST_METHOD2(forEachFile, ErrorCode(const Control& control, FileCallback cb)); MOCK_CONST_METHOD2(forEachIncompleteFile, ErrorCode(const Control& control, FileCallback cb)); + MOCK_CONST_METHOD1(getMetrics, std::optional<Metrics>(std::string_view path)); + MOCK_CONST_METHOD1(getLastReadError, std::optional<LastReadError>(const Control& control)); MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); diff --git a/services/net/Android.bp b/services/net/Android.bp index 800f7addbd65..f92db86bb880 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -52,7 +52,8 @@ java_library { libs: [ "unsupportedappusage", "framework-wifi-util-lib", - "framework-connectivity" + "framework-connectivity", + "modules-utils-build_system", ], static_libs: [ // All the classes in netd_aidl_interface must be jarjar so they do not conflict with the @@ -60,6 +61,7 @@ java_library { "netd_aidl_interface-V3-java", "netlink-client", "networkstack-client", + "modules-utils-build_system", ], apex_available: [ "com.android.wifi", @@ -80,7 +82,7 @@ filegroup { ], visibility: [ "//frameworks/base/packages/Tethering", - "//packages/modules/Connectivity/Tethering" + "//packages/modules/Connectivity/Tethering", ], } diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java index a8d8a90e8935..96495701811e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java @@ -19,6 +19,7 @@ package com.android.server.app; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyInt; @@ -32,8 +33,10 @@ import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.os.Bundle; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; +import android.util.ArraySet; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -140,15 +143,19 @@ public class GameManagerServiceTests { applicationInfo.category = ApplicationInfo.CATEGORY_GAME; final PackageInfo pi = new PackageInfo(); pi.packageName = mPackageName; + pi.applicationInfo = applicationInfo; final List<PackageInfo> packages = new ArrayList<>(); packages.add(pi); - when(mMockPackageManager.getInstalledPackages(anyInt())).thenReturn(packages); + when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) + .thenReturn(packages); when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) .thenReturn(applicationInfo); } @After public void tearDown() throws Exception { + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.disableCompatScale(mPackageName); if (mMockingSession != null) { mMockingSession.finishMocking(); } @@ -165,57 +172,95 @@ public class GameManagerServiceTests { } private void mockDeviceConfigDefault() { - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, "").build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(""); } private void mockDeviceConfigNone() { - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(null); } private void mockDeviceConfigPerformance() { String configString = "mode=2,downscaleFactor=0.5"; - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); } private void mockDeviceConfigBattery() { String configString = "mode=3,downscaleFactor=0.7"; - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); } private void mockDeviceConfigAll() { String configString = "mode=3,downscaleFactor=0.7:mode=2,downscaleFactor=0.5"; - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); } private void mockDeviceConfigInvalid() { String configString = "mode=2,downscaleFactor=0.55"; - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); } private void mockDeviceConfigMalformed() { String configString = "adsljckv=nin3rn9hn1231245:8795tq=21ewuydg"; - DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder( - DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build(); - when(DeviceConfig.getProperties(anyString(), anyString())) - .thenReturn(properties); + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); + } + + private void mockGameModeOptInAll() throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_PERFORMANCE_MODE_ENABLE, true); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_BATTERY_MODE_ENABLE, true); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockGameModeOptInPerformance() throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_PERFORMANCE_MODE_ENABLE, true); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockGameModeOptInBattery() throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_BATTERY_MODE_ENABLE, true); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockInterventionAllowDownscaleTrue() throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_WM_ALLOW_DOWNSCALE, true); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockInterventionAllowDownscaleFalse() throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_WM_ALLOW_DOWNSCALE, false); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); } /** @@ -353,136 +398,209 @@ public class GameManagerServiceTests { gameManagerService.getGameMode(mPackageName, USER_ID_2)); } + private void checkReportedModes(int ...requiredModes) { + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.onUserStarting(USER_ID_1); + gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName); + ArraySet<Integer> reportedModes = new ArraySet<>(); + int[] modes = gameManagerService.getAvailableGameModes(mPackageName); + for (int mode : modes) { + reportedModes.add(mode); + } + assertEquals(requiredModes.length, reportedModes.size()); + for (int requiredMode : reportedModes) { + assertTrue("Required game mode not supported: " + requiredMode, + reportedModes.contains(requiredMode)); + } + } + + private void checkDownscaling(int gameMode, String scaling) { + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.onUserStarting(USER_ID_1); + gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName); + GameManagerService.GamePackageConfiguration config = + gameManagerService.getConfig(mPackageName); + assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling); + } + /** - * Phonesky device config exists, but is only propagating the default value. + * Phenotype device config exists, but is only propagating the default value. */ @Test public void testDeviceConfigDefault() { mockDeviceConfigDefault(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - assertEquals(modes.length, 1); - assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED); + checkReportedModes(GameManager.GAME_MODE_UNSUPPORTED); } /** - * Phonesky device config does not exists. + * Phenotype device config does not exists. */ @Test public void testDeviceConfigNone() { mockDeviceConfigNone(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - assertEquals(modes.length, 1); - assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED); + checkReportedModes(GameManager.GAME_MODE_UNSUPPORTED); } /** - * Phonesky device config for performance mode exists and is valid. + * Phenotype device config for performance mode exists and is valid. */ @Test public void testDeviceConfigPerformance() { mockDeviceConfigPerformance(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - boolean perfModeExists = false; - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - for (int mode : modes) { - if (mode == GameManager.GAME_MODE_PERFORMANCE) { - perfModeExists = true; - } - } - assertEquals(modes.length, 1); - assertTrue(perfModeExists); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_STANDARD); } /** - * Phonesky device config for battery mode exists and is valid. + * Phenotype device config for battery mode exists and is valid. */ @Test public void testDeviceConfigBattery() { mockDeviceConfigBattery(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - boolean batteryModeExists = false; - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - for (int mode : modes) { - if (mode == GameManager.GAME_MODE_BATTERY) { - batteryModeExists = true; - } - } - assertEquals(modes.length, 1); - assertTrue(batteryModeExists); + checkReportedModes(GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD); } /** - * Phonesky device configs for both battery and performance modes exists and are valid. + * Phenotype device configs for both battery and performance modes exists and are valid. */ @Test public void testDeviceConfigAll() { mockDeviceConfigAll(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - boolean batteryModeExists = false; - boolean perfModeExists = false; - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - for (int mode : modes) { - if (mode == GameManager.GAME_MODE_BATTERY) { - batteryModeExists = true; - } else if (mode == GameManager.GAME_MODE_PERFORMANCE) { - perfModeExists = true; - } - } - assertTrue(batteryModeExists); - assertTrue(perfModeExists); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_BATTERY, + GameManager.GAME_MODE_STANDARD); } /** - * Phonesky device config contains values that parse correctly but are not valid in game mode. + * Phenotype device config contains values that parse correctly but are not valid in game mode. */ @Test public void testDeviceConfigInvalid() { mockDeviceConfigInvalid(); mockModifyGameModeGranted(); - GameManagerService gameManagerService = new GameManagerService(mMockContext); - gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - assertEquals(modes.length, 1); - assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED); + checkReportedModes(GameManager.GAME_MODE_UNSUPPORTED); } /** - * Phonesky device config is garbage. + * Phenotype device config is garbage. */ @Test public void testDeviceConfigMalformed() { mockDeviceConfigMalformed(); mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_UNSUPPORTED); + } + + /** + * Game modes are made available only through app manifest opt-in. + */ + @Test + public void testGameModeOptInAll() throws Exception { + mockGameModeOptInAll(); + mockDeviceConfigNone(); + mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_BATTERY, + GameManager.GAME_MODE_STANDARD); + } + + /** + * BATTERY game mode is available through the app manifest opt-in. + */ + @Test + public void testGameModeOptInBattery() throws Exception { + mockGameModeOptInBattery(); + mockDeviceConfigNone(); + mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD); + } + + /** + * PERFORMANCE game mode is available through the app manifest opt-in. + */ + @Test + public void testGameModeOptInPerformance() throws Exception { + mockGameModeOptInPerformance(); + mockDeviceConfigNone(); + mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_STANDARD); + } + + /** + * BATTERY game mode is available through the app manifest opt-in and PERFORMANCE game mode is + * available through Phenotype. + */ + @Test + public void testGameModeOptInBatteryMixed() throws Exception { + mockGameModeOptInBattery(); + mockDeviceConfigPerformance(); + mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_BATTERY, + GameManager.GAME_MODE_STANDARD); + } + + /** + * PERFORMANCE game mode is available through the app manifest opt-in and BATTERY game mode is + * available through Phenotype. + */ + @Test + public void testGameModeOptInPerformanceMixed() throws Exception { + mockGameModeOptInPerformance(); + mockDeviceConfigBattery(); + mockModifyGameModeGranted(); + checkReportedModes(GameManager.GAME_MODE_PERFORMANCE, GameManager.GAME_MODE_BATTERY, + GameManager.GAME_MODE_STANDARD); + } + + /** + * PERFORMANCE game mode is configured through Phenotype. The app hasn't specified any metadata. + */ + @Test + public void testInterventionAllowScalingDefault() throws Exception { + mockDeviceConfigPerformance(); + mockModifyGameModeGranted(); + checkDownscaling(GameManager.GAME_MODE_PERFORMANCE, "0.5"); + } + + /** + * PERFORMANCE game mode is configured through Phenotype. The app has opted-out of scaling. + */ + @Test + public void testInterventionAllowDownscaleFalse() throws Exception { + mockDeviceConfigPerformance(); + mockInterventionAllowDownscaleFalse(); + mockModifyGameModeGranted(); + checkDownscaling(GameManager.GAME_MODE_PERFORMANCE, "1.0"); + } + + /** + * PERFORMANCE game mode is configured through Phenotype. The app has redundantly specified + * the downscaling metadata default value of "true". + */ + @Test + public void testInterventionAllowDownscaleTrue() throws Exception { + mockDeviceConfigPerformance(); + mockInterventionAllowDownscaleTrue(); + mockModifyGameModeGranted(); + checkDownscaling(GameManager.GAME_MODE_PERFORMANCE, "0.5"); + } + + /** + * PERFORMANCE game mode is configured through Phenotype, but the app has also opted into the + * same mode. No interventions for this game mode should be available in this case. + */ + @Test + public void testDeviceConfigOptInOverlap() throws Exception { + mockDeviceConfigPerformance(); + mockGameModeOptInPerformance(); + mockModifyGameModeGranted(); GameManagerService gameManagerService = new GameManagerService(mMockContext); gameManagerService.onUserStarting(USER_ID_1); - gameManagerService.loadDeviceConfigLocked(); - - int[] modes = gameManagerService.getAvailableGameModes(mPackageName); - assertEquals(modes.length, 1); - assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED); + gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName); + GameManagerService.GamePackageConfiguration config = + gameManagerService.getConfig(mPackageName); + assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE)); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 1b42dfa0712e..c54dffc3c431 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -30,6 +30,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; +import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.PasswordMetrics.computeForPasswordOrPin; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; @@ -7333,6 +7334,48 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(dpm.getPolicyExemptApps()).containsExactly("4", "8", "15", "16", "23", "42"); } + @Test + public void testSetGlobalPrivateDnsModeOpportunistic_asDeviceOwner() throws Exception { + setDeviceOwner(); + // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the + // feature is disabled because there are non-affiliated secondary users. + getServices().removeUser(CALLER_USER_HANDLE); + clearInvocations(getServices().settings); + + int result = dpm.setGlobalPrivateDnsModeOpportunistic(admin1); + + assertThat(result).isEqualTo(PRIVATE_DNS_SET_NO_ERROR); + } + + @Test + public void testSetGlobalPrivateDnsModeOpportunistic_hasUnaffiliatedUsers() throws Exception { + setDeviceOwner(); + setAsProfileOwner(admin2); + + assertThrows(SecurityException.class, + () -> dpm.setGlobalPrivateDnsModeOpportunistic(admin1)); + } + + @Test + public void testSetRecommendedGlobalProxy_asDeviceOwner() throws Exception { + setDeviceOwner(); + // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the + // feature is disabled because there are non-affiliated secondary users. + getServices().removeUser(CALLER_USER_HANDLE); + + dpm.setRecommendedGlobalProxy(admin1, null); + + verify(getServices().connectivityManager).setGlobalProxy(null); + } + + @Test + public void testSetRecommendedGlobalProxy_hasUnaffiliatedUsers() throws Exception { + setDeviceOwner(); + setAsProfileOwner(admin2); + + assertThrows(SecurityException.class, () -> dpm.setRecommendedGlobalProxy(admin1, null)); + } + private void setUserUnlocked(int userHandle, boolean unlocked) { when(getServices().userManager.isUserUnlocked(eq(userHandle))).thenReturn(unlocked); } diff --git a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java index 153938cbbbf1..b2c300255aef 100644 --- a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java @@ -18,6 +18,7 @@ package com.android.server.pm; import static org.junit.Assert.assertTrue; +import android.content.ComponentName; import android.content.IntentFilter; import androidx.test.filters.SmallTest; @@ -83,4 +84,80 @@ public class WatchedIntentHandlingTest { watcher.verifyNoChangeReported("pulled snapshot"); } + @Test + public void testPreferredActivity() { + // Create a bunch of nondescript component names + ComponentName component = new ComponentName("Package_A", "Class_A"); + ComponentName[] components = new ComponentName[10]; + for (int i = 0; i < components.length; i++) { + components[i] = new ComponentName("Package_" + i, "Class_" + i); + } + IntentFilter i = new IntentFilter("TEST_ACTION"); + PreferredActivity a = new PreferredActivity(i, 1, components, component, true); + final WatchableTester watcher = new WatchableTester(a, "PreferredIntentResolver"); + watcher.register(); + + // Verify that the initial IntentFilter and the PreferredActivity are truly + // independent. This is in addition to verifying that the PreferredActivity + // properly reports its changes. + i.setPriority(i.getPriority() + 1); + watcher.verifyNoChangeReported("indepenent intent"); + a.setPriority(a.getPriority() + 2); + watcher.verifyChangeReported("dependent intent"); + // Verify independence of i and a + assertTrue(i.getPriority() != a.getPriority()); + + // Verify that snapshots created from the PreferredActivity are stable when the + // source PreferredActivity changes. + a.setPriority(3); + watcher.verifyChangeReported("initialize intent priority"); + PreferredActivity s1 = a.snapshot(); + watcher.verifyNoChangeReported("pulled snapshot"); + // Verify snapshot cache. In the absence of changes to the PreferredActivity, the + // snapshot will not be rebuilt and will be the exact same object as before. + assertTrue(s1 == a.snapshot()); + // Force a change by incrementing the priority. The next snapshot must be + // different from the first snapshot. + a.setPriority(a.getPriority() + 1); + watcher.verifyChangeReported("increment priority"); + PreferredActivity s2 = a.snapshot(); + watcher.verifyNoChangeReported("pulled second snapshot"); + assertTrue(s1 != s2); + // Assert the two snapshots are different. s1 should have priority 3 and s2 + // should have priority 4. s2 should match the current value in a. + assertTrue(a.getPriority() == s2.getPriority()); + assertTrue(s1.getPriority() != s2.getPriority()); + } + + @Test + public void testPreferredIntentResolver() { + PreferredIntentResolver r = new PreferredIntentResolver(); + final WatchableTester watcher = new WatchableTester(r, "PreferredIntentResolver"); + watcher.register(); + // Create a bunch of nondescript component names + ComponentName component = new ComponentName("Package_A", "Class_A"); + ComponentName[] components = new ComponentName[10]; + for (int i = 0; i < components.length; i++) { + components[i] = new ComponentName("Package_" + i, "Class_" + i); + } + IntentFilter i = new IntentFilter("TEST_ACTION"); + PreferredActivity a1 = new PreferredActivity(i, 1, components, component, true); + + r.addFilter(a1); + watcher.verifyChangeReported("addFilter"); + i.setPriority(i.getPriority() + 1); + watcher.verifyNoChangeReported("indepenent intent"); + a1.setPriority(a1.getPriority() + 1); + watcher.verifyChangeReported("dependent intent"); + + PreferredActivity s1 = a1.snapshot(); + watcher.verifyNoChangeReported("pulled snapshot"); + // Verify snapshot cache. + assertTrue(s1 == a1.snapshot()); + a1.setPriority(a1.getPriority() + 1); + watcher.verifyChangeReported("increment priority"); + PreferredActivity s2 = a1.snapshot(); + watcher.verifyNoChangeReported("pulled second snapshot"); + assertTrue(s1.getPriority() != s2.getPriority()); + } } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OrdinalGeneratorTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/OrdinalGeneratorTest.java index af954d599334..3fdac66225a8 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/OrdinalGeneratorTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OrdinalGeneratorTest.java @@ -25,13 +25,14 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.Arrays; +import java.util.function.Function; @RunWith(AndroidJUnit4.class) public class OrdinalGeneratorTest { @Test - public void testOrdinal() { - OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(); + public void testOrdinal_withIdentityFunction() { + OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(Function.identity()); int oneOrd = ordinalGenerator.ordinal("One"); int twoOrd = ordinalGenerator.ordinal("Two"); assertNotEquals(oneOrd, twoOrd); @@ -45,8 +46,8 @@ public class OrdinalGeneratorTest { } @Test - public void testOrdinals() { - OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(); + public void testOrdinals_withIdentityFunction() { + OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(Function.identity()); int[] oneTwoOrds = ordinalGenerator.ordinals(Arrays.asList("One", "Two")); int[] twoThreeOrds = ordinalGenerator.ordinals(Arrays.asList("Two", "Three")); assertEquals(oneTwoOrds[0], ordinalGenerator.ordinal("One")); @@ -54,4 +55,33 @@ public class OrdinalGeneratorTest { assertEquals(twoThreeOrds[0], ordinalGenerator.ordinal("Two")); assertEquals(twoThreeOrds[1], ordinalGenerator.ordinal("Three")); } + + @Test + public void testOrdinal_withCanonicalizationFunction() { + OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(String::toLowerCase); + + int oneOrd = ordinalGenerator.ordinal("One"); + int twoOrd = ordinalGenerator.ordinal("Two"); + assertNotEquals(oneOrd, twoOrd); + + assertEquals(oneOrd, ordinalGenerator.ordinal("ONE")); + assertEquals(twoOrd, ordinalGenerator.ordinal("two")); + + int threeOrd = ordinalGenerator.ordinal("Three"); + assertNotEquals(oneOrd, threeOrd); + assertNotEquals(twoOrd, threeOrd); + } + + @Test + public void testOrdinals_withCanonicalizationFunction() { + OrdinalGenerator<String> ordinalGenerator = new OrdinalGenerator<>(String::toLowerCase); + + int[] oneTwoOrds = ordinalGenerator.ordinals(Arrays.asList("One", "Two")); + int[] twoThreeOrds = ordinalGenerator.ordinals(Arrays.asList("Two", "Three")); + + assertEquals(oneTwoOrds[0], ordinalGenerator.ordinal("ONE")); + assertEquals(oneTwoOrds[1], ordinalGenerator.ordinal("two")); + assertEquals(twoThreeOrds[0], ordinalGenerator.ordinal("TWO")); + assertEquals(twoThreeOrds[1], ordinalGenerator.ordinal("threE")); + } } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneCanonicalizerTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneCanonicalizerTest.java new file mode 100644 index 000000000000..0c78f5b85fac --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneCanonicalizerTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezonedetector; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class TimeZoneCanonicalizerTest { + + TimeZoneCanonicalizer mFunction = new TimeZoneCanonicalizer(); + + @Test + public void deprecatedTimeZonesAreEqualToCanonical() { + assertThat(mFunction.apply("America/Godthab")).isEqualTo("America/Nuuk"); + assertThat(mFunction.apply("Australia/Currie")).isEqualTo("Australia/Hobart"); + } + + @Test + public void wellKnownCanonicalIDs() { + assertThat(mFunction.apply("America/Detroit")).isEqualTo("America/Detroit"); + assertThat(mFunction.apply("Europe/London")).isEqualTo("Europe/London"); + assertThat(mFunction.apply("America/New_York")).isEqualTo("America/New_York"); + assertThat(mFunction.apply("Europe/Volgograd")).isEqualTo("Europe/Volgograd"); + } + + @Test + public void timeZonesAsGmtOffsetsTreatedAsCanonical() { + assertThat(mFunction.apply("Etc/GMT-11")).isEqualTo("Etc/GMT-11"); + } + + @Test + public void nonExistingOneMappedToThemselves() { + assertThat(mFunction.apply("Mars/Base")).isEqualTo("Mars/Base"); + } +} diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index 47475a66c0d5..331f76cf7dc2 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -56,6 +56,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; /** * White-box unit tests for {@link TimeZoneDetectorStrategyImpl}. @@ -1008,7 +1009,7 @@ public class TimeZoneDetectorStrategyImplTest { // Check the various feature state values are what we expect. assertFeatureStateMatchesConfig(expectedInternalConfig, actualState, expectedDetectionMode); - OrdinalGenerator<String> tzIdOrdinalGenerator = new OrdinalGenerator<>(); + OrdinalGenerator<String> tzIdOrdinalGenerator = new OrdinalGenerator<>(Function.identity()); MetricsTimeZoneDetectorState expectedState = MetricsTimeZoneDetectorState.create( tzIdOrdinalGenerator, expectedInternalConfig, expectedDeviceTimeZoneId, diff --git a/services/tests/servicestests/src/com/android/server/utils/OWNERS b/services/tests/servicestests/src/com/android/server/utils/OWNERS new file mode 100644 index 000000000000..1853220b9433 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/utils/OWNERS @@ -0,0 +1,4 @@ +per-file WatchableTester.java = file:/services/core/java/com/android/server/pm/OWNERS +per-file WatchableTester.java = shombert@google.com +per-file WatcherTest.java = file:/services/core/java/com/android/server/pm/OWNERS +per-file WatcherTest.java = shombert@google.com diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java index f255c67cf47d..9679e58c4e7d 100644 --- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java +++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java @@ -916,5 +916,14 @@ public class WatcherTest { assertTrue(s1 != s2); assertTrue(leafA.get() == s1.get() + 1); assertTrue(leafA.get() == s2.get()); + + // Test sealed snapshots + SnapshotCache<Leaf> sealed = new SnapshotCache.Sealed(); + try { + Leaf x1 = sealed.snapshot(); + fail(name + " sealed snapshot did not throw"); + } catch (UnsupportedOperationException e) { + // This is the passing scenario - the exception is expected. + } } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java index a05fea2c8f70..1126e1ece452 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java @@ -21,6 +21,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + import android.app.Notification; import android.os.UserHandle; import android.service.notification.StatusBarNotification; @@ -37,7 +39,11 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.ConcurrentModificationException; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; @SmallTest @RunWith(AndroidJUnit4.class) @@ -165,4 +171,54 @@ public class ArchiveTest extends UiServiceTestCase { assertThat(expected).contains(sbn.getKey()); } } + + @Test + public void testRemoveChannelNotifications_concurrently() throws InterruptedException { + List<String> expected = new ArrayList<>(); + // Add one extra notification to the beginning to test when 2 adjacent notifications will be + // removed in the same pass. + StatusBarNotification sbn0 = getNotification("pkg", 0, UserHandle.of(USER_CURRENT)); + mArchive.record(sbn0, REASON_CANCEL); + for (int i = 0; i < SIZE; i++) { + StatusBarNotification sbn = getNotification("pkg", i, UserHandle.of(USER_CURRENT)); + mArchive.record(sbn, REASON_CANCEL); + if (i >= SIZE - 2) { + // Remove everything < SIZE - 2 + expected.add(sbn.getKey()); + } + } + + // Remove these in multiple threads to try to get them to happen at the same time + int numThreads = SIZE - 2; + AtomicBoolean error = new AtomicBoolean(false); + CountDownLatch startThreadsLatch = new CountDownLatch(1); + CountDownLatch threadsDone = new CountDownLatch(numThreads); + for (int i = 0; i < numThreads; i++) { + final int idx = i; + new Thread(() -> { + try { + startThreadsLatch.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test" + idx); + } catch (ConcurrentModificationException e) { + error.compareAndSet(false, true); + } + }).start(); + } + + startThreadsLatch.countDown(); + threadsDone.await(10, TimeUnit.SECONDS); + if (error.get()) { + fail("Concurrent modification exception"); + } + + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + assertThat(actual).hasSize(expected.size()); + for (StatusBarNotification sbn : actual) { + assertThat(expected).contains(sbn.getKey()); + } + } } 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 537bc2c7d52c..c33287c57377 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -141,6 +141,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.os.Looper; import android.os.Parcel; import android.os.Process; import android.os.RemoteException; @@ -267,6 +268,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { RankingHandler mRankingHandler; @Mock ActivityManagerInternal mAmi; + @Mock + private Looper mMainLooper; @Mock IIntentSender pi1; @@ -514,7 +517,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppOpsManager, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), mAmi, mToastRateLimiter); - mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); + // Return first true for RoleObserver main-thread check + when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); + mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); mService.setAudioManager(mAudioManager); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java index 4ce237e3aadc..27ae46c87b28 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java @@ -16,6 +16,7 @@ package com.android.server.notification; +import static android.app.role.RoleManager.ROLE_BROWSER; import static android.app.role.RoleManager.ROLE_DIALER; import static android.app.role.RoleManager.ROLE_EMERGENCY; import static android.content.pm.PackageManager.MATCH_ALL; @@ -23,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_ALL; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; @@ -31,6 +33,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static java.util.Arrays.asList; + import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; @@ -44,7 +48,6 @@ import android.companion.ICompanionDeviceManager; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; import android.os.Looper; import android.os.UserHandle; import android.os.UserManager; @@ -80,7 +83,6 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Executor; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -98,13 +100,13 @@ public class RoleObserverTest extends UiServiceTestCase { @Mock private UserManager mUm; @Mock - private Executor mExecutor; - @Mock private RoleManager mRoleManager; + @Mock + private Looper mMainLooper; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 1 << 30); - private List<UserInfo> mUsers; + private List<UserHandle> mUsers; private static class TestableNotificationManagerService extends NotificationManagerService { TestableNotificationManagerService(Context context, @@ -133,13 +135,15 @@ public class RoleObserverTest extends UiServiceTestCase { mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); mUsers = new ArrayList<>(); - mUsers.add(new UserInfo(0, "system", 0)); - mUsers.add(new UserInfo(10, "second", 0)); - when(mUm.getUsers()).thenReturn(mUsers); + mUsers.add(new UserHandle(0)); + mUsers.add(new UserHandle(10)); + when(mUm.getUserHandles(anyBoolean())).thenReturn(mUsers); + + when(mMainLooper.isCurrentThread()).thenReturn(true); mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, mNotificationInstanceIdSequence); - mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor); + mRoleObserver = mService.new RoleObserver(mContext, mRoleManager, mPm, mMainLooper); try { mService.init(mService.new WorkerHandler(mock(Looper.class)), @@ -174,7 +178,7 @@ public class RoleObserverTest extends UiServiceTestCase { } @Test - public void testInit() throws Exception { + public void testInit_forNonBlockableDefaultApps() throws Exception { List<String> dialer0 = new ArrayList<>(); dialer0.add("dialer"); List<String> emer0 = new ArrayList<>(); @@ -191,29 +195,29 @@ public class RoleObserverTest extends UiServiceTestCase { when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(dialer0); + mUsers.get(0))) + .thenReturn(dialer0); when(mRoleManager.getRoleHoldersAsUser( ROLE_EMERGENCY, - mUsers.get(0).getUserHandle())). - thenReturn(emer0); + mUsers.get(0))) + .thenReturn(emer0); mRoleObserver.init(); // verify internal records of current state of the world assertTrue(mRoleObserver.isApprovedPackageForRoleForUser( - ROLE_DIALER, dialer0.get(0), mUsers.get(0).id)); + ROLE_DIALER, dialer0.get(0), mUsers.get(0).getIdentifier())); assertFalse(mRoleObserver.isApprovedPackageForRoleForUser( - ROLE_DIALER, dialer0.get(0), mUsers.get(1).id)); + ROLE_DIALER, dialer0.get(0), mUsers.get(1).getIdentifier())); assertTrue(mRoleObserver.isApprovedPackageForRoleForUser( - ROLE_EMERGENCY, emer0.get(0), mUsers.get(0).id)); + ROLE_EMERGENCY, emer0.get(0), mUsers.get(0).getIdentifier())); assertFalse(mRoleObserver.isApprovedPackageForRoleForUser( - ROLE_EMERGENCY, emer0.get(0), mUsers.get(1).id)); + ROLE_EMERGENCY, emer0.get(0), mUsers.get(1).getIdentifier())); // make sure we're listening to updates verify(mRoleManager, times(1)).addOnRoleHoldersChangedListenerAsUser( - eq(mExecutor), any(), eq(UserHandle.ALL)); + any(), any(), eq(UserHandle.ALL)); // make sure we told pref helper about the state of the world verify(mPreferencesHelper, times(1)).updateDefaultApps(0, null, dialer0Pair); @@ -221,14 +225,31 @@ public class RoleObserverTest extends UiServiceTestCase { } @Test - public void testSwapDefault() throws Exception { + public void testInit_forTrampolines() throws Exception { + when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30); + when(mRoleManager.getRoleHoldersAsUser( + ROLE_BROWSER, + mUsers.get(0))) + .thenReturn(asList("com.browser")); + + mRoleObserver.init(); + + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30)); + + // make sure we're listening to updates + verify(mRoleManager, times(1)).addOnRoleHoldersChangedListenerAsUser(any(), any(), + eq(UserHandle.ALL)); + } + + @Test + public void testSwapDefault_forNonBlockableDefaultApps() throws Exception { List<String> dialer0 = new ArrayList<>(); dialer0.add("dialer"); when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(dialer0); + mUsers.get(0))) + .thenReturn(dialer0); mRoleObserver.init(); @@ -241,8 +262,8 @@ public class RoleObserverTest extends UiServiceTestCase { when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(newDefault); + mUsers.get(0))) + .thenReturn(newDefault); mRoleObserver.onRoleHoldersChanged(ROLE_DIALER, UserHandle.of(0)); @@ -251,15 +272,39 @@ public class RoleObserverTest extends UiServiceTestCase { } @Test - public void testSwapDefault_multipleOverlappingApps() throws Exception { + public void testSwapDefault_forTrampolines() throws Exception { + List<String> dialer0 = new ArrayList<>(); + when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30); + when(mPm.getPackageUid("com.browser2", MATCH_ALL, 0)).thenReturn(31); + when(mRoleManager.getRoleHoldersAsUser( + ROLE_BROWSER, + mUsers.get(0))) + .thenReturn(asList("com.browser")); + mRoleObserver.init(); + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30)); + assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(31)); + // Default changed + when(mRoleManager.getRoleHoldersAsUser( + ROLE_BROWSER, + mUsers.get(0))) + .thenReturn(asList("com.browser2")); + mRoleObserver.onRoleHoldersChanged(ROLE_BROWSER, UserHandle.of(0)); + + assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(30)); + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(31)); + } + + @Test + public void testSwapDefault_multipleOverlappingApps_forNonBlockableDefaultApps() + throws Exception { List<String> dialer0 = new ArrayList<>(); dialer0.add("dialer"); dialer0.add("phone"); when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(dialer0); + mUsers.get(0))) + .thenReturn(dialer0); mRoleObserver.init(); @@ -273,8 +318,8 @@ public class RoleObserverTest extends UiServiceTestCase { when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(newDefault); + mUsers.get(0))) + .thenReturn(newDefault); ArraySet<String> expectedRemove = new ArraySet<>(); expectedRemove.add("dialer"); @@ -294,14 +339,14 @@ public class RoleObserverTest extends UiServiceTestCase { } @Test - public void testSwapDefault_newUser() throws Exception { + public void testSwapDefault_newUser_forNonBlockableDefaultApps() throws Exception { List<String> dialer0 = new ArrayList<>(); dialer0.add("dialer"); when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(0).getUserHandle())). - thenReturn(dialer0); + mUsers.get(0))) + .thenReturn(dialer0); mRoleObserver.init(); @@ -310,8 +355,8 @@ public class RoleObserverTest extends UiServiceTestCase { when(mRoleManager.getRoleHoldersAsUser( ROLE_DIALER, - mUsers.get(1).getUserHandle())). - thenReturn(dialer10); + mUsers.get(1))) + .thenReturn(dialer10); ArraySet<Pair<String, Integer>> expectedAddPair = new ArraySet<>(); expectedAddPair.add(new Pair("phone", 30)); @@ -329,4 +374,27 @@ public class RoleObserverTest extends UiServiceTestCase { assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "phone", 10)); assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "dialer", 0)); } + + @Test + public void testSwapDefault_newUser_forTrampolines() throws Exception { + List<String> dialer0 = new ArrayList<>(); + when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30); + when(mPm.getPackageUid("com.browser2", MATCH_ALL, 10)).thenReturn(1031); + when(mRoleManager.getRoleHoldersAsUser( + ROLE_BROWSER, + mUsers.get(0))) + .thenReturn(asList("com.browser")); + mRoleObserver.init(); + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30)); + assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(1031)); + // New user + when(mRoleManager.getRoleHoldersAsUser( + ROLE_BROWSER, + mUsers.get(1))) + .thenReturn(asList("com.browser2")); + mRoleObserver.onRoleHoldersChanged(ROLE_BROWSER, UserHandle.of(10)); + + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30)); + assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(1031)); + } } 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 fdeb7a6eb71a..4bbea94060c4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1723,6 +1723,15 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(display.hasTopFixedRotationLaunchingApp()); assertFalse(activity.hasFixedRotationTransform()); + + // Simulate that the activity requests the same orientation as display. + activity.setOrientation(display.getConfiguration().orientation); + // Skip the real freezing. + activity.mVisibleRequested = false; + clearInvocations(activity); + activity.onCancelFixedRotationTransform(originalRotation); + // The implementation of cancellation must be executed. + verify(activity).startFreezingScreen(originalRotation); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 13ef9982494e..9226c0b6f32b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -62,7 +62,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; import android.app.ActivityManager; import android.app.TaskInfo; @@ -1323,20 +1322,22 @@ public class TaskTests extends WindowTestsBase { } @Test - public void testNotifyOrientationChangeCausedByConfigurationChange() { + public void testTaskOrientationOnDisplayWindowingModeChange() { + // Skip unnecessary operations to speed up the test. + mAtm.deferWindowLayout(); final Task task = getTestTask(); final ActivityRecord activity = task.getTopMostActivity(); final DisplayContent display = task.getDisplayContent(); - display.setWindowingMode(WINDOWING_MODE_FREEFORM); + mWm.setWindowingMode(display.mDisplayId, WINDOWING_MODE_FREEFORM); activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); assertEquals(SCREEN_ORIENTATION_UNSET, task.getOrientation()); - verify(display).onDescendantOrientationChanged(same(task)); - reset(display); + assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, display.getLastOrientation()); - display.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + mWm.setWindowingMode(display.mDisplayId, WINDOWING_MODE_FULLSCREEN); assertEquals(SCREEN_ORIENTATION_LANDSCAPE, task.getOrientation()); - verify(display).onDescendantOrientationChanged(same(task)); + assertEquals(SCREEN_ORIENTATION_LANDSCAPE, display.getLastOrientation()); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, display.getConfiguration().orientation); } @Test diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index d9001bd488f4..78da86c57ef1 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -15016,6 +15016,15 @@ public class TelephonyManager { "CAPABILITY_SLICING_CONFIG_SUPPORTED"; /** + * Indicates whether PHYSICAL_CHANNEL_CONFIG HAL1.6 is supported. See comments on + * respective methods for more information. + * + * @hide + */ + public static final String CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED = + "CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED"; + + /** * A list of the radio interface capability values with public valid constants. * * Here is a related list for the systemapi-only valid constants: diff --git a/test-mock/Android.bp b/test-mock/Android.bp index a2447d71c3bd..b83bce654a85 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -38,6 +38,7 @@ java_sdk_library { ], libs: [ "framework", + "framework-annotations-lib", "app-compat-annotations", "unsupportedappusage", ], diff --git a/tests/HwAccelerationTest/res/layout/stretch_layout.xml b/tests/HwAccelerationTest/res/layout/stretch_layout.xml index df5f297da729..81e0c019490f 100644 --- a/tests/HwAccelerationTest/res/layout/stretch_layout.xml +++ b/tests/HwAccelerationTest/res/layout/stretch_layout.xml @@ -16,7 +16,6 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scroll_view" - android:edgeEffectType="stretch" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout @@ -26,7 +25,6 @@ <HorizontalScrollView android:id="@+id/horizontal_scroll_view" - android:edgeEffectType="stretch" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout diff --git a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt index c01d32bf4cd2..6ef1ecdae59b 100644 --- a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt +++ b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt @@ -35,7 +35,7 @@ class ViewFrameInfoTest { fun setUp() { mViewFrameInfo.reset() mViewFrameInfo.setInputEvent(139) - mViewFrameInfo.flags = mViewFrameInfo.flags or FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED + mViewFrameInfo.flags = mViewFrameInfo.flags or FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED mTimeStarted = SystemClock.uptimeNanos() mViewFrameInfo.markDrawStart() } @@ -43,7 +43,7 @@ class ViewFrameInfoTest { @Test fun testPopulateFields() { assertThat(mViewFrameInfo.drawStart).isGreaterThan(mTimeStarted) - assertThat(mViewFrameInfo.flags).isEqualTo(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED) + assertThat(mViewFrameInfo.flags).isEqualTo(FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) } @Test @@ -66,7 +66,7 @@ class ViewFrameInfoTest { mViewFrameInfo.populateFrameInfo(frameInfo) assertThat(frameInfo.frameInfo[FrameInfo.INPUT_EVENT_ID]).isEqualTo(139) assertThat(frameInfo.frameInfo[FrameInfo.FLAGS]).isEqualTo( - FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED) + FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) assertThat(frameInfo.frameInfo[FrameInfo.DRAW_START]).isGreaterThan(mTimeStarted) } }
\ No newline at end of file diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp index 8b0ae5c37bae..ea5a43104bba 100644 --- a/tests/UpdatableSystemFontTest/Android.bp +++ b/tests/UpdatableSystemFontTest/Android.bp @@ -21,16 +21,15 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -java_test_host { +android_test { name: "UpdatableSystemFontTest", srcs: ["src/**/*.java"], - libs: [ - "tradefed", - "compatibility-tradefed", - "compatibility-host-util", - ], + libs: ["android.test.runner"], static_libs: [ - "frameworks-base-hostutils", + "androidx.test.ext.junit", + "compatibility-device-util-axt", + "platform-test-annotations", + "truth-prebuilt", ], test_suites: [ "general-tests", @@ -47,4 +46,5 @@ java_test_host { ":UpdatableSystemFontTestNotoColorEmojiVPlus2Ttf", ":UpdatableSystemFontTestNotoColorEmojiVPlus2TtfFsvSig", ], + sdk_version: "test_current", } diff --git a/tests/UpdatableSystemFontTest/AndroidManifest.xml b/tests/UpdatableSystemFontTest/AndroidManifest.xml new file mode 100644 index 000000000000..531ee981a92c --- /dev/null +++ b/tests/UpdatableSystemFontTest/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.updatablesystemfont"> + + <application android:label="UpdatableSystemFontTest"> + <uses-library android:name="android.test.runner"/> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:label="UpdatableSystemFontTest" + android:targetPackage="com.android.updatablesystemfont"> + </instrumentation> + +</manifest> diff --git a/tests/UpdatableSystemFontTest/AndroidTest.xml b/tests/UpdatableSystemFontTest/AndroidTest.xml index 4f116698ba72..4f6487e7e953 100644 --- a/tests/UpdatableSystemFontTest/AndroidTest.xml +++ b/tests/UpdatableSystemFontTest/AndroidTest.xml @@ -21,6 +21,7 @@ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="UpdatableSystemFontTest.apk" /> <option name="test-file-name" value="EmojiRenderingTestApp.apk" /> </target_preparer> @@ -37,7 +38,7 @@ <option name="push" value="UpdatableSystemFontTestNotoColorEmojiVPlus2.ttf.fsv_sig->/data/local/tmp/UpdatableSystemFontTestNotoColorEmojiVPlus2.ttf.fsv_sig" /> </target_preparer> - <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" > - <option name="jar" value="UpdatableSystemFontTest.jar" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.updatablesystemfont" /> </test> </configuration> diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java index 74f6bca4d7a0..9793c3447ff2 100644 --- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java +++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java @@ -16,44 +16,59 @@ package com.android.updatablesystemfont; +import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; + import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; + +import static org.junit.Assume.assumeTrue; import static java.util.concurrent.TimeUnit.SECONDS; +import android.app.UiAutomation; +import android.content.Context; +import android.graphics.fonts.FontFamilyUpdateRequest; +import android.graphics.fonts.FontFileUpdateRequest; +import android.graphics.fonts.FontManager; +import android.os.ParcelFileDescriptor; import android.platform.test.annotations.RootPermissionTest; +import android.security.FileIntegrityManager; +import android.text.FontConfig; +import android.util.Log; +import android.util.Pair; -import com.android.fsverity.AddFsVerityCertRule; -import com.android.tradefed.device.DeviceNotAvailableException; -import com.android.tradefed.log.LogUtil.CLog; -import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; -import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; -import com.android.tradefed.util.CommandResult; -import com.android.tradefed.util.CommandStatus; +import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.StreamUtil; +import com.android.compatibility.common.util.SystemUtil; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; /** - * Tests if fonts can be updated by 'cmd font'. + * Tests if fonts can be updated by {@link FontManager} API. */ @RootPermissionTest -@RunWith(DeviceJUnit4ClassRunner.class) -public class UpdatableSystemFontTest extends BaseHostJUnit4Test { +@RunWith(AndroidJUnit4.class) +public class UpdatableSystemFontTest { + private static final String TAG = "UpdatableSystemFontTest"; private static final String SYSTEM_FONTS_DIR = "/system/fonts/"; private static final String DATA_FONTS_DIR = "/data/fonts/files/"; - private static final String CERT_PATH = "/data/local/tmp/UpdatableSystemFontTestCert.der"; - - private static final Pattern PATTERN_FONT = Pattern.compile("path = ([^, \n]*)"); - private static final String NOTO_COLOR_EMOJI_TTF = "NotoColorEmoji.ttf"; + private static final String NOTO_COLOR_EMOJI_POSTSCRIPT_NAME = "NotoColorEmoji"; private static final String ORIGINAL_NOTO_COLOR_EMOJI_TTF = "/data/local/tmp/NotoColorEmoji.ttf"; @@ -80,64 +95,75 @@ public class UpdatableSystemFontTest extends BaseHostJUnit4Test { EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity"; private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10); - private interface ThrowingSupplier<T> { - T get() throws Exception; - } - - @Rule - public final AddFsVerityCertRule mAddFsverityCertRule = - new AddFsVerityCertRule(this, CERT_PATH); + private String mKeyId; + private FontManager mFontManager; @Before public void setUp() throws Exception { - expectRemoteCommandToSucceed("cmd font clear"); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + // Run tests only if updatable system font is enabled. + FileIntegrityManager fim = context.getSystemService(FileIntegrityManager.class); + assumeTrue(fim != null); + assumeTrue(fim.isApkVeritySupported()); + mKeyId = insertCert(CERT_PATH); + mFontManager = context.getSystemService(FontManager.class); + expectCommandToSucceed("cmd font clear"); } @After public void tearDown() throws Exception { - expectRemoteCommandToSucceed("cmd font clear"); + expectCommandToSucceed("cmd font clear"); + if (mKeyId != null) { + expectCommandToSucceed("mini-keyctl unlink " + mKeyId + " .fs-verity"); + } } @Test public void updateFont() throws Exception { - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String fontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPath).startsWith(DATA_FONTS_DIR); // The updated font should be readable and unmodifiable. - expectRemoteCommandToSucceed("cat " + fontPath + " > /dev/null"); - expectRemoteCommandToFail("echo -n '' >> " + fontPath); + expectCommandToSucceed("dd status=none if=" + fontPath + " of=/dev/null"); + expectCommandToFail("dd status=none if=" + CERT_PATH + " of=" + fontPath); } @Test public void updateFont_twice() throws Exception { - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String fontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)); - String fontPath2 = getFontPath(NOTO_COLOR_EMOJI_TTF); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath2 = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPath2).startsWith(DATA_FONTS_DIR); assertThat(fontPath2).isNotEqualTo(fontPath); // The new file should be readable. - expectRemoteCommandToSucceed("cat " + fontPath2 + " > /dev/null"); + expectCommandToSucceed("dd status=none if=" + fontPath2 + " of=/dev/null"); // The old file should be still readable. - expectRemoteCommandToSucceed("cat " + fontPath + " > /dev/null"); + expectCommandToSucceed("dd status=none if=" + fontPath + " of=/dev/null"); } @Test public void updateFont_allowSameVersion() throws Exception { // Update original font to the same version - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - ORIGINAL_NOTO_COLOR_EMOJI_TTF, ORIGINAL_NOTO_COLOR_EMOJI_TTF_FSV_SIG)); - String fontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String fontPath2 = getFontPath(NOTO_COLOR_EMOJI_TTF); + assertThat(updateFontFile( + ORIGINAL_NOTO_COLOR_EMOJI_TTF, ORIGINAL_NOTO_COLOR_EMOJI_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath2 = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); // Update updated font to the same version - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String fontPath3 = getFontPath(NOTO_COLOR_EMOJI_TTF); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String fontPath3 = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPath).startsWith(DATA_FONTS_DIR); assertThat(fontPath2).isNotEqualTo(fontPath); assertThat(fontPath2).startsWith(DATA_FONTS_DIR); @@ -147,134 +173,171 @@ public class UpdatableSystemFontTest extends BaseHostJUnit4Test { @Test public void updateFont_invalidCert() throws Exception { - expectRemoteCommandToFail(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_ERROR_VERIFICATION_FAILURE); } @Test public void updateFont_downgradeFromSystem() throws Exception { - expectRemoteCommandToFail(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_V0_TTF, TEST_NOTO_COLOR_EMOJI_V0_TTF_FSV_SIG)); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_V0_TTF, TEST_NOTO_COLOR_EMOJI_V0_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_ERROR_DOWNGRADING); } @Test public void updateFont_downgradeFromData() throws Exception { - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)); - expectRemoteCommandToFail(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS2_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_ERROR_DOWNGRADING); } @Test public void launchApp() throws Exception { - String fontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); + String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPath).startsWith(SYSTEM_FONTS_DIR); startActivity(EMOJI_RENDERING_TEST_APP_ID, EMOJI_RENDERING_TEST_ACTIVITY); - waitUntil(ACTIVITY_TIMEOUT_MILLIS, () -> - isFileOpenedBy(fontPath, EMOJI_RENDERING_TEST_APP_ID)); + SystemUtil.eventually( + () -> assertThat(isFileOpenedBy(fontPath, EMOJI_RENDERING_TEST_APP_ID)).isTrue(), + ACTIVITY_TIMEOUT_MILLIS); } @Test public void launchApp_afterUpdateFont() throws Exception { - String originalFontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); + String originalFontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(originalFontPath).startsWith(SYSTEM_FONTS_DIR); - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", - TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String updatedFontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); + assertThat(updateFontFile( + TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)) + .isEqualTo(FontManager.RESULT_SUCCESS); + String updatedFontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(updatedFontPath).startsWith(DATA_FONTS_DIR); startActivity(EMOJI_RENDERING_TEST_APP_ID, EMOJI_RENDERING_TEST_ACTIVITY); // The original font should NOT be opened by the app. - waitUntil(ACTIVITY_TIMEOUT_MILLIS, () -> - isFileOpenedBy(updatedFontPath, EMOJI_RENDERING_TEST_APP_ID) - && !isFileOpenedBy(originalFontPath, EMOJI_RENDERING_TEST_APP_ID)); + SystemUtil.eventually(() -> { + assertThat(isFileOpenedBy(updatedFontPath, EMOJI_RENDERING_TEST_APP_ID)).isTrue(); + assertThat(isFileOpenedBy(originalFontPath, EMOJI_RENDERING_TEST_APP_ID)).isFalse(); + }, ACTIVITY_TIMEOUT_MILLIS); } @Test public void reboot() throws Exception { - expectRemoteCommandToSucceed(String.format("cmd font update %s %s", + expectCommandToSucceed(String.format("cmd font update %s %s", TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); - String fontPath = getFontPath(NOTO_COLOR_EMOJI_TTF); + String fontPath = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPath).startsWith(DATA_FONTS_DIR); // Emulate reboot by 'cmd font restart'. - expectRemoteCommandToSucceed("cmd font restart"); - String fontPathAfterReboot = getFontPath(NOTO_COLOR_EMOJI_TTF); + expectCommandToSucceed("cmd font restart"); + String fontPathAfterReboot = getFontPath(NOTO_COLOR_EMOJI_POSTSCRIPT_NAME); assertThat(fontPathAfterReboot).isEqualTo(fontPath); } - private String getFontPath(String fontFileName) throws Exception { - // TODO: add a dedicated command for testing. - String lines = expectRemoteCommandToSucceed("cmd font dump"); - for (String line : lines.split("\n")) { - Matcher m = PATTERN_FONT.matcher(line); - if (m.find() && m.group(1).endsWith(fontFileName)) { - return m.group(1); - } + private static String insertCert(String certPath) throws Exception { + Pair<String, String> result; + try (InputStream is = new FileInputStream(certPath)) { + result = runShellCommand("mini-keyctl padd asymmetric fsv_test .fs-verity", is); + } + // Assert that there are no errors. + assertThat(result.second).isEmpty(); + String keyId = result.first.trim(); + assertThat(keyId).matches("^\\d+$"); + return keyId; + } + + private int updateFontFile(String fontPath, String signaturePath) throws IOException { + byte[] signature = Files.readAllBytes(Paths.get(signaturePath)); + try (ParcelFileDescriptor fd = + ParcelFileDescriptor.open(new File(fontPath), MODE_READ_ONLY)) { + return SystemUtil.runWithShellPermissionIdentity(() -> { + FontConfig fontConfig = mFontManager.getFontConfig(); + return mFontManager.updateFontFamily( + new FontFamilyUpdateRequest.Builder() + .addFontFileUpdateRequest(new FontFileUpdateRequest(fd, signature)) + .build(), + fontConfig.getConfigVersion()); + }); } - CLog.e("Font not found: " + fontFileName); - return null; } - private void startActivity(String appId, String activityId) throws Exception { - // Make sure that the app is installed and enabled. - waitUntil(ACTIVITY_TIMEOUT_MILLIS, () -> { - String packageInfo = expectRemoteCommandToSucceed( - "pm list packages -e " + EMOJI_RENDERING_TEST_APP_ID); - return !packageInfo.isEmpty(); + private String getFontPath(String psName) { + return SystemUtil.runWithShellPermissionIdentity(() -> { + FontConfig fontConfig = mFontManager.getFontConfig(); + for (FontConfig.FontFamily family : fontConfig.getFontFamilies()) { + for (FontConfig.Font font : family.getFontList()) { + if (psName.equals(font.getPostScriptName())) { + return font.getFile().getAbsolutePath(); + } + } + } + throw new AssertionError("Font not found: " + psName); }); - expectRemoteCommandToSucceed("am force-stop " + EMOJI_RENDERING_TEST_APP_ID); - expectRemoteCommandToSucceed("am start-activity -n " + EMOJI_RENDERING_TEST_ACTIVITY); } - private String expectRemoteCommandToSucceed(String cmd) throws Exception { - CommandResult result = getDevice().executeShellV2Command(cmd); - assertWithMessage("`" + cmd + "` failed: " + result.getStderr()) - .that(result.getStatus()) - .isEqualTo(CommandStatus.SUCCESS); - return result.getStdout(); + private static void startActivity(String appId, String activityId) throws Exception { + expectCommandToSucceed("am force-stop " + appId); + expectCommandToSucceed("am start-activity -n " + activityId); + } + + private static String expectCommandToSucceed(String cmd) throws IOException { + Pair<String, String> result = runShellCommand(cmd, null); + // UiAutomation.runShellCommand() does not return exit code. + // Assume that the command fails if stderr is not empty. + assertThat(result.second.trim()).isEmpty(); + return result.first; } - private void expectRemoteCommandToFail(String cmd) throws Exception { - CommandResult result = getDevice().executeShellV2Command(cmd); - assertWithMessage("Unexpected success from `" + cmd + "`: " + result.getStderr()) - .that(result.getStatus()) - .isNotEqualTo(CommandStatus.SUCCESS); + private static void expectCommandToFail(String cmd) throws IOException { + Pair<String, String> result = runShellCommand(cmd, null); + // UiAutomation.runShellCommand() does not return exit code. + // Assume that the command fails if stderr is not empty. + assertThat(result.second.trim()).isNotEmpty(); } - private void waitUntil(long timeoutMillis, ThrowingSupplier<Boolean> func) { - long untilMillis = System.currentTimeMillis() + timeoutMillis; - do { - try { - if (func.get()) return; - Thread.sleep(100); - } catch (InterruptedException e) { - throw new AssertionError("Interrupted", e); - } catch (Exception e) { - throw new AssertionError("Unexpected exception", e); + /** Runs a command and returns (stdout, stderr). */ + private static Pair<String, String> runShellCommand(String cmd, @Nullable InputStream input) + throws IOException { + Log.i(TAG, "runShellCommand: " + cmd); + UiAutomation automation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); + ParcelFileDescriptor[] rwe = automation.executeShellCommandRwe(cmd); + // executeShellCommandRwe returns [stdout, stdin, stderr]. + try (ParcelFileDescriptor outFd = rwe[0]; + ParcelFileDescriptor inFd = rwe[1]; + ParcelFileDescriptor errFd = rwe[2]) { + if (input != null) { + try (OutputStream os = new FileOutputStream(inFd.getFileDescriptor())) { + StreamUtil.copyStreams(input, os); + } } - } while (System.currentTimeMillis() < untilMillis); - throw new AssertionError("Timed out"); + // We have to close stdin before reading stdout and stderr. + // It's safe to close ParcelFileDescriptor multiple times. + inFd.close(); + String stdout; + try (InputStream is = new FileInputStream(outFd.getFileDescriptor())) { + stdout = StreamUtil.readInputStream(is); + } + Log.i(TAG, "stdout = " + stdout); + String stderr; + try (InputStream is = new FileInputStream(errFd.getFileDescriptor())) { + stderr = StreamUtil.readInputStream(is); + } + Log.i(TAG, "stderr = " + stderr); + return new Pair<>(stdout, stderr); + } } - private boolean isFileOpenedBy(String path, String appId) throws DeviceNotAvailableException { + private static boolean isFileOpenedBy(String path, String appId) throws Exception { String pid = pidOf(appId); if (pid.isEmpty()) { return false; } - CommandResult result = getDevice().executeShellV2Command( - String.format("lsof -t -p %s '%s'", pid, path)); - if (result.getStatus() != CommandStatus.SUCCESS) { - return false; - } - // The file is open if the output of lsof is non-empty. - return !result.getStdout().trim().isEmpty(); + String cmd = String.format("lsof -t -p %s %s", pid, path); + return !expectCommandToSucceed(cmd).trim().isEmpty(); } - private String pidOf(String appId) throws DeviceNotAvailableException { - CommandResult result = getDevice().executeShellV2Command("pidof " + appId); - if (result.getStatus() != CommandStatus.SUCCESS) { - return ""; - } - return result.getStdout().trim(); + private static String pidOf(String appId) throws Exception { + return expectCommandToSucceed("pidof " + appId).trim(); } } diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp index c75ba71c4432..a19d183d617b 100644 --- a/tools/aapt/Android.bp +++ b/tools/aapt/Android.bp @@ -124,6 +124,9 @@ cc_binary_host { srcs: ["Main.cpp"], use_version_lib: true, static_libs: ["libaapt"], + dist: { + targets: ["aapt2_artifacts"], + }, } // ========================================================== diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 21386b88ce2c..f2c3b86e409e 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -969,6 +969,8 @@ int doDump(Bundle* bundle) densities.add(dens); } + std::vector<ResXMLParser::ResXMLPosition> tagsToSkip; + size_t len; ResXMLTree::event_code_t code; int depth = 0; @@ -1091,6 +1093,42 @@ int doDump(Bundle* bundle) Vector<FeatureGroup> featureGroups; KeyedVector<String8, ImpliedFeature> impliedFeatures; + { + int curDepth = 0; + ResXMLParser::ResXMLPosition initialPos; + tree.getPosition(&initialPos); + + // Find all of the "uses-sdk" tags within the "manifest" tag. + std::vector<ResXMLParser::ResXMLPosition> usesSdkTagPositions; + ResXMLParser::ResXMLPosition curPos; + while ((code = tree.next()) != ResXMLTree::END_DOCUMENT && + code != ResXMLTree::BAD_DOCUMENT) { + if (code == ResXMLTree::END_TAG) { + curDepth--; + continue; + } + if (code == ResXMLTree::START_TAG) { + curDepth++; + } + const char16_t* ctag16 = tree.getElementName(&len); + if (ctag16 == NULL || String8(ctag16) != "uses-sdk" || curDepth != 2) { + continue; + } + + tree.getPosition(&curPos); + usesSdkTagPositions.emplace_back(curPos); + } + + // Skip all "uses-sdk" tags besides the very last tag. The android runtime only uses + // the attribute values from the last defined tag. + for (size_t i = 0; i < usesSdkTagPositions.size() - 1; i++) { + tagsToSkip.emplace_back(usesSdkTagPositions[i]); + } + + // Reset the position before parsing. + tree.setPosition(initialPos); + } + while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::END_TAG) { @@ -1202,8 +1240,25 @@ int doDump(Bundle* bundle) if (code != ResXMLTree::START_TAG) { continue; } + depth++; + // If this tag should be skipped, skip to the end of this tag. + ResXMLParser::ResXMLPosition curPos; + tree.getPosition(&curPos); + if (std::find(tagsToSkip.begin(), tagsToSkip.end(), curPos) != tagsToSkip.end()) { + const int breakDepth = depth - 1; + while ((code = tree.next()) != ResXMLTree::END_DOCUMENT && + code != ResXMLTree::BAD_DOCUMENT) { + if (code == ResXMLTree::END_TAG && --depth == breakDepth) { + break; + } else if (code == ResXMLTree::START_TAG) { + depth++; + } + } + continue; + } + const char16_t* ctag16 = tree.getElementName(&len); if (ctag16 == NULL) { SourcePos(manifestFile, tree.getLineNumber()).error( diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index f29c9185cafa..61ba09b6a3c9 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -132,6 +132,12 @@ class ManifestExtractor { /** Adds an element to the list of children of the element. */ void AddChild(std::unique_ptr<Element>& child) { children_.push_back(std::move(child)); } + template <typename Predicate> + void Filter(Predicate&& func) { + children_.erase(std::remove_if(children_.begin(), children_.end(), + [&](const auto& e) { return func(e.get()); })); + } + /** Retrieves the list of children of the element. */ const std::vector<std::unique_ptr<Element>>& children() const { return children_; @@ -1963,6 +1969,21 @@ bool ManifestExtractor::Dump(text::Printer* printer, IDiagnostics* diag) { // Extract badging information auto root = Visit(element); + // Filter out all "uses-sdk" tags besides the very last tag. The android runtime only uses the + // attribute values from the last defined tag. + std::vector<UsesSdkBadging*> filtered_uses_sdk_tags; + for (const auto& child : root->children()) { + if (auto uses_sdk = ElementCast<UsesSdkBadging>(child.get())) { + filtered_uses_sdk_tags.emplace_back(uses_sdk); + } + } + filtered_uses_sdk_tags.pop_back(); + + root->Filter([&](const ManifestExtractor::Element* e) { + return std::find(filtered_uses_sdk_tags.begin(), filtered_uses_sdk_tags.end(), e) != + filtered_uses_sdk_tags.end(); + }); + // Print the elements in order seen Print(root.get(), printer); |