diff options
207 files changed, 2757 insertions, 1849 deletions
diff --git a/.clang-format b/.clang-format index 03af56d64062..021d9382d62b 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ BasedOnStyle: Google AccessModifierOffset: -4 AlignOperands: false -AllowShortFunctionsOnASingleLine: Inline +AllowShortFunctionsOnASingleLine: Empty AlwaysBreakBeforeMultilineStrings: false ColumnLimit: 100 CommentPragmas: NOLINT:.* diff --git a/Android.bp b/Android.bp index 62d2632a8af6..b4e02c0a092f 100644 --- a/Android.bp +++ b/Android.bp @@ -345,6 +345,7 @@ java_defaults { "framework-permission-aidl-java", "spatializer-aidl-java", "audiopolicy-types-aidl-java", + "modules-utils-expresslog", ], } @@ -531,7 +532,7 @@ filegroup { "core/java/**/*.logtags", "**/package.html", ], - visibility: ["//visibility:private"], + visibility: ["//frameworks/base/api"], } // Defaults for all stubs that include the non-updatable framework. These defaults do not include @@ -545,12 +546,10 @@ stubs_defaults { java_version: "1.8", arg_files: [":frameworks-base-core-AndroidManifest.xml"], aidl: { - local_include_dirs: [ - "media/aidl", - "telephony/java", - ], include_dirs: [ "frameworks/av/aidl", + "frameworks/base/media/aidl", + "frameworks/base/telephony/java", "frameworks/native/libs/permission/aidl", "packages/modules/Bluetooth/framework/aidl-export", "packages/modules/Connectivity/framework/aidl-export", @@ -582,7 +581,7 @@ stubs_defaults { annotations_enabled: true, previous_api: ":android.api.public.latest", merge_annotations_dirs: ["metalava-manual"], - defaults_visibility: ["//visibility:private"], + defaults_visibility: ["//frameworks/base/api"], visibility: ["//frameworks/base/api"], } @@ -610,12 +609,9 @@ stubs_defaults { // NOTE: The below can be removed once the prebuilt stub contains IKE. "sdk_system_current_android.net.ipsec.ike", ], - defaults_visibility: ["//visibility:private"], } build = [ - "StubLibraries.bp", - "ApiDocs.bp", "ProtoLibraries.bp", "TestProtoLibraries.bp", ] diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp index 9064b4494ed1..2590fe3d843f 100644 --- a/apct-tests/perftests/blobstore/Android.bp +++ b/apct-tests/perftests/blobstore/Android.bp @@ -29,7 +29,7 @@ android_test { "androidx.test.rules", "androidx.annotation_annotation", "apct-perftests-utils", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "collector-device-lib-platform", "androidx.benchmark_benchmark-macro", ], diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java index 0208dab33746..4e4780ff8948 100644 --- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java +++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java @@ -21,10 +21,10 @@ import android.app.UiAutomation; import android.os.ParcelFileDescriptor; import android.perftests.utils.TraceMarkParser; import android.perftests.utils.TraceMarkParser.TraceMarkSlice; -import android.support.test.uiautomator.UiDevice; import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import java.io.BufferedReader; import java.io.IOException; diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java index 03e5468a342a..3cd9f50aee6a 100644 --- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java +++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java @@ -25,12 +25,12 @@ import android.perftests.utils.ManualBenchmarkState; import android.perftests.utils.PerfManualStatusReporter; import android.perftests.utils.TraceMarkParser; import android.perftests.utils.TraceMarkParser.TraceMarkSlice; -import android.support.test.uiautomator.UiDevice; import android.util.DataUnit; import androidx.benchmark.macro.MacrobenchmarkScope; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import com.android.utils.blob.FakeBlobData; diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java index 80a70a6e9e9e..1cd1a4611a94 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java @@ -31,7 +31,7 @@ import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.expresslog.Counter; +import com.android.modules.expresslog.Counter; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateControllerProto; diff --git a/api/Android.bp b/api/Android.bp index 9d20eca75f8f..f40f0c990f72 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -252,3 +252,8 @@ java_genrule { out: ["api_fingerprint.txt"], cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)", } + +build = [ + "ApiDocs.bp", + "StubLibraries.bp", +] diff --git a/ApiDocs.bp b/api/ApiDocs.bp index a46ecce5c721..fbcaa52f9bb4 100644 --- a/ApiDocs.bp +++ b/api/ApiDocs.bp @@ -182,10 +182,10 @@ droidstubs { // using droiddoc ///////////////////////////////////////////////////////////////////// -framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " + +framework_docs_only_args = " -android -manifest $(location :frameworks-base-core-AndroidManifest.xml) " + "-metalavaApiSince " + "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " + - "-overview $(location core/java/overview.html) " + + "-overview $(location :frameworks-base-java-overview) " + // Federate Support Library references against local API file. "-federate SupportLib https://developer.android.com " + "-federationapi SupportLib $(location :current-support-api) " + @@ -218,16 +218,16 @@ doc_defaults { "sdk.preview 0", ], arg_files: [ - "core/res/AndroidManifest.xml", - "core/java/overview.html", + ":frameworks-base-core-AndroidManifest.xml", + ":frameworks-base-java-overview", ":current-support-api", ":current-androidx-api", ], // TODO(b/169090544): remove below aidl includes. aidl: { - local_include_dirs: ["media/aidl"], include_dirs: [ "frameworks/av/aidl", + "frameworks/base/media/aidl", "frameworks/native/libs/permission/aidl", ], }, diff --git a/StubLibraries.bp b/api/StubLibraries.bp index b005591980c0..f08745b5cd2c 100644 --- a/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -515,6 +515,7 @@ droidstubs { ], api_levels_sdk_type: "public", extensions_info_file: ":sdk-extensions-info", + visibility: ["//frameworks/base"], } droidstubs { diff --git a/api/api.go b/api/api.go index 09c238336a39..af817b5666cd 100644 --- a/api/api.go +++ b/api/api.go @@ -15,7 +15,9 @@ package api import ( + "fmt" "sort" + "strings" "github.com/google/blueprint/proptools" @@ -102,6 +104,13 @@ type fgProps struct { Visibility []string } +type defaultsProps struct { + Name *string + Api_surface *string + Api_contributions []string + Defaults_visibility []string +} + type Bazel_module struct { Bp2build_available *bool } @@ -164,26 +173,26 @@ func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { } func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) { - for _, i := range []struct{ + for _, i := range []struct { name string tag string modules []string }{ { - name: "all-modules-public-annotations", - tag: "{.public.annotations.zip}", + name: "all-modules-public-annotations", + tag: "{.public.annotations.zip}", modules: modules, }, { - name: "all-modules-system-annotations", - tag: "{.system.annotations.zip}", + name: "all-modules-system-annotations", + tag: "{.system.annotations.zip}", modules: modules, }, { - name: "all-modules-module-lib-annotations", - tag: "{.module-lib.annotations.zip}", + name: "all-modules-module-lib-annotations", + tag: "{.module-lib.annotations.zip}", modules: modules, }, { - name: "all-modules-system-server-annotations", - tag: "{.system-server.annotations.zip}", + name: "all-modules-system-server-annotations", + tag: "{.system-server.annotations.zip}", modules: system_server_modules, }, } { @@ -329,6 +338,30 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ } } +func createApiContributionDefaults(ctx android.LoadHookContext, modules []string) { + defaultsSdkKinds := []android.SdkKind{ + android.SdkPublic, android.SdkSystem, android.SdkModule, + } + for _, sdkKind := range defaultsSdkKinds { + props := defaultsProps{} + props.Name = proptools.StringPtr( + sdkKind.DefaultJavaLibraryName() + "_contributions") + if sdkKind == android.SdkModule { + props.Name = proptools.StringPtr( + sdkKind.DefaultJavaLibraryName() + "_contributions_full") + } + props.Api_surface = proptools.StringPtr(sdkKind.String()) + apiSuffix := "" + if sdkKind != android.SdkPublic { + apiSuffix = "." + strings.ReplaceAll(sdkKind.String(), "-", "_") + } + props.Api_contributions = transformArray( + modules, "", fmt.Sprintf(".stubs.source%s.api.contribution", apiSuffix)) + props.Defaults_visibility = []string{"//visibility:public"} + ctx.CreateModule(java.DefaultsFactory, &props) + } +} + func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { bootclasspath := a.properties.Bootclasspath system_server_classpath := a.properties.System_server_classpath @@ -347,6 +380,8 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath) createPublicStubsSourceFilegroup(ctx, bootclasspath) + + createApiContributionDefaults(ctx, bootclasspath) } func combinedApisModuleFactory() android.Module { @@ -374,7 +409,7 @@ func (a *CombinedApis) ConvertWithBp2build(ctx android.TopDownMutatorContext) { "system-server": "-system-server-current.txt", } - for scopeName, suffix := range scopeToSuffix{ + for scopeName, suffix := range scopeToSuffix { name := a.Name() + suffix var scope bazel.StringAttribute diff --git a/api/docs b/api/docs new file mode 120000 index 000000000000..a9594bfe4ab6 --- /dev/null +++ b/api/docs @@ -0,0 +1 @@ +../docs
\ No newline at end of file diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 6b6bc9728b7f..27dadda40407 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,6 +107,7 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; +static const int MAX_CHECK_EXIT_INTERVAL_US = 50000; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; @@ -1680,7 +1681,17 @@ bool BootAnimation::playAnimation(const Animation& animation) { checkExit(); } - usleep(part.pause * ns2us(frameDuration)); + int pauseDuration = part.pause * ns2us(frameDuration); + while(pauseDuration > 0 && !exitPending()){ + if (pauseDuration > MAX_CHECK_EXIT_INTERVAL_US) { + usleep(MAX_CHECK_EXIT_INTERVAL_US); + pauseDuration -= MAX_CHECK_EXIT_INTERVAL_US; + } else { + usleep(pauseDuration); + break; + } + checkExit(); + } if (exitPending() && !part.count && mCurrentInset >= mTargetInset && !part.hasFadingPhase()) { diff --git a/core/api/current.txt b/core/api/current.txt index cf3938ade32d..77a6fec604be 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -31081,6 +31081,7 @@ package android.os { field public static final int S_V2 = 32; // 0x20 field public static final int TIRAMISU = 33; // 0x21 field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710 + field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index c6c4daf7b0ac..13a48993f68f 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -17,10 +17,19 @@ package android.app { public class ActivityManager { method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]); + method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener); + method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); } + public static interface ActivityManager.UidFrozenStateChangedCallback { + method public void onUidFrozenStateChanged(@NonNull int[], @NonNull int[]); + field public static final int UID_FROZEN_STATE_FROZEN = 1; // 0x1 + field public static final int UID_FROZEN_STATE_UNFROZEN = 2; // 0x2 + } + public class AppOpsManager { field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage"; } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 6a5ef3a67488..dc0166285cbb 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -122,16 +122,19 @@ package android.app { method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener); method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName); method public long getTotalRam(); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]); method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessCapabilities(int); method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessState(int); method public void holdLock(android.os.IBinder, int); method public static boolean isHighEndGfx(); + method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener); method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors(); method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void setStopUserOnSwitch(int); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int, boolean); + method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle(); field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL @@ -161,6 +164,12 @@ package android.app { method @Nullable public String getIconResourcePackage(); } + public static interface ActivityManager.UidFrozenStateChangedCallback { + method public void onUidFrozenStateChanged(@NonNull int[], @NonNull int[]); + field public static final int UID_FROZEN_STATE_FROZEN = 1; // 0x1 + field public static final int UID_FROZEN_STATE_UNFROZEN = 2; // 0x2 + } + public class ActivityOptions { method public boolean isEligibleForLegacyPermissionPrompt(); method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); @@ -3469,7 +3478,7 @@ package android.window { public class WindowOrganizer { ctor public WindowOrganizer(); - method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback); method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public void applyTransaction(@NonNull android.window.WindowContainerTransaction); } diff --git a/core/java/Android.bp b/core/java/Android.bp index 7df3d1e13aa0..8ceea92957ed 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -429,6 +429,11 @@ aidl_interface { }, } +filegroup { + name: "frameworks-base-java-overview", + srcs: ["overview.html"], +} + // Avoid including Parcelable classes as we don't want to have two copies of // Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony) // and TeleService app (packages/services/Telephony). diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index c17fbf19516b..dd955406e690 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -2523,6 +2523,10 @@ public abstract class AccessibilityService extends Service { IAccessibilityServiceConnection connection = AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId); if (mInfo != null && connection != null) { + if (!mInfo.isWithinParcelableSize()) { + throw new IllegalStateException( + "Cannot update service info: size is larger than safe parcelable limits."); + } try { connection.setServiceInfo(mInfo); mInfo = null; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 530de0f3af6b..0cbcdb5a2b62 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -40,6 +40,7 @@ import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; @@ -1128,6 +1129,15 @@ public class AccessibilityServiceInfo implements Parcelable { return 0; } + /** @hide */ + public final boolean isWithinParcelableSize() { + final Parcel parcel = Parcel.obtain(); + writeToParcel(parcel, 0); + final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE; + parcel.recycle(); + return result; + } + public void writeToParcel(Parcel parcel, int flagz) { parcel.writeInt(eventTypes); parcel.writeStringArray(packageNames); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d24b677b1d72..e85fa9d46d10 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -959,7 +959,7 @@ public class Activity extends ContextThemeWrapper private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE; private SpannableStringBuilder mDefaultKeySsb = null; - private ActivityManager.TaskDescription mTaskDescription = + private final ActivityManager.TaskDescription mTaskDescription = new ActivityManager.TaskDescription(); protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused}; @@ -970,7 +970,7 @@ public class Activity extends ContextThemeWrapper private Thread mUiThread; @UnsupportedAppUsage - ActivityTransitionState mActivityTransitionState = new ActivityTransitionState(); + final ActivityTransitionState mActivityTransitionState = new ActivityTransitionState(); SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK; SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK; @@ -1839,7 +1839,7 @@ public class Activity extends ContextThemeWrapper final int numDialogs = ids.length; mManagedDialogs = new SparseArray<ManagedDialog>(numDialogs); for (int i = 0; i < numDialogs; i++) { - final Integer dialogId = ids[i]; + final int dialogId = ids[i]; Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId)); if (dialogState != null) { // Calling onRestoreInstanceState() below will invoke dispatchOnCreate @@ -1909,7 +1909,7 @@ public class Activity extends ContextThemeWrapper * <code>persistAcrossReboots</code>. * * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState} - * @param persistentState The data caming from the PersistableBundle first + * @param persistentState The data coming from the PersistableBundle first * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}. * * @see #onCreate @@ -5058,7 +5058,7 @@ public class Activity extends ContextThemeWrapper * This hook is called when the user signals the desire to start a search. * * <p>You can use this function as a simple way to launch the search UI, in response to a - * menu item, search button, or other widgets within your activity. Unless overidden, + * menu item, search button, or other widgets within your activity. Unless overridden, * calling this function is the same as calling * {@link #startSearch startSearch(null, false, null, false)}, which launches * search for the current activity as specified in its manifest, see {@link SearchManager}. @@ -8797,7 +8797,7 @@ public class Activity extends ContextThemeWrapper * @see Activity#convertFromTranslucent() * @see Activity#convertToTranslucent(TranslucentConversionListener, ActivityOptions) */ - public void onTranslucentConversionComplete(boolean drawComplete); + void onTranslucentConversionComplete(boolean drawComplete); } private void dispatchRequestPermissionsResult(int requestCode, Intent data) { @@ -8920,7 +8920,7 @@ public class Activity extends ContextThemeWrapper /** * Registers remote animations per transition type for this activity. * - * @param definition The remote animation definition that defines which transition whould run + * @param definition The remote animation definition that defines which transition would run * which remote animation. * @hide */ diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index d328b34a2a8f..932866468314 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -231,6 +231,114 @@ public class ActivityManager { final ArrayMap<OnUidImportanceListener, UidObserver> mImportanceListeners = new ArrayMap<>(); /** + * Callback object for {@link #registerUidFrozenStateChangedCallback} + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public interface UidFrozenStateChangedCallback { + /** + * Indicates that the UID was frozen. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + int UID_FROZEN_STATE_FROZEN = 1; + + /** + * Indicates that the UID was unfrozen. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + int UID_FROZEN_STATE_UNFROZEN = 2; + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = false, prefix = {"UID_FROZEN_STATE_"}, value = { + UID_FROZEN_STATE_FROZEN, + UID_FROZEN_STATE_UNFROZEN, + }) + public @interface UidFrozenState {} + + /** + * Notify the client that the frozen states of an array of UIDs have changed. + * + * @param uids The UIDs for which the frozen state has changed + * @param frozenStates Frozen state for each UID index, Will be set to + * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN} + * when the UID is frozen. When the UID is unfrozen, + * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN} + * will be set. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + void onUidFrozenStateChanged(@NonNull int[] uids, + @NonNull @UidFrozenState int[] frozenStates); + } + + /** + * Register a {@link UidFrozenStateChangedCallback} object to receive notification + * when a UID is frozen or unfrozen. Will throw an exception if the same + * callback object is registered more than once. + * + * @param executor The executor that the callback will be run from. + * @param callback The callback to be registered. Callbacks for previous frozen/unfrozen + * UID changes will not be delivered. Only changes in state from the point of + * registration onward will be reported. + * @throws IllegalStateException if the {@code callback} is already registered. + * + * @hide + */ + @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public void registerUidFrozenStateChangedCallback( + @NonNull Executor executor, + @NonNull UidFrozenStateChangedCallback callback) { + } + + /** + * Unregister a {@link UidFrozenStateChangedCallback} callback. + * @param callback The callback to be unregistered. + * + * @hide + */ + @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public void unregisterUidFrozenStateChangedCallback( + @NonNull UidFrozenStateChangedCallback callback) { + } + + /** + * Query the frozen state of a list of UIDs. + * + * @param uids the array of UIDs which the client would like to know the frozen state of. + * @return An array containing the frozen state for each requested UID, by index. Will be set + * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN} + * if the UID is frozen. If the UID is not frozen or not found, + * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN} + * will be set. + * + * @hide + */ + @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public @NonNull @UidFrozenStateChangedCallback.UidFrozenState + int[] getUidFrozenState(@NonNull int[] uids) { + return new int[uids.length]; + } + + /** * <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code * <meta-data>}</a> name for a 'home' Activity that declares a package that is to be * uninstalled in lieu of the declaring one. The package named here must be diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5ba7a4cb4f54..a1e4dbf0b50d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -266,7 +266,6 @@ public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal { /** @hide */ public static final String TAG = "ActivityThread"; - private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; static final boolean localLOGV = false; static final boolean DEBUG_MESSAGES = false; /** @hide */ @@ -368,7 +367,7 @@ public final class ActivityThread extends ClientTransactionHandler private final AtomicInteger mNumLaunchingActivities = new AtomicInteger(); @GuardedBy("mAppThread") private int mLastProcessState = PROCESS_STATE_UNKNOWN; - ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>(); + final ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>(); private int mLastSessionId; final ArrayMap<IBinder, CreateServiceData> mServicesData = new ArrayMap<>(); @UnsupportedAppUsage @@ -564,7 +563,7 @@ public final class ActivityThread extends ClientTransactionHandler Configuration createdConfig; Configuration overrideConfig; // Used for consolidating configs before sending on to Activity. - private Configuration tmpConfig = new Configuration(); + private final Configuration tmpConfig = new Configuration(); // Callback used for updating activity override config and camera compat control state. ViewRootImpl.ActivityConfigCallback activityConfigCallback; ActivityClientRecord nextIdle; @@ -769,7 +768,7 @@ public final class ActivityThread extends ClientTransactionHandler } } - final class ProviderClientRecord { + static final class ProviderClientRecord { final String[] mNames; @UnsupportedAppUsage final IContentProvider mProvider; @@ -796,7 +795,7 @@ public final class ActivityThread extends ClientTransactionHandler } @UnsupportedAppUsage - Intent intent; + final Intent intent; @UnsupportedAppUsage ActivityInfo info; @UnsupportedAppUsage @@ -3336,11 +3335,8 @@ public final class ActivityThread extends ClientTransactionHandler public void registerOnActivityPausedListener(Activity activity, OnActivityPausedListener listener) { synchronized (mOnPauseListeners) { - ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); - if (list == null) { - list = new ArrayList<OnActivityPausedListener>(); - mOnPauseListeners.put(activity, list); - } + ArrayList<OnActivityPausedListener> list = + mOnPauseListeners.computeIfAbsent(activity, k -> new ArrayList<>()); list.add(listener); } } @@ -5400,7 +5396,7 @@ public final class ActivityThread extends ClientTransactionHandler /** Core implementation of activity destroy call. */ void performDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) { - Class<? extends Activity> activityClass = null; + Class<? extends Activity> activityClass; if (localLOGV) Slog.v(TAG, "Performing finish of " + r); activityClass = r.activity.getClass(); r.activity.mConfigChangeFlags |= configChanges; @@ -7051,7 +7047,7 @@ public final class ActivityThread extends ClientTransactionHandler // Note that we cannot hold the lock while acquiring and installing the // provider since it might take a long time to run and it could also potentially // be re-entrant in the case where the provider is in the same process. - ContentProviderHolder holder = null; + ContentProviderHolder holder; final ProviderKey key = getGetProviderKey(auth, userId); try { synchronized (key) { @@ -7105,11 +7101,7 @@ public final class ActivityThread extends ClientTransactionHandler private ProviderKey getGetProviderKey(String auth, int userId) { final ProviderKey key = new ProviderKey(auth, userId); synchronized (mGetProviderKeys) { - ProviderKey lock = mGetProviderKeys.get(key); - if (lock == null) { - lock = key; - mGetProviderKeys.put(key, lock); - } + ProviderKey lock = mGetProviderKeys.computeIfAbsent(key, k -> k); return lock; } } @@ -7744,7 +7736,7 @@ public final class ActivityThread extends ClientTransactionHandler if (!DEPRECATE_DATA_COLUMNS) return; // Install interception and make sure it sticks! - Os def = null; + Os def; do { def = Os.getDefault(); } while (!Os.compareAndSetDefault(def, new AndroidOs(def))); diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java index 37be90160d9a..f266769a3abf 100644 --- a/core/java/android/app/AliasActivity.java +++ b/core/java/android/app/AliasActivity.java @@ -16,9 +16,6 @@ package android.app; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; @@ -29,13 +26,16 @@ import android.util.Xml; import com.android.internal.util.XmlUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; /** * Stub activity that launches another activity (and then finishes itself) * based on information in its component's manifest meta-data. This is a * simple way to implement an alias-like mechanism. - * + * * To use this activity, you should include in the manifest for the associated * component an entry named "android.app.alias". It is a reference to an XML * resource describing an intent that launches the real application. @@ -51,11 +51,11 @@ public class AliasActivity extends Activity { * {@hide} */ public final String ALIAS_META_DATA = "android.app.alias"; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + XmlResourceParser parser = null; try { ActivityInfo ai = getPackageManager().getActivityInfo( @@ -66,21 +66,17 @@ public class AliasActivity extends Activity { throw new RuntimeException("Alias requires a meta-data field " + ALIAS_META_DATA); } - + Intent intent = parseAlias(parser); if (intent == null) { throw new RuntimeException( "No <intent> tag found in alias description"); } - + startActivity(intent); finish(); - - } catch (PackageManager.NameNotFoundException e) { - throw new RuntimeException("Error parsing alias", e); - } catch (XmlPullParserException e) { - throw new RuntimeException("Error parsing alias", e); - } catch (IOException e) { + + } catch (PackageManager.NameNotFoundException | XmlPullParserException | IOException e) { throw new RuntimeException("Error parsing alias", e); } finally { if (parser != null) parser.close(); @@ -90,21 +86,21 @@ public class AliasActivity extends Activity { private Intent parseAlias(XmlPullParser parser) throws XmlPullParserException, IOException { AttributeSet attrs = Xml.asAttributeSet(parser); - + Intent intent = null; - + int type; while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { } - + String nodeName = parser.getName(); if (!"alias".equals(nodeName)) { throw new RuntimeException( "Alias meta-data must start with <alias> tag; found" + nodeName + " at " + parser.getPositionDescription()); } - + int outerDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -120,8 +116,8 @@ public class AliasActivity extends Activity { XmlUtils.skipCurrentTag(parser); } } - + return intent; } - + } diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java index bd5d1057f5bf..05742e658704 100644 --- a/core/java/android/app/SearchableInfo.java +++ b/core/java/android/app/SearchableInfo.java @@ -535,7 +535,7 @@ public final class SearchableInfo implements Parcelable { */ public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo, int userId) { - Context userContext = null; + Context userContext; try { userContext = context.createPackageContextAsUser("system", 0, new UserHandle(userId)); diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java index 99d406446dae..e563de20d6d6 100644 --- a/core/java/android/app/WallpaperInfo.java +++ b/core/java/android/app/WallpaperInfo.java @@ -96,31 +96,30 @@ public final class WallpaperInfo implements Parcelable { throws XmlPullParserException, IOException { mService = service; ServiceInfo si = service.serviceInfo; - + final PackageManager pm = context.getPackageManager(); - XmlResourceParser parser = null; - try { - parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA); + try (XmlResourceParser parser = si.loadXmlMetaData(pm, + WallpaperService.SERVICE_META_DATA)) { if (parser == null) { throw new XmlPullParserException("No " + WallpaperService.SERVICE_META_DATA + " meta-data"); } - + Resources res = pm.getResourcesForApplication(si.applicationInfo); - + AttributeSet attrs = Xml.asAttributeSet(parser); - + int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { } - + String nodeName = parser.getName(); if (!"wallpaper".equals(nodeName)) { throw new XmlPullParserException( "Meta-data does not start with wallpaper tag"); } - + TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.Wallpaper); mSettingsActivityName = sa.getString( @@ -159,8 +158,6 @@ public final class WallpaperInfo implements Parcelable { } catch (NameNotFoundException e) { throw new XmlPullParserException( "Unable to create context for: " + si.packageName); - } finally { - if (parser != null) parser.close(); } } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index dea1a050a27a..75b450db9299 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1629,7 +1629,6 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - boolean ok = false; try { fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); copyStreamToWallpaperFile(resources.openRawResource(resid), fos); diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS index e857c72bb28e..80ecaa41dbf3 100644 --- a/core/java/android/app/assist/OWNERS +++ b/core/java/android/app/assist/OWNERS @@ -3,3 +3,5 @@ joannechung@google.com markpun@google.com lpeter@google.com tymtsai@google.com +hackz@google.com +volnov@google.com
\ No newline at end of file diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2ea0d8235548..a320f1e9509c 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -11488,7 +11488,7 @@ public class Intent implements Parcelable, Cloneable { private void toUriInner(StringBuilder uri, String scheme, String defAction, String defPackage, int flags) { if (scheme != null) { - uri.append("scheme=").append(scheme).append(';'); + uri.append("scheme=").append(Uri.encode(scheme)).append(';'); } if (mAction != null && !mAction.equals(defAction)) { uri.append("action=").append(Uri.encode(mAction)).append(';'); diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index b1252fd0b21f..49d3cac63124 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -19,6 +19,7 @@ package android.content; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.PendingIntentInfo; +import android.app.ActivityOptions; import android.compat.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.os.Handler; @@ -158,7 +159,7 @@ public class IntentSender implements Parcelable { */ public void sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler) throws SendIntentException { - sendIntent(context, code, intent, onFinished, handler, null); + sendIntent(context, code, intent, onFinished, handler, null, null /* options */); } /** @@ -190,6 +191,42 @@ public class IntentSender implements Parcelable { public void sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission) throws SendIntentException { + sendIntent(context, code, intent, onFinished, handler, requiredPermission, + null /* options */); + } + + /** + * Perform the operation associated with this IntentSender, allowing the + * caller to specify information about the Intent to use and be notified + * when the send has completed. + * + * @param context The Context of the caller. This may be null if + * <var>intent</var> is also null. + * @param code Result code to supply back to the IntentSender's target. + * @param intent Additional Intent data. See {@link Intent#fillIn + * Intent.fillIn()} for information on how this is applied to the + * original Intent. Use null to not modify the original Intent. + * @param onFinished The object to call back on when the send has + * completed, or null for no callback. + * @param handler Handler identifying the thread on which the callback + * should happen. If null, the callback will happen from the thread + * pool of the process. + * @param requiredPermission Name of permission that a recipient of the PendingIntent + * is required to hold. This is only valid for broadcast intents, and + * corresponds to the permission argument in + * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. + * If null, no permission is required. + * @param options Additional options the caller would like to provide to modify the sending + * behavior. May be built from an {@link ActivityOptions} to apply to an activity start. + * + * @throws SendIntentException Throws CanceledIntentException if the IntentSender + * is no longer allowing more intents to be sent through it. + * @hide + */ + public void sendIntent(Context context, int code, Intent intent, + OnFinished onFinished, Handler handler, String requiredPermission, + @Nullable Bundle options) + throws SendIntentException { try { String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) @@ -199,7 +236,7 @@ public class IntentSender implements Parcelable { onFinished != null ? new FinishedDispatcher(this, onFinished, handler) : null, - requiredPermission, null); + requiredPermission, options); if (res < 0) { throw new SendIntentException(); } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index a6c79b3a289f..9179f5de1a4f 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -2228,6 +2228,12 @@ public class CameraDeviceImpl extends CameraDevice } else { List<CaptureResult> partialResults = mFrameNumberTracker.popPartialResults(frameNumber); + if (mBatchOutputMap.containsKey(requestId)) { + int requestCount = mBatchOutputMap.get(requestId); + for (int i = 1; i < requestCount; i++) { + mFrameNumberTracker.popPartialResults(frameNumber - (requestCount - i)); + } + } final long sensorTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java index aee20db6783e..e9777515ecdb 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java @@ -46,6 +46,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl { public final static String TAG = "CameraExtensionJpeg"; private final static int JPEG_QUEUE_SIZE = 1; + private final static int JPEG_APP_SEGMENT_SIZE = 64 * 1024; private final Handler mHandler; private final HandlerThread mHandlerThread; @@ -225,9 +226,10 @@ public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl { private void initializePipeline() throws RemoteException { if ((mFormat != -1) && (mOutputSurface != null) && (mResolution != null) && (mYuvReader == null)) { - // Jpeg/blobs are expected to be configured with (w*h)x1 + // Jpeg/blobs are expected to be configured with (w*h)x1.5 + 64k Jpeg APP1 segment mOutputWriter = ImageWriter.newInstance(mOutputSurface, 1 /*maxImages*/, - ImageFormat.JPEG, mResolution.width * mResolution.height, 1); + ImageFormat.JPEG, + (mResolution.width * mResolution.height * 3)/2 + JPEG_APP_SEGMENT_SIZE, 1); mYuvReader = ImageReader.newInstance(mResolution.width, mResolution.height, mFormat, JPEG_QUEUE_SIZE); mYuvReader.setOnImageAvailableListener(new YuvCallback(), mHandler); diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java index bb36536fe2ce..fac747c8f1a3 100644 --- a/core/java/android/net/metrics/WakeupStats.java +++ b/core/java/android/net/metrics/WakeupStats.java @@ -80,18 +80,20 @@ public class WakeupStats { break; } - switch (ev.dstHwAddr.getAddressType()) { - case MacAddress.TYPE_UNICAST: - l2UnicastCount++; - break; - case MacAddress.TYPE_MULTICAST: - l2MulticastCount++; - break; - case MacAddress.TYPE_BROADCAST: - l2BroadcastCount++; - break; - default: - break; + if (ev.dstHwAddr != null) { + switch (ev.dstHwAddr.getAddressType()) { + case MacAddress.TYPE_UNICAST: + l2UnicastCount++; + break; + case MacAddress.TYPE_MULTICAST: + l2MulticastCount++; + break; + case MacAddress.TYPE_BROADCAST: + l2BroadcastCount++; + break; + default: + break; + } } increment(ethertypes, ev.ethertype); diff --git a/core/java/android/nfc/NfcAntennaInfo.java b/core/java/android/nfc/NfcAntennaInfo.java index d54fcd2ed5b3..b002ca21e8e3 100644 --- a/core/java/android/nfc/NfcAntennaInfo.java +++ b/core/java/android/nfc/NfcAntennaInfo.java @@ -85,8 +85,8 @@ public final class NfcAntennaInfo implements Parcelable { this.mDeviceHeight = in.readInt(); this.mDeviceFoldable = in.readByte() != 0; this.mAvailableNfcAntennas = new ArrayList<>(); - in.readParcelableList(this.mAvailableNfcAntennas, - AvailableNfcAntenna.class.getClassLoader()); + in.readTypedList(this.mAvailableNfcAntennas, + AvailableNfcAntenna.CREATOR); } public static final @NonNull Parcelable.Creator<NfcAntennaInfo> CREATOR = diff --git a/core/java/android/nfc/tech/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java index f19d30258393..2240fe7f7d3b 100644 --- a/core/java/android/nfc/tech/NdefFormatable.java +++ b/core/java/android/nfc/tech/NdefFormatable.java @@ -124,6 +124,9 @@ public final class NdefFormatable extends BasicTagTechnology { try { int serviceHandle = mTag.getServiceHandle(); INfcTag tagService = mTag.getTagService(); + if (tagService == null) { + throw new IOException(); + } int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT); switch (errorCode) { case ErrorCodes.SUCCESS: diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 0cb7df73f9b7..5d0a723241b0 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -325,7 +325,24 @@ public class Binder implements IBinder { * @hide */ @CriticalNative - public static final native boolean isDirectlyHandlingTransaction(); + public static final native boolean isDirectlyHandlingTransactionNative(); + + private static boolean sIsHandlingBinderTransaction = false; + + /** + * @hide + */ + public static final boolean isDirectlyHandlingTransaction() { + return sIsHandlingBinderTransaction || isDirectlyHandlingTransactionNative(); + } + + /** + * This is Test API which will be used to override output of isDirectlyHandlingTransactionNative + * @hide + */ + public static void setIsDirectlyHandlingTransactionOverride(boolean isInTransaction) { + sIsHandlingBinderTransaction = isInTransaction; + } /** * Returns {@code true} if the current thread has had its identity diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 244632a87593..2e05b8dc8da3 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1223,6 +1223,11 @@ public class Build { * Upside Down Cake. */ public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT; + + /** + * Vanilla Ice Cream. + */ + public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 0f5fc34bcc21..cdc8268fa7a1 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -63,6 +63,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -363,6 +364,22 @@ public final class Parcel { // see libbinder's binder/Status.h private static final int EX_TRANSACTION_FAILED = -129; + // Allow limit of 1 MB for allocating arrays + private static final int ARRAY_ALLOCATION_LIMIT = 1000000; + + // Following type size are used to determine allocation size while creating arrays + private static final int SIZE_BYTE = 1; + private static final int SIZE_CHAR = 2; + private static final int SIZE_SHORT = 2; + private static final int SIZE_BOOLEAN = 4; + private static final int SIZE_INT = 4; + private static final int SIZE_FLOAT = 4; + private static final int SIZE_DOUBLE = 8; + private static final int SIZE_LONG = 8; + + // Assume the least possible size for complex objects + private static final int SIZE_COMPLEX_TYPE = 1; + @CriticalNative private static native void nativeMarkSensitive(long nativePtr); @FastNative @@ -1503,9 +1520,71 @@ public final class Parcel { } } + private static <T> int getItemTypeSize(@NonNull Class<T> arrayClass) { + final Class<?> componentType = arrayClass.getComponentType(); + // typeSize has been referred from respective create*Array functions + if (componentType == boolean.class) { + return SIZE_BOOLEAN; + } else if (componentType == byte.class) { + return SIZE_BYTE; + } else if (componentType == char.class) { + return SIZE_CHAR; + } else if (componentType == int.class) { + return SIZE_INT; + } else if (componentType == long.class) { + return SIZE_LONG; + } else if (componentType == float.class) { + return SIZE_FLOAT; + } else if (componentType == double.class) { + return SIZE_DOUBLE; + } + + return SIZE_COMPLEX_TYPE; + } + + private void ensureWithinMemoryLimit(int typeSize, @NonNull int... dimensions) { + // For Multidimensional arrays, Calculate total object + // which will be allocated. + int totalObjects = 1; + try { + for (int dimension : dimensions) { + totalObjects = Math.multiplyExact(totalObjects, dimension); + } + } catch (ArithmeticException e) { + Log.e(TAG, "ArithmeticException occurred while multiplying dimensions " + e); + BadParcelableException badParcelableException = new BadParcelableException("Estimated " + + "array length is too large. Array Dimensions:" + Arrays.toString(dimensions)); + SneakyThrow.sneakyThrow(badParcelableException); + } + ensureWithinMemoryLimit(typeSize, totalObjects); + } + + private void ensureWithinMemoryLimit(int typeSize, @NonNull int length) { + int estimatedAllocationSize = 0; + try { + estimatedAllocationSize = Math.multiplyExact(typeSize, length); + } catch (ArithmeticException e) { + Log.e(TAG, "ArithmeticException occurred while multiplying values " + typeSize + + " and " + length + " Exception: " + e); + BadParcelableException badParcelableException = new BadParcelableException("Estimated " + + "allocation size is too large. typeSize: " + typeSize + " length: " + length); + SneakyThrow.sneakyThrow(badParcelableException); + } + + boolean isInBinderTransaction = Binder.isDirectlyHandlingTransaction(); + if (isInBinderTransaction && (estimatedAllocationSize > ARRAY_ALLOCATION_LIMIT)) { + Log.e(TAG, "Trying to Allocate " + estimatedAllocationSize + + " memory, In Binder Transaction : " + isInBinderTransaction); + BadParcelableException e = new BadParcelableException("Allocation of size " + + estimatedAllocationSize + " is above allowed limit of 1MB"); + SneakyThrow.sneakyThrow(e); + } + } + @Nullable public final boolean[] createBooleanArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_BOOLEAN, N); // >>2 as a fast divide-by-4 works in the create*Array() functions // because dataAvail() will never return a negative number. 4 is // the size of a stored boolean in the stream. @@ -1548,6 +1627,7 @@ public final class Parcel { @Nullable public short[] createShortArray() { int n = readInt(); + ensureWithinMemoryLimit(SIZE_SHORT, n); if (n >= 0 && n <= (dataAvail() >> 2)) { short[] val = new short[n]; for (int i = 0; i < n; i++) { @@ -1586,6 +1666,7 @@ public final class Parcel { @Nullable public final char[] createCharArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_CHAR, N); if (N >= 0 && N <= (dataAvail() >> 2)) { char[] val = new char[N]; for (int i=0; i<N; i++) { @@ -1623,6 +1704,7 @@ public final class Parcel { @Nullable public final int[] createIntArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_INT, N); if (N >= 0 && N <= (dataAvail() >> 2)) { int[] val = new int[N]; for (int i=0; i<N; i++) { @@ -1660,6 +1742,7 @@ public final class Parcel { @Nullable public final long[] createLongArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_LONG, N); // >>3 because stored longs are 64 bits if (N >= 0 && N <= (dataAvail() >> 3)) { long[] val = new long[N]; @@ -1698,6 +1781,7 @@ public final class Parcel { @Nullable public final float[] createFloatArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_FLOAT, N); // >>2 because stored floats are 4 bytes if (N >= 0 && N <= (dataAvail() >> 2)) { float[] val = new float[N]; @@ -1736,6 +1820,7 @@ public final class Parcel { @Nullable public final double[] createDoubleArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_DOUBLE, N); // >>3 because stored doubles are 8 bytes if (N >= 0 && N <= (dataAvail() >> 3)) { double[] val = new double[N]; @@ -1789,6 +1874,7 @@ public final class Parcel { @Nullable public final String[] createString8Array() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); if (N >= 0) { String[] val = new String[N]; for (int i=0; i<N; i++) { @@ -1829,6 +1915,7 @@ public final class Parcel { @Nullable public final String[] createString16Array() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); if (N >= 0) { String[] val = new String[N]; for (int i=0; i<N; i++) { @@ -1921,6 +2008,7 @@ public final class Parcel { @Nullable public final IBinder[] createBinderArray() { int N = readInt(); + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); if (N >= 0) { IBinder[] val = new IBinder[N]; for (int i=0; i<N; i++) { @@ -1955,6 +2043,7 @@ public final class Parcel { public final <T extends IInterface> T[] createInterfaceArray( @NonNull IntFunction<T[]> newArray, @NonNull Function<IBinder, T> asInterface) { int N = readInt(); + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); if (N >= 0) { T[] val = newArray.apply(N); for (int i=0; i<N; i++) { @@ -3201,6 +3290,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); FileDescriptor[] f = new FileDescriptor[N]; for (int i = 0; i < N; i++) { f[i] = readRawFileDescriptor(); @@ -3667,6 +3757,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); ArrayList<T> l = new ArrayList<T>(N); while (N > 0) { l.add(readTypedObject(c)); @@ -3721,6 +3812,7 @@ public final class Parcel { if (count < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count); final SparseArray<T> array = new SparseArray<>(count); for (int i = 0; i < count; i++) { final int index = readInt(); @@ -3749,6 +3841,7 @@ public final class Parcel { if (count < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count); final ArrayMap<String, T> map = new ArrayMap<>(count); for (int i = 0; i < count; i++) { final String key = readString(); @@ -3775,6 +3868,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); ArrayList<String> l = new ArrayList<String>(N); while (N > 0) { l.add(readString()); @@ -3800,6 +3894,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); ArrayList<IBinder> l = new ArrayList<IBinder>(N); while (N > 0) { l.add(readStrongBinder()); @@ -3826,6 +3921,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); ArrayList<T> l = new ArrayList<T>(N); while (N > 0) { l.add(asInterface.apply(readStrongBinder())); @@ -3985,6 +4081,7 @@ public final class Parcel { if (N < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N); T[] l = c.newArray(N); for (int i=0; i<N; i++) { l[i] = readTypedObject(c); @@ -4213,6 +4310,10 @@ public final class Parcel { while (innermost.isArray()) { innermost = innermost.getComponentType(); } + + int typeSize = getItemTypeSize(innermost); + ensureWithinMemoryLimit(typeSize, dimensions); + val = (T) Array.newInstance(innermost, dimensions); for (int i = 0; i < length; i++) { readFixedArray(Array.get(val, i)); @@ -4269,6 +4370,10 @@ public final class Parcel { while (innermost.isArray()) { innermost = innermost.getComponentType(); } + + int typeSize = getItemTypeSize(innermost); + ensureWithinMemoryLimit(typeSize, dimensions); + val = (T) Array.newInstance(innermost, dimensions); for (int i = 0; i < length; i++) { readFixedArray(Array.get(val, i), asInterface); @@ -4324,6 +4429,10 @@ public final class Parcel { while (innermost.isArray()) { innermost = innermost.getComponentType(); } + + int typeSize = getItemTypeSize(innermost); + ensureWithinMemoryLimit(typeSize, dimensions); + val = (T) Array.newInstance(innermost, dimensions); for (int i = 0; i < length; i++) { readFixedArray(Array.get(val, i), c); @@ -5069,6 +5178,7 @@ public final class Parcel { if (n < 0) { return null; } + ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, n); T[] p = (T[]) ((clazz == null) ? new Parcelable[n] : Array.newInstance(clazz, n)); for (int i = 0; i < n; i++) { p[i] = readParcelableInternal(loader, clazz); diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index bb74e1983510..89da45b045a3 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -1360,7 +1360,7 @@ public class Process { String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB"); long memSize = FileUtils.parseSize(formatSize); - if (memSize == Long.MIN_VALUE) { + if (memSize <= 0) { return FileUtils.roundStorageSize(getTotalMemory()); } diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index 5aa4e27fc2f3..7cdaecddbd70 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -202,6 +202,13 @@ public class DynamicSystemClient { public static final String ACTION_NOTIFY_IF_IN_USE = "android.os.image.action.NOTIFY_IF_IN_USE"; + /** + * Intent action: hide notifications about the status of {@code DynamicSystem}. + * @hide + */ + public static final String ACTION_HIDE_NOTIFICATION = + "android.os.image.action.HIDE_NOTIFICATION"; + /* * Intent Keys */ @@ -217,6 +224,28 @@ public class DynamicSystemClient { */ public static final String KEY_USERDATA_SIZE = "KEY_USERDATA_SIZE"; + /** + * Intent key: Whether to enable DynamicSystem immediately after installation is done. + * Note this will reboot the device automatically. + * @hide + */ + public static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; + + /** + * Intent key: Whether to leave DynamicSystem on device reboot. + * False indicates a sticky mode where device stays in DynamicSystem across reboots. + * @hide + */ + public static final String KEY_ONE_SHOT = "KEY_ONE_SHOT"; + + /** + * Intent key: Whether to use default strings when showing the dialog that prompts + * user for device credentials. + * False indicates using the custom strings provided by {@code DynamicSystem}. + * @hide + */ + public static final String KEY_KEYGUARD_USE_DEFAULT_STRINGS = + "KEY_KEYGUARD_USE_DEFAULT_STRINGS"; private static class IncomingHandler extends Handler { private final WeakReference<DynamicSystemClient> mWeakClient; diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS index d34b45bf1ff1..4603e43fd164 100644 --- a/core/java/android/permission/OWNERS +++ b/core/java/android/permission/OWNERS @@ -1,18 +1,19 @@ # Bug component: 137825 -evanseverson@google.com -evanxinchen@google.com ashfall@google.com -guojing@google.com +augale@google.com +evanseverson@google.com +fayey@google.com jaysullivan@google.com +joecastro@google.com kvakil@google.com mrulhania@google.com narayan@google.com ntmyren@google.com olekarg@google.com pyuli@google.com -raphk@google.com rmacgregor@google.com sergeynv@google.com theianchen@google.com +yutingfang@google.com zhanghai@google.com diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index 4d6422c670c2..9088a7790db4 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -337,8 +337,22 @@ public final class KeymasterDefs { ErrorCode.ROLLBACK_RESISTANCE_UNAVAILABLE; // -67; public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68; + public static final int KM_ERROR_PROOF_OF_PRESENCE_REQUIRED = + ErrorCode.PROOF_OF_PRESENCE_REQUIRED; // -69; + public static final int KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = + ErrorCode.CONCURRENT_PROOF_OF_PRESENCE_REQUESTED; // -70; + public static final int KM_ERROR_NO_USER_CONFIRMATION = + ErrorCode.NO_USER_CONFIRMATION; // -71; public static final int KM_ERROR_DEVICE_LOCKED = ErrorCode.DEVICE_LOCKED; // -72; + public static final int KM_ERROR_EARLY_BOOT_ENDED = + ErrorCode.EARLY_BOOT_ENDED; // -73; + public static final int KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED = + ErrorCode.ATTESTATION_KEYS_NOT_PROVISIONED; // -74; + public static final int KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED = + ErrorCode.ATTESTATION_IDS_NOT_PROVISIONED; // -75; + public static final int KM_ERROR_INVALID_OPERATION = + ErrorCode.INVALID_OPERATION; // -76; public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED = ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77, public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST = @@ -348,7 +362,13 @@ public final class KeymasterDefs { public static final int KM_ERROR_MISSING_NOT_BEFORE = ErrorCode.MISSING_NOT_BEFORE; // -80; public static final int KM_ERROR_MISSING_NOT_AFTER = - ErrorCode.MISSING_NOT_AFTER; // -80; + ErrorCode.MISSING_NOT_AFTER; // -81; + public static final int KM_ERROR_MISSING_ISSUER_SUBJECT = + ErrorCode.MISSING_ISSUER_SUBJECT; // -82; + public static final int KM_ERROR_INVALID_ISSUER_SUBJECT = + ErrorCode.INVALID_ISSUER_SUBJECT; // -83; + public static final int KM_ERROR_BOOT_LEVEL_EXCEEDED = + ErrorCode.BOOT_LEVEL_EXCEEDED; // -84; public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE = ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85 public static final int KM_ERROR_UNIMPLEMENTED = diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java index b885e726918d..0e20997d307f 100644 --- a/core/java/android/security/net/config/ManifestConfigSource.java +++ b/core/java/android/security/net/config/ManifestConfigSource.java @@ -25,7 +25,7 @@ import java.util.Set; /** @hide */ public class ManifestConfigSource implements ConfigSource { - private static final boolean DBG = true; + private static final boolean DBG = false; private static final String LOG_TAG = "NetworkSecurityConfig"; private final Object mLock = new Object(); diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS index 462d8bed743c..162e02904075 100644 --- a/core/java/android/speech/OWNERS +++ b/core/java/android/speech/OWNERS @@ -2,3 +2,4 @@ volnov@google.com eugeniom@google.com schfan@google.com andreaambu@google.com +hackz@google.com
\ No newline at end of file diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index 3a74b2ed63a7..c7f745664561 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -138,8 +138,12 @@ public abstract class DisplayEventReceiver { mMessageQueue = null; } - static final class VsyncEventData { - + /** + * Class to capture all inputs required for syncing events data. + * + * @hide + */ + public static final class VsyncEventData { static final FrameTimeline[] INVALID_FRAME_TIMELINES = {new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)}; diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS index 1a5cb1e4ca4a..d1eda9648520 100644 --- a/core/java/android/view/contentcapture/OWNERS +++ b/core/java/android/view/contentcapture/OWNERS @@ -5,3 +5,5 @@ joannechung@google.com markpun@google.com lpeter@google.com tymtsai@google.com +hackz@google.com +volnov@google.com
\ No newline at end of file diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index fadad99f0885..14aac89dcb10 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -709,7 +709,10 @@ public class Editor { } getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true); - makeBlink(); + // Call resumeBlink here instead of makeBlink to ensure that if mBlink is not null the + // Blink object is uncancelled. This ensures when a view is removed and added back the + // cursor will resume blinking. + resumeBlink(); } void onDetachedFromWindow() { @@ -1081,8 +1084,10 @@ public class Editor { private void resumeBlink() { if (mBlink != null) { mBlink.uncancel(); - makeBlink(); } + // Moving makeBlink outside of the null check block ensures that mBlink object gets + // instantiated when the view is added to the window if mBlink is still null. + makeBlink(); } void adjustInputType(boolean password, boolean passwordInputType, @@ -2862,6 +2867,9 @@ public class Editor { if (shouldBlink()) { mShowCursor = SystemClock.uptimeMillis(); if (mBlink == null) mBlink = new Blink(); + // Call uncancel as mBlink could have previously been cancelled and cursor will not + // resume blinking unless uncancelled. + mBlink.uncancel(); mTextView.removeCallbacks(mBlink); mTextView.postDelayed(mBlink, BLINK); } else { diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java index 2a80d021abd6..740fbacbbfcc 100644 --- a/core/java/android/window/WindowOrganizer.java +++ b/core/java/android/window/WindowOrganizer.java @@ -61,9 +61,7 @@ public class WindowOrganizer { * Apply multiple WindowContainer operations at once. * * Note that using this API requires the caller to hold - * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using - * {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is - * created by itself. + * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}. * * @param t The transaction to apply. * @param callback This transaction will use the synchronization scheme described in @@ -72,8 +70,7 @@ public class WindowOrganizer { * @return An ID for the sync operation which will later be passed to transactionReady callback. * This lets the caller differentiate overlapping sync operations. */ - @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS, - conditional = true) + @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull WindowContainerTransaction t, @NonNull WindowContainerTransactionCallback callback) { try { diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS index a1d571fc4350..52f18fb80c27 100644 --- a/core/java/com/android/internal/app/OWNERS +++ b/core/java/com/android/internal/app/OWNERS @@ -1,15 +1,16 @@ per-file *AppOp* = file:/core/java/android/permission/OWNERS per-file UnlaunchableAppActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS per-file IntentForwarderActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS -per-file *Resolver* = file:/packages/SystemUI/OWNERS -per-file *Chooser* = file:/packages/SystemUI/OWNERS -per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS -per-file AbstractMultiProfilePagerAdapter.java = file:/packages/SystemUI/OWNERS -per-file *EmptyStateProvider.java = file:/packages/SystemUI/OWNERS per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS +# Chooser and Resolver. +per-file *Chooser* = file:chooser/OWNERS +per-file *Resolver* = file:chooser/OWNERS +per-file SimpleIconFactory.java = file:chooser/OWNERS +per-file AbstractMultiProfilePagerAdapter.java = file:chooser/OWNERS +per-file *EmptyStateProvider.java = file:chooser/OWNERS # Voice Interaction per-file *Assist* = file:/core/java/android/service/voice/OWNERS diff --git a/core/java/com/android/internal/app/chooser/OWNERS b/core/java/com/android/internal/app/chooser/OWNERS index a6f1632e7b8c..0844cfa6d053 100644 --- a/core/java/com/android/internal/app/chooser/OWNERS +++ b/core/java/com/android/internal/app/chooser/OWNERS @@ -1 +1,3 @@ -file:/packages/SystemUI/OWNERS
\ No newline at end of file +# Bug component: 324112 + +include platform/packages/modules/IntentResolver:/OWNERS diff --git a/core/java/com/android/internal/expresslog/Counter.java b/core/java/com/android/internal/expresslog/Counter.java deleted file mode 100644 index 4a46d91efbf0..000000000000 --- a/core/java/com/android/internal/expresslog/Counter.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.expresslog; - -import android.annotation.NonNull; - -import com.android.internal.util.FrameworkStatsLog; - -/** Counter encapsulates StatsD write API calls */ -public final class Counter { - - // Not instantiable. - private Counter() {} - - /** - * Increments Telemetry Express Counter metric by 1 - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @hide - */ - public static void logIncrement(@NonNull String metricId) { - logIncrement(metricId, 1); - } - - /** - * Increments Telemetry Express Counter metric by 1 - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param uid used as a dimension for the count metric - * @hide - */ - public static void logIncrementWithUid(@NonNull String metricId, int uid) { - logIncrementWithUid(metricId, uid, 1); - } - - /** - * Increments Telemetry Express Counter metric by arbitrary value - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param amount to increment counter - * @hide - */ - public static void logIncrement(@NonNull String metricId, long amount) { - final long metricIdHash = Utils.hashString(metricId); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_EVENT_REPORTED, metricIdHash, amount); - } - - /** - * Increments Telemetry Express Counter metric by arbitrary value - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param uid used as a dimension for the count metric - * @param amount to increment counter - * @hide - */ - public static void logIncrementWithUid(@NonNull String metricId, int uid, long amount) { - final long metricIdHash = Utils.hashString(metricId); - FrameworkStatsLog.write( - FrameworkStatsLog.EXPRESS_UID_EVENT_REPORTED, metricIdHash, amount, uid); - } -} diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java deleted file mode 100644 index 2fe784a5a855..000000000000 --- a/core/java/com/android/internal/expresslog/Histogram.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.expresslog; - -import android.annotation.FloatRange; -import android.annotation.IntRange; -import android.annotation.NonNull; - -import com.android.internal.util.FrameworkStatsLog; - -import java.util.Arrays; - -/** Histogram encapsulates StatsD write API calls */ -public final class Histogram { - - private final long mMetricIdHash; - private final BinOptions mBinOptions; - - /** - * Creates Histogram metric logging wrapper - * - * @param metricId to log, logging will be no-op if metricId is not defined in the TeX catalog - * @param binOptions to calculate bin index for samples - * @hide - */ - public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) { - mMetricIdHash = Utils.hashString(metricId); - mBinOptions = binOptions; - } - - /** - * Logs increment sample count for automatically calculated bin - * - * @param sample value - * @hide - */ - public void logSample(float sample) { - final int binIndex = mBinOptions.getBinForSample(sample); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, - /*count*/ 1, binIndex); - } - - /** - * Logs increment sample count for automatically calculated bin - * - * @param uid used as a dimension for the count metric - * @param sample value - * @hide - */ - public void logSampleWithUid(int uid, float sample) { - final int binIndex = mBinOptions.getBinForSample(sample); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED, - mMetricIdHash, /*count*/ 1, binIndex, uid); - } - - /** Used by Histogram to map data sample to corresponding bin */ - public interface BinOptions { - /** - * Returns bins count to be used by a histogram - * - * @return bins count used to initialize Options, including overflow & underflow bins - * @hide - */ - int getBinsCount(); - - /** - * Returns bin index for the input sample value - * index == 0 stands for underflow - * index == getBinsCount() - 1 stands for overflow - * - * @return zero based index - * @hide - */ - int getBinForSample(float sample); - } - - /** Used by Histogram to map data sample to corresponding bin for uniform bins */ - public static final class UniformOptions implements BinOptions { - - private final int mBinCount; - private final float mMinValue; - private final float mExclusiveMaxValue; - private final float mBinSize; - - /** - * Creates options for uniform (linear) sized bins - * - * @param binCount amount of histogram bins. 2 bin indexes will be calculated - * automatically to represent underflow & overflow bins - * @param minValue is included in the first bin, values less than minValue - * go to underflow bin - * @param exclusiveMaxValue is included in the overflow bucket. For accurate - * measure up to kMax, then exclusiveMaxValue - * should be set to kMax + 1 - * @hide - */ - public UniformOptions(@IntRange(from = 1) int binCount, float minValue, - float exclusiveMaxValue) { - if (binCount < 1) { - throw new IllegalArgumentException("Bin count should be positive number"); - } - - if (exclusiveMaxValue <= minValue) { - throw new IllegalArgumentException("Bins range invalid (maxValue < minValue)"); - } - - mMinValue = minValue; - mExclusiveMaxValue = exclusiveMaxValue; - mBinSize = (mExclusiveMaxValue - minValue) / binCount; - - // Implicitly add 2 for the extra underflow & overflow bins - mBinCount = binCount + 2; - } - - @Override - public int getBinsCount() { - return mBinCount; - } - - @Override - public int getBinForSample(float sample) { - if (sample < mMinValue) { - // goes to underflow - return 0; - } else if (sample >= mExclusiveMaxValue) { - // goes to overflow - return mBinCount - 1; - } - return (int) ((sample - mMinValue) / mBinSize + 1); - } - } - - /** Used by Histogram to map data sample to corresponding bin for scaled bins */ - public static final class ScaledRangeOptions implements BinOptions { - // store minimum value per bin - final long[] mBins; - - /** - * Creates options for scaled range bins - * - * @param binCount amount of histogram bins. 2 bin indexes will be calculated - * automatically to represent underflow & overflow bins - * @param minValue is included in the first bin, values less than minValue - * go to underflow bin - * @param firstBinWidth used to represent first bin width and as a reference to calculate - * width for consecutive bins - * @param scaleFactor used to calculate width for consecutive bins - * @hide - */ - public ScaledRangeOptions(@IntRange(from = 1) int binCount, int minValue, - @FloatRange(from = 1.f) float firstBinWidth, - @FloatRange(from = 1.f) float scaleFactor) { - if (binCount < 1) { - throw new IllegalArgumentException("Bin count should be positive number"); - } - - if (firstBinWidth < 1.f) { - throw new IllegalArgumentException( - "First bin width invalid (should be 1.f at minimum)"); - } - - if (scaleFactor < 1.f) { - throw new IllegalArgumentException( - "Scaled factor invalid (should be 1.f at minimum)"); - } - - // precalculating bins ranges (no need to create a bin for underflow reference value) - mBins = initBins(binCount + 1, minValue, firstBinWidth, scaleFactor); - } - - @Override - public int getBinsCount() { - return mBins.length + 1; - } - - @Override - public int getBinForSample(float sample) { - if (sample < mBins[0]) { - // goes to underflow - return 0; - } else if (sample >= mBins[mBins.length - 1]) { - // goes to overflow - return mBins.length; - } - - return lower_bound(mBins, (long) sample) + 1; - } - - // To find lower bound using binary search implementation of Arrays utility class - private static int lower_bound(long[] array, long sample) { - int index = Arrays.binarySearch(array, sample); - // If key is not present in the array - if (index < 0) { - // Index specify the position of the key when inserted in the sorted array - // so the element currently present at this position will be the lower bound - return Math.abs(index) - 2; - } - return index; - } - - private static long[] initBins(int count, int minValue, float firstBinWidth, - float scaleFactor) { - long[] bins = new long[count]; - bins[0] = minValue; - double lastWidth = firstBinWidth; - for (int i = 1; i < count; i++) { - // current bin minValue = previous bin width * scaleFactor - double currentBinMinValue = bins[i - 1] + lastWidth; - if (currentBinMinValue > Integer.MAX_VALUE) { - throw new IllegalArgumentException( - "Attempted to create a bucket larger than maxint"); - } - - bins[i] = (long) currentBinMinValue; - lastWidth *= scaleFactor; - } - return bins; - } - } -} diff --git a/core/java/com/android/internal/expresslog/OWNERS b/core/java/com/android/internal/expresslog/OWNERS deleted file mode 100644 index ee865b1e4ec8..000000000000 --- a/core/java/com/android/internal/expresslog/OWNERS +++ /dev/null @@ -1 +0,0 @@ -include /services/core/java/com/android/server/stats/OWNERS diff --git a/core/java/com/android/internal/expresslog/TEST_MAPPING b/core/java/com/android/internal/expresslog/TEST_MAPPING deleted file mode 100644 index c9b0cf80a1e6..000000000000 --- a/core/java/com/android/internal/expresslog/TEST_MAPPING +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presubmit": [ - { - "name": "ExpressLogTests", - "options": [ - { - "exclude-annotation": "org.junit.Ignore" - } - ] - } - ] -}
\ No newline at end of file diff --git a/core/java/com/android/internal/expresslog/Utils.java b/core/java/com/android/internal/expresslog/Utils.java deleted file mode 100644 index d82192f51662..000000000000 --- a/core/java/com/android/internal/expresslog/Utils.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.expresslog; - -final class Utils { - static native long hashString(String stringToHash); -} diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 05cad77ca9ab..d8aeb51c2e4d 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -1018,7 +1018,7 @@ public final class Zygote { * Applies debugger system properties to the zygote arguments. * * For eng builds all apps are debuggable. On userdebug and user builds - * if persist.debuggable.dalvik.vm.jdwp.enabled is 1 all apps are + * if persist.debug.dalvik.vm.jdwp.enabled is 1 all apps are * debuggable. Otherwise, the debugger state is specified via the * "--enable-jdwp" flag in the spawn request. * diff --git a/core/jni/Android.bp b/core/jni/Android.bp index b5b7c0f38bb9..73c93ac9d06b 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -221,7 +221,6 @@ cc_library_shared { "android_content_res_Configuration.cpp", "android_security_Scrypt.cpp", "com_android_internal_content_om_OverlayConfig.cpp", - "com_android_internal_expresslog_Utils.cpp", "com_android_internal_net_NetworkUtilsInternal.cpp", "com_android_internal_os_ClassLoaderFactory.cpp", "com_android_internal_os_FuseAppLoop.cpp", @@ -256,6 +255,7 @@ cc_library_shared { "libstatssocket_lazy", "libskia", "libtextclassifier_hash_static", + "libexpresslog_jni", ], shared_libs: [ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9c7f0a8b613d..7c8ea93894a5 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -195,8 +195,7 @@ extern int register_android_animation_PropertyValuesHolder(JNIEnv *env); extern int register_android_security_Scrypt(JNIEnv *env); extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env); extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env); -extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env); -extern int register_com_android_internal_expresslog_Utils(JNIEnv* env); +extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv* env); extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env); extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env); extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); @@ -213,6 +212,7 @@ extern int register_com_android_internal_os_ZygoteCommandBuffer(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_security_VerityUtils(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); +extern int register_com_android_modules_expresslog_Utils(JNIEnv* env); extern int register_android_window_WindowInfosListener(JNIEnv* env); // Namespace for Android Runtime flags applied during boot time. @@ -646,9 +646,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char saveResolvedClassesDelayMsOptsBuf[ sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX]; char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX]; - char profileMinFirstSaveOptsBuf[ - sizeof("-Xps-min-first-save-ms:")-1 + PROPERTY_VALUE_MAX]; - char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX]; + char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX]; char madviseWillNeedFileSizeVdex[ sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX]; char madviseWillNeedFileSizeOdex[ @@ -861,13 +859,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p jitprithreadweightOptBuf, "-Xjitprithreadweight:"); - parseRuntimeOption("dalvik.vm.jittransitionweight", - jittransitionweightOptBuf, + parseRuntimeOption("dalvik.vm.jittransitionweight", jittransitionweightOptBuf, "-Xjittransitionweight:"); - /* - * Madvise related options. - */ - parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:"); /* * Use default platform configuration as limits for madvising, @@ -1591,7 +1584,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_SharedMemory), REG_JNI(register_android_os_incremental_IncrementalManager), REG_JNI(register_com_android_internal_content_om_OverlayConfig), - REG_JNI(register_com_android_internal_expresslog_Utils), REG_JNI(register_com_android_internal_net_NetworkUtilsInternal), REG_JNI(register_com_android_internal_os_ClassLoaderFactory), REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter), @@ -1601,6 +1593,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_ZygoteInit), REG_JNI(register_com_android_internal_security_VerityUtils), REG_JNI(register_com_android_internal_util_VirtualRefBasePtr), + REG_JNI(register_com_android_modules_expresslog_Utils), REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_camera2_CameraMetadata), REG_JNI(register_android_hardware_camera2_DngCreator), diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 1e7a93c8e812..84b050cdfbdb 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -102,6 +102,3 @@ per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNER # PM per-file com_android_internal_content_* = file:/PACKAGE_MANAGER_OWNERS - -# Stats/expresslog -per-file *expresslog* = file:/services/core/java/com/android/server/stats/OWNERS diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index cdb058028fdd..56c2a8647168 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2382,36 +2382,31 @@ static jint android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject th if (jSurroundFormats == nullptr) { ALOGE("jSurroundFormats is NULL"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) { ALOGE("getSurroundFormats not a map"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } jint jStatus; unsigned int numSurroundFormats = 0; - audio_format_t *surroundFormats = nullptr; - bool *surroundFormatsEnabled = nullptr; - status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats, - surroundFormatsEnabled); + status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, nullptr, nullptr); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status); - jStatus = nativeToJavaStatus(status); - goto exit; + return nativeToJavaStatus(status); } if (numSurroundFormats == 0) { - jStatus = (jint)AUDIO_JAVA_SUCCESS; - goto exit; + return static_cast<jint>(AUDIO_JAVA_SUCCESS); } - surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t)); - surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool)); - status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats, - surroundFormatsEnabled); + auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats); + auto surroundFormatsEnabled = std::make_unique<bool[]>(numSurroundFormats); + status = AudioSystem::getSurroundFormats(&numSurroundFormats, &surroundFormats[0], + &surroundFormatsEnabled[0]); jStatus = nativeToJavaStatus(status); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status); - goto exit; + return jStatus; } for (size_t i = 0; i < numSurroundFormats; i++) { int audioFormat = audioFormatFromNative(surroundFormats[i]); @@ -2427,9 +2422,6 @@ static jint android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject th env->DeleteLocalRef(enabled); } -exit: - free(surroundFormats); - free(surroundFormatsEnabled); return jStatus; } @@ -2439,31 +2431,28 @@ static jint android_media_AudioSystem_getReportedSurroundFormats(JNIEnv *env, jo if (jSurroundFormats == nullptr) { ALOGE("jSurroundFormats is NULL"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } if (!env->IsInstanceOf(jSurroundFormats, gArrayListClass)) { ALOGE("jSurroundFormats not an arraylist"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } jint jStatus; unsigned int numSurroundFormats = 0; - audio_format_t *surroundFormats = nullptr; - status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats); + status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, nullptr); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status); - jStatus = nativeToJavaStatus(status); - goto exit; + return nativeToJavaStatus(status); } if (numSurroundFormats == 0) { - jStatus = (jint)AUDIO_JAVA_SUCCESS; - goto exit; + return static_cast<jint>(AUDIO_JAVA_SUCCESS); } - surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t)); - status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats); + auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats); + status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, &surroundFormats[0]); jStatus = nativeToJavaStatus(status); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status); - goto exit; + return jStatus; } for (size_t i = 0; i < numSurroundFormats; i++) { int audioFormat = audioFormatFromNative(surroundFormats[i]); @@ -2477,8 +2466,6 @@ static jint android_media_AudioSystem_getReportedSurroundFormats(JNIEnv *env, jo env->DeleteLocalRef(surroundFormat); } -exit: - free(surroundFormats); return jStatus; } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index b24dc8a9e63b..8bc52b874ae0 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -974,7 +974,7 @@ static jint android_os_Binder_getCallingUid() return IPCThreadState::self()->getCallingUid(); } -static jboolean android_os_Binder_isDirectlyHandlingTransaction() { +static jboolean android_os_Binder_isDirectlyHandlingTransactionNative() { return getCurrentServingCall() == BinderCallType::BINDER; } @@ -1082,7 +1082,8 @@ static const JNINativeMethod gBinderMethods[] = { // @CriticalNative { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, // @CriticalNative - { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction }, + { "isDirectlyHandlingTransactionNative", "()Z", + (void*)android_os_Binder_isDirectlyHandlingTransactionNative }, // @CriticalNative { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, // @CriticalNative diff --git a/core/jni/com_android_internal_expresslog_Utils.cpp b/core/jni/com_android_internal_expresslog_Utils.cpp deleted file mode 100644 index d33a7bda27f7..000000000000 --- a/core/jni/com_android_internal_expresslog_Utils.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <nativehelper/JNIHelp.h> -#include <utils/hash/farmhash.h> - -#include "core_jni_helpers.h" - -// ---------------------------------------------------------------------------- -// JNI Glue -// ---------------------------------------------------------------------------- - -static jclass g_stringClass = nullptr; - -/** - * Class: com_android_internal_expresslog_Utils - * Method: hashString - * Signature: (Ljava/lang/String;)J - */ -static jlong hashString(JNIEnv* env, jclass /*class*/, jstring metricNameObj) { - ScopedUtfChars name(env, metricNameObj); - if (name.c_str() == nullptr) { - return 0; - } - - return static_cast<jlong>(farmhash::Fingerprint64(name.c_str(), name.size())); -} - -static const JNINativeMethod g_methods[] = { - {"hashString", "(Ljava/lang/String;)J", (void*)hashString}, -}; - -static const char* const kUtilsPathName = "com/android/internal/expresslog/Utils"; - -namespace android { - -int register_com_android_internal_expresslog_Utils(JNIEnv* env) { - jclass stringClass = FindClassOrDie(env, "java/lang/String"); - g_stringClass = MakeGlobalRefOrDie(env, stringClass); - - return RegisterMethodsOrDie(env, kUtilsPathName, g_methods, NELEM(g_methods)); -} - -} // namespace android diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp index a5152b6e689c..56c01ba2c3a3 100644 --- a/core/jni/com_android_internal_os_ZygoteInit.cpp +++ b/core/jni/com_android_internal_os_ZygoteInit.cpp @@ -23,43 +23,13 @@ namespace { -// Shadow call stack (SCS) is a security mitigation that uses a separate stack -// (the SCS) for return addresses. In versions of Android newer than P, the -// compiler cooperates with the system to ensure that the SCS address is always -// stored in register x18, as long as the app was compiled with a new enough -// compiler and does not use features that rely on SP-HALs (this restriction is -// because the SP-HALs might not preserve x18 due to potentially having been -// compiled with an old compiler as a consequence of Treble; it generally means -// that the app must be a system app without a UI). This struct is used to -// temporarily store the address on the stack while preloading the SP-HALs, so -// that such apps can use the same zygote as everything else. -struct ScopedSCSExit { -#ifdef __aarch64__ - void* scs; - - ScopedSCSExit() { - __asm__ __volatile__("str x18, [%0]" ::"r"(&scs)); - } - - ~ScopedSCSExit() { - __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs)); - } -#else - // Silence unused variable warnings in non-SCS builds. - ScopedSCSExit() {} - ~ScopedSCSExit() {} -#endif -}; - void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) { - ScopedSCSExit x; android::GraphicBufferMapper::preloadHal(); // Add preloading here for other HALs that are (a) always passthrough, and // (b) loaded by most app processes. } void android_internal_os_ZygoteInit_nativePreloadGraphicsDriver(JNIEnv* env, jclass) { - ScopedSCSExit x; zygote_preload_graphics(); } diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 7205dd817eb5..c596c54d2780 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -1008,6 +1008,7 @@ message AppsExitInfoProto { optional int32 uid = 1; repeated .android.app.ApplicationExitInfoProto app_exit_info = 2; + repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3; } repeated User users = 2; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 277bdf388188..35dc8e37aaab 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2328,6 +2328,8 @@ <p>Protection level: normal --> <permission android:name="android.permission.NFC_TRANSACTION_EVENT" + android:description="@string/permdesc_nfcTransactionEvent" + android:label="@string/permlab_nfcTransactionEvent" android:protectionLevel="normal" /> <!-- Allows applications to receive NFC preferred payment service information. @@ -4237,11 +4239,11 @@ android:protectionLevel="internal|preinstalled" /> <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state. - <p>Protection level: internal|role - <p>Intended for use by ROLE_ASSISTANT only. + <p>Protection level: signature|role + <p>Intended for use by ROLE_ASSISTANT and signature apps only. --> <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" - android:protectionLevel="internal|role"/> + android:protectionLevel="signature|role"/> <!-- Must be required by a {@link android.service.autofill.AutofillService}, to ensure that only the system can bind to it. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4b05f99f8242..031a6669a3c6 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4475,6 +4475,9 @@ <!-- Whether or not we should show the option to show battery percentage --> <bool name="config_battery_percentage_setting_available">true</bool> + <!-- Default value set for battery percentage in status bar false = disabled, true = enabled --> + <bool name="config_defaultBatteryPercentageSetting">false</bool> + <!-- Whether or not battery saver should be "sticky" when manually enabled. --> <bool name="config_batterySaverStickyBehaviourDisabled">false</bool> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8a1b74d33065..5a1e0e8d6d47 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1604,6 +1604,12 @@ with Near Field Communication (NFC) tags, cards, and readers.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcTransactionEvent">Secure Element transaction event</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcTransactionEvent">Allows the app to receive information about + transactions happening on a Secure Element.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_disableKeyguard">disable your screen lock</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_disableKeyguard">Allows the app to disable the diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index ba1030b7a99c..716d1bd89182 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2359,6 +2359,7 @@ <java-symbol type="style" name="Animation.RecentApplications" /> <java-symbol type="integer" name="dock_enter_exit_duration" /> <java-symbol type="bool" name="config_battery_percentage_setting_available" /> + <java-symbol type="bool" name="config_defaultBatteryPercentageSetting" /> <java-symbol type="string" name="nas_upgrade_notification_title" /> <java-symbol type="string" name="nas_upgrade_notification_content" /> <java-symbol type="string" name="nas_upgrade_notification_enable_action" /> diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 48c9df04a662..035eaeedc653 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -84,8 +84,8 @@ android_test { ":BstatsTestApp", ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp2", + ":com.android.cts.helpers.aosp", ], - required: ["com.android.cts.helpers.aosp"], } // Rules to copy all the test apks to the intermediate raw resource directory diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS index b3f399363aef..8d9461d8035d 100644 --- a/core/tests/coretests/src/android/app/OWNERS +++ b/core/tests/coretests/src/android/app/OWNERS @@ -4,3 +4,6 @@ per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS per-file *Notification* = file:/packages/SystemUI/OWNERS per-file *Zen* = file:/packages/SystemUI/OWNERS per-file *StatusBar* = file:/packages/SystemUI/OWNERS + +# A11Y and related +per-file *UiAutomation* = file:/services/accessibility/OWNERS diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java index e2fe87b4cfe3..4b993fadc1e0 100644 --- a/core/tests/coretests/src/android/os/ParcelTest.java +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -246,4 +246,93 @@ public class ParcelTest { assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0)); assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0)); } + + /*** + * Tests for b/205282403 + * This test checks if allocations made over limit of 1MB for primitive types + * and 1M length for complex objects are not allowed. + */ + @Test + public void testAllocationsOverLimit_whenOverLimit_throws() { + Binder.setIsDirectlyHandlingTransactionOverride(true); + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.writeInt(Integer.MAX_VALUE); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createBooleanArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createCharArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createIntArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createLongArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createBinderArray()); + + int[] dimensions = new int[]{Integer.MAX_VALUE, 100, 100}; + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(int[][][].class, dimensions)); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(String[][][].class, dimensions)); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(IBinder[][][].class, dimensions)); + + p.recycle(); + Binder.setIsDirectlyHandlingTransactionOverride(false); + } + + /*** + * Tests for b/205282403 + * This test checks if allocations made under limit of 1MB for primitive types + * and 1M length for complex objects are allowed. + */ + @Test + public void testAllocations_whenWithinLimit() { + Binder.setIsDirectlyHandlingTransactionOverride(true); + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.writeInt(100000); + + p.setDataPosition(0); + p.createByteArray(); + + p.setDataPosition(0); + p.createCharArray(); + + p.setDataPosition(0); + p.createIntArray(); + + p.setDataPosition(0); + p.createLongArray(); + + p.setDataPosition(0); + p.createBinderArray(); + + int[] dimensions = new int[]{ 100, 100, 100 }; + + p.setDataPosition(0); + int[][][] data = new int[100][100][100]; + p.writeFixedArray(data, 0, dimensions); + p.setDataPosition(0); + p.createFixedArray(int[][][].class, dimensions); + + p.setDataPosition(0); + IBinder[][][] parcelables = new IBinder[100][100][100]; + p.writeFixedArray(parcelables, 0, dimensions); + p.setDataPosition(0); + p.createFixedArray(IBinder[][][].class, dimensions); + + p.recycle(); + Binder.setIsDirectlyHandlingTransactionOverride(false); + } } diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java index 52846dfbb14b..b2ffdc035e8b 100644 --- a/core/tests/coretests/src/android/os/ProcessTest.java +++ b/core/tests/coretests/src/android/os/ProcessTest.java @@ -73,6 +73,7 @@ public class ProcessTest extends TestCase { } public void testGetAdvertisedMem() { + assertTrue(Process.getAdvertisedMem() > 0); assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem()); } } diff --git a/core/tests/expresslog/Android.bp b/core/tests/expresslog/Android.bp deleted file mode 100644 index cab49a76a734..000000000000 --- a/core/tests/expresslog/Android.bp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2023 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_test { - name: "ExpressLogTests", - - srcs: [ - "src/**/*.java", - ], - - static_libs: [ - "androidx.test.rules", - "modules-utils-build", - ], - - libs: [ - "android.test.base", - "android.test.runner", - ], - - platform_apis: true, - test_suites: [ - "general-tests", - ], - - certificate: "platform", -} diff --git a/core/tests/expresslog/AndroidManifest.xml b/core/tests/expresslog/AndroidManifest.xml deleted file mode 100644 index 94a39e06c974..000000000000 --- a/core/tests/expresslog/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2023 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - android:installLocation="internalOnly" - package="com.android.internal.expresslog" > - - <application > - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.internal.expresslog" - android:label="Telemetry Express Logging Helper Tests" /> - -</manifest> diff --git a/core/tests/expresslog/OWNERS b/core/tests/expresslog/OWNERS deleted file mode 100644 index 3dc958b07f9c..000000000000 --- a/core/tests/expresslog/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Bug component: 719316 -# Stats/expresslog -file:/services/core/java/com/android/server/stats/OWNERS diff --git a/core/tests/expresslog/TEST_MAPPING b/core/tests/expresslog/TEST_MAPPING deleted file mode 100644 index c9b0cf80a1e6..000000000000 --- a/core/tests/expresslog/TEST_MAPPING +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presubmit": [ - { - "name": "ExpressLogTests", - "options": [ - { - "exclude-annotation": "org.junit.Ignore" - } - ] - } - ] -}
\ No newline at end of file diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java deleted file mode 100644 index ee62d7528818..000000000000 --- a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.expresslog; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -@SmallTest -public class ScaledRangeOptionsTest { - private static final String TAG = ScaledRangeOptionsTest.class.getSimpleName(); - - @Test - public void testGetBinsCount() { - Histogram.ScaledRangeOptions options1 = new Histogram.ScaledRangeOptions(1, 100, 100, 2); - assertEquals(3, options1.getBinsCount()); - - Histogram.ScaledRangeOptions options10 = new Histogram.ScaledRangeOptions(10, 100, 100, 2); - assertEquals(12, options10.getBinsCount()); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructZeroBinsCount() { - new Histogram.ScaledRangeOptions(0, 100, 100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeBinsCount() { - new Histogram.ScaledRangeOptions(-1, 100, 100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeFirstBinWidth() { - new Histogram.ScaledRangeOptions(10, 100, -100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooSmallFirstBinWidth() { - new Histogram.ScaledRangeOptions(10, 100, 0.5f, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, -2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooSmallScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, 0.5f); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooBigScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, 500.f); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooBigBinRange() { - new Histogram.ScaledRangeOptions(100, 100, 100, 10.f); - } - - @Test - public void testBinIndexForRangeEqual1() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 1, 1); - assertEquals(12, options.getBinsCount()); - - assertEquals(11, options.getBinForSample(11)); - - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i)); - } - } - - @Test - public void testBinIndexForRangeEqual2() { - // this should produce bin otpions similar to linear histogram with bin width 2 - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 2, 1); - assertEquals(12, options.getBinsCount()); - - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i * 2)); - assertEquals(i, options.getBinForSample(i * 2 - 1)); - } - } - - @Test - public void testBinIndexForRangeEqual5() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(2, 0, 5, 1); - assertEquals(4, options.getBinsCount()); - for (int i = 0; i < 2; i++) { - for (int sample = 0; sample < 5; sample++) { - assertEquals(i + 1, options.getBinForSample(i * 5 + sample)); - } - } - } - - @Test - public void testBinIndexForRangeEqual10() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 10, 1); - assertEquals(0, options.getBinForSample(0)); - assertEquals(options.getBinsCount() - 2, options.getBinForSample(100)); - assertEquals(options.getBinsCount() - 1, options.getBinForSample(101)); - - final float binSize = (101 - 1) / 10f; - for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) { - assertEquals(i, options.getBinForSample(i * binSize)); - } - } - - @Test - public void testBinIndexForScaleFactor2() { - final int binsCount = 10; - final int minValue = 10; - final int firstBinWidth = 5; - final int scaledFactor = 2; - - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions( - binsCount, minValue, firstBinWidth, scaledFactor); - assertEquals(binsCount + 2, options.getBinsCount()); - long[] binCounts = new long[10]; - - // precalculate max valid value - start value for the overflow bin - int lastBinStartValue = minValue; //firstBinMin value - int lastBinWidth = firstBinWidth; - for (int binIdx = 2; binIdx <= binsCount + 1; binIdx++) { - lastBinStartValue = lastBinStartValue + lastBinWidth; - lastBinWidth *= scaledFactor; - } - - // underflow bin - for (int i = 1; i < minValue; i++) { - assertEquals(0, options.getBinForSample(i)); - } - - for (int i = 10; i < lastBinStartValue; i++) { - assertTrue(options.getBinForSample(i) > 0); - assertTrue(options.getBinForSample(i) <= binsCount); - binCounts[options.getBinForSample(i) - 1]++; - } - - // overflow bin - assertEquals(binsCount + 1, options.getBinForSample(lastBinStartValue)); - - for (int i = 1; i < binsCount; i++) { - assertEquals(binCounts[i], binCounts[i - 1] * 2L); - } - } -} diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java deleted file mode 100644 index 037dbb32c2f8..000000000000 --- a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.expresslog; - -import androidx.test.filters.SmallTest; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -@SmallTest -public class UniformOptionsTest { - private static final String TAG = UniformOptionsTest.class.getSimpleName(); - - @Test - public void testGetBinsCount() { - Histogram.UniformOptions options1 = new Histogram.UniformOptions(1, 100, 1000); - assertEquals(3, options1.getBinsCount()); - - Histogram.UniformOptions options10 = new Histogram.UniformOptions(10, 100, 1000); - assertEquals(12, options10.getBinsCount()); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructZeroBinsCount() { - new Histogram.UniformOptions(0, 100, 1000); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeBinsCount() { - new Histogram.UniformOptions(-1, 100, 1000); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructMaxValueLessThanMinValue() { - new Histogram.UniformOptions(10, 1000, 100); - } - - @Test - public void testBinIndexForRangeEqual1() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 11); - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i)); - } - } - - @Test - public void testBinIndexForRangeEqual2() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 21); - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i * 2)); - assertEquals(i, options.getBinForSample(i * 2 - 1)); - } - } - - @Test - public void testBinIndexForRangeEqual5() { - Histogram.UniformOptions options = new Histogram.UniformOptions(2, 0, 10); - assertEquals(4, options.getBinsCount()); - for (int i = 0; i < 2; i++) { - for (int sample = 0; sample < 5; sample++) { - assertEquals(i + 1, options.getBinForSample(i * 5 + sample)); - } - } - } - - @Test - public void testBinIndexForRangeEqual10() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 101); - assertEquals(0, options.getBinForSample(0)); - assertEquals(options.getBinsCount() - 2, options.getBinForSample(100)); - assertEquals(options.getBinsCount() - 1, options.getBinForSample(101)); - - final float binSize = (101 - 1) / 10f; - for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) { - assertEquals(i, options.getBinForSample(i * binSize)); - } - } - - @Test - public void testBinIndexForRangeEqual90() { - final int binCount = 10; - final int minValue = 100; - final int maxValue = 100000; - - Histogram.UniformOptions options = new Histogram.UniformOptions(binCount, minValue, - maxValue); - - // logging underflow sample - assertEquals(0, options.getBinForSample(minValue - 1)); - - // logging overflow sample - assertEquals(binCount + 1, options.getBinForSample(maxValue)); - assertEquals(binCount + 1, options.getBinForSample(maxValue + 1)); - - // logging min edge sample - assertEquals(1, options.getBinForSample(minValue)); - - // logging max edge sample - assertEquals(binCount, options.getBinForSample(maxValue - 1)); - - // logging single valid sample per bin - final int binSize = (maxValue - minValue) / binCount; - - for (int i = 0; i < binCount; i++) { - assertEquals(i + 1, options.getBinForSample(minValue + binSize * i)); - } - } -} diff --git a/core/tests/fuzzers/ParcelFuzzer/Android.bp b/core/tests/fuzzers/ParcelFuzzer/Android.bp index b71a06e3572e..eff19853fc7e 100644 --- a/core/tests/fuzzers/ParcelFuzzer/Android.bp +++ b/core/tests/fuzzers/ParcelFuzzer/Android.bp @@ -34,6 +34,7 @@ java_fuzz { "smoreland@google.com", "waghpawan@google.com", ], + triage_assignee: "cobark@google.com", // TODO(b/280770893) // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer hotlists: ["4637097"], }, diff --git a/core/tests/fuzzers/java_service_fuzzer/Android.bp b/core/tests/fuzzers/java_service_fuzzer/Android.bp index 6acb19852210..97538a5035f3 100644 --- a/core/tests/fuzzers/java_service_fuzzer/Android.bp +++ b/core/tests/fuzzers/java_service_fuzzer/Android.bp @@ -42,6 +42,7 @@ java_fuzz { "smoreland@google.com", "waghpawan@google.com", ], + triage_assignee: "cobark@google.com", // TODO(b/261539788) // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer hotlists: ["4637097"], }, diff --git a/core/xsd/vts/OWNERS b/core/xsd/vts/OWNERS new file mode 100644 index 000000000000..9af2ebaba437 --- /dev/null +++ b/core/xsd/vts/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 151862 +sundongahn@google.com diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java index d785c3c895b8..f26b50ed4e2a 100644 --- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java +++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java @@ -21,10 +21,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.FeatureInfo; import android.content.pm.PackageManager; -import android.os.RemoteException; import android.os.ServiceManager; -import android.security.GenerateRkpKey; -import android.security.keymaster.KeymasterDefs; class CredstoreIdentityCredentialStore extends IdentityCredentialStore { @@ -125,18 +122,7 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore { @NonNull String docType) throws AlreadyPersonalizedException, DocTypeNotSupportedException { try { - IWritableCredential wc; - wc = mStore.createCredential(credentialName, docType); - try { - GenerateRkpKey keyGen = new GenerateRkpKey(mContext); - // We don't know what the security level is for the backing keymint, so go ahead and - // poke the provisioner for both TEE and SB. - keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT); - keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX); - } catch (RemoteException e) { - // Not really an error state. Does not apply at all if RKP is unsupported or - // disabled on a given device. - } + IWritableCredential wc = mStore.createCredential(credentialName, docType); return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc); } catch (android.os.RemoteException e) { throw new RuntimeException("Unexpected RemoteException ", e); diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java deleted file mode 100644 index 698133287f63..000000000000 --- a/keystore/java/android/security/GenerateRkpKey.java +++ /dev/null @@ -1,159 +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.security; - -import android.annotation.CheckResult; -import android.annotation.IntDef; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner - * app. There are two cases where Keystore should use this class. - * - * (1) : An app generates a new attested key pair, so Keystore calls notifyKeyGenerated to let the - * RemoteProvisioner app check if the state of the attestation key pool is getting low enough - * to warrant provisioning more attestation certificates early. - * - * (2) : An app attempts to generate a new key pair, but the keystore service discovers it is out of - * attestation key pairs and cannot provide one for the given application. Keystore can then - * make a blocking call on notifyEmpty to allow the RemoteProvisioner app to get another - * attestation certificate chain provisioned. - * - * In most cases, the proper usage of (1) should preclude the need for (2). - * - * @hide - */ -public class GenerateRkpKey { - private static final String TAG = "GenerateRkpKey"; - - private static final int NOTIFY_EMPTY = 0; - private static final int NOTIFY_KEY_GENERATED = 1; - private static final int TIMEOUT_MS = 1000; - - private IGenerateRkpKeyService mBinder; - private Context mContext; - private CountDownLatch mCountDownLatch; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = { - IGenerateRkpKeyService.Status.OK, - IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY, - IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR, - IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED, - IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR, - IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR, - IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR, - IGenerateRkpKeyService.Status.INTERNAL_ERROR, - }) - public @interface Status { - } - - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - mBinder = IGenerateRkpKeyService.Stub.asInterface(service); - mCountDownLatch.countDown(); - } - - @Override public void onBindingDied(ComponentName className) { - mCountDownLatch.countDown(); - } - - @Override - public void onServiceDisconnected(ComponentName className) { - mBinder = null; - } - }; - - /** - * Constructor which takes a Context object. - */ - public GenerateRkpKey(Context context) { - mContext = context; - } - - @Status - private int bindAndSendCommand(int command, int securityLevel) throws RemoteException { - Intent intent = new Intent(IGenerateRkpKeyService.class.getName()); - ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - int returnCode = IGenerateRkpKeyService.Status.OK; - if (comp == null) { - // On a system that does not use RKP, the RemoteProvisioner app won't be installed. - return returnCode; - } - intent.setComponent(comp); - mCountDownLatch = new CountDownLatch(1); - Executor executor = Executors.newCachedThreadPool(); - if (!mContext.bindService(intent, Context.BIND_AUTO_CREATE, executor, mConnection)) { - throw new RemoteException("Failed to bind to GenerateRkpKeyService"); - } - try { - mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted: ", e); - } - if (mBinder != null) { - switch (command) { - case NOTIFY_EMPTY: - returnCode = mBinder.generateKey(securityLevel); - break; - case NOTIFY_KEY_GENERATED: - mBinder.notifyKeyGenerated(securityLevel); - break; - default: - Log.e(TAG, "Invalid case for command"); - } - } else { - Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService."); - returnCode = IGenerateRkpKeyService.Status.INTERNAL_ERROR; - } - mContext.unbindService(mConnection); - return returnCode; - } - - /** - * Fulfills the use case of (2) described in the class documentation. Blocks until the - * RemoteProvisioner application can get new attestation keys signed by the server. - * @return the status of the key generation - */ - @CheckResult - @Status - public int notifyEmpty(int securityLevel) throws RemoteException { - return bindAndSendCommand(NOTIFY_EMPTY, securityLevel); - } - - /** - * Fulfills the use case of (1) described in the class documentation. Non blocking call. - */ - public void notifyKeyGenerated(int securityLevel) throws RemoteException { - bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel); - } -} diff --git a/keystore/java/android/security/GenerateRkpKeyException.java b/keystore/java/android/security/GenerateRkpKeyException.java deleted file mode 100644 index a2d65e4e7119..000000000000 --- a/keystore/java/android/security/GenerateRkpKeyException.java +++ /dev/null @@ -1,31 +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.security; - -/** - * Thrown on problems in attempting to attest to a key using a remotely provisioned key. - * - * @hide - */ -public class GenerateRkpKeyException extends Exception { - - /** - * Constructs a new {@code GenerateRkpKeyException}. - */ - public GenerateRkpKeyException() { - } -} diff --git a/keystore/java/android/security/IGenerateRkpKeyService.aidl b/keystore/java/android/security/IGenerateRkpKeyService.aidl deleted file mode 100644 index eeaeb27a7c77..000000000000 --- a/keystore/java/android/security/IGenerateRkpKeyService.aidl +++ /dev/null @@ -1,60 +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.security; - -/** - * Interface to allow the framework to notify the RemoteProvisioner app when keys are empty. This - * will be used if Keystore replies with an error code NO_KEYS_AVAILABLE in response to an - * attestation request. The framework can then synchronously call generateKey() to get more - * attestation keys generated and signed. Upon return, the caller can be certain an attestation key - * is available. - * - * @hide - */ -interface IGenerateRkpKeyService { - @JavaDerive(toString=true) - @Backing(type="int") - enum Status { - /** No error(s) occurred */ - OK = 0, - /** Unable to provision keys due to a lack of internet connectivity. */ - NO_NETWORK_CONNECTIVITY = 1, - /** An error occurred while communicating with the RKP server. */ - NETWORK_COMMUNICATION_ERROR = 2, - /** The given device was not registered with the RKP backend. */ - DEVICE_NOT_REGISTERED = 4, - /** The RKP server returned an HTTP client error, indicating a misbehaving client. */ - HTTP_CLIENT_ERROR = 5, - /** The RKP server returned an HTTP server error, indicating something went wrong on the server. */ - HTTP_SERVER_ERROR = 6, - /** The RKP server returned an HTTP status that is unknown. This should never happen. */ - HTTP_UNKNOWN_ERROR = 7, - /** An unexpected internal error occurred. This should never happen. */ - INTERNAL_ERROR = 8, - } - - /** - * Ping the provisioner service to let it know an app generated a key. This may or may not have - * consumed a remotely provisioned attestation key, so the RemoteProvisioner app should check. - */ - oneway void notifyKeyGenerated(in int securityLevel); - - /** - * Ping the provisioner service to indicate there are no remaining attestation keys left. - */ - Status generateKey(in int securityLevel); -} diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java index cb757794a11d..253d70465720 100644 --- a/keystore/java/android/security/KeyStoreException.java +++ b/keystore/java/android/security/KeyStoreException.java @@ -614,9 +614,23 @@ public class KeyStoreException extends Exception { KEYMINT_UNIMPLEMENTED_ERROR); sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE, KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_PROOF_OF_PRESENCE_REQUIRED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_NO_USER_CONFIRMATION, + KEYMINT_INCORRECT_USAGE_ERROR); sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DEVICE_LOCKED, new PublicErrorInformation(IS_SYSTEM_ERROR | REQUIRES_USER_AUTHENTICATION, ERROR_USER_AUTHENTICATION_REQUIRED)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_EARLY_BOOT_ENDED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION, + GENERAL_KEYMINT_ERROR); sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED, KEYMINT_UNIMPLEMENTED_ERROR); sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST, @@ -627,6 +641,12 @@ public class KeyStoreException extends Exception { KEYMINT_INCORRECT_USAGE_ERROR); sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER, KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_ISSUER_SUBJECT, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ISSUER_SUBJECT, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_BOOT_LEVEL_EXCEEDED, + KEYMINT_INCORRECT_USAGE_ERROR); // This should not be exposed to apps as it's handled by Keystore. sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_NOT_YET_AVAILABLE, GENERAL_KEYMINT_ERROR); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index 7571e44a7713..d12989187281 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -24,6 +24,7 @@ import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyStoreCryptoOperation; +import android.system.keystore2.Authorization; import libcore.util.EmptyArray; @@ -119,6 +120,14 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mCipher = null; } + private Authorization[] getKeyCharacteristics(Key key) { + if (!(key instanceof AndroidKeyStoreKey)) { + return new Authorization[] {}; + } + + return ((AndroidKeyStoreKey) key).getAuthorizations(); + } + @Override protected final void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { @@ -173,7 +182,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor init(opmode, key, random); initAlgorithmSpecificParameters(); try { - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(key)); } catch (InvalidAlgorithmParameterException e) { throw new InvalidKeyException(e); } @@ -206,7 +215,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor try { init(opmode, key, random); initAlgorithmSpecificParameters(params); - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(key)); success = true; } finally { if (!success) { @@ -236,7 +245,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor try { init(opmode, key, random); initAlgorithmSpecificParameters(params); - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(key)); success = true; } finally { if (!success) { @@ -310,7 +319,8 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mCachedException = null; } - private void ensureKeystoreOperationInitialized() throws InvalidKeyException, + private void ensureKeystoreOperationInitialized(Authorization[] keyCharacteristics) + throws InvalidKeyException, InvalidAlgorithmParameterException { if (mMainDataStreamer != null) { return; @@ -323,7 +333,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor } List<KeyParameter> parameters = new ArrayList<>(); - addAlgorithmSpecificParametersToBegin(parameters); + addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics); int purpose; if (mKeymasterPurposeOverride != -1) { @@ -404,7 +414,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor return null; } try { - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey)); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { mCachedException = e; return null; @@ -520,7 +530,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor } try { - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey)); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { mCachedException = e; return; @@ -597,7 +607,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor } try { - ensureKeystoreOperationInitialized(); + ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey)); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); } @@ -1012,6 +1022,22 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor @NonNull List<KeyParameter> parameters); /** + * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation, + * including the key characteristics. This is useful in case the parameters to {@code begin} + * depend on how the key was generated. + * The default implementation provided here simply ignores these key characteristics because + * they are not be needed for most engines. + * + * @param parameters keystore/keymaster arguments to be populated with algorithm-specific + * parameters. + * @param keyCharacteristics The key's characteristics. + */ + protected void addAlgorithmSpecificParametersToBegin( + @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) { + addAlgorithmSpecificParametersToBegin(parameters); + } + + /** * Invoked to obtain algorithm-specific parameters from the result of the KeyStore's * {@code begin} operation. * diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index c3b0f9bc16d3..474b7ea56be9 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -20,7 +20,6 @@ import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MG import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityThread; import android.content.Context; import android.hardware.security.keymint.EcCurve; import android.hardware.security.keymint.KeyParameter; @@ -28,9 +27,6 @@ import android.hardware.security.keymint.KeyPurpose; import android.hardware.security.keymint.SecurityLevel; import android.hardware.security.keymint.Tag; import android.os.Build; -import android.os.RemoteException; -import android.security.GenerateRkpKey; -import android.security.IGenerateRkpKeyService; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore2; import android.security.KeyStoreException; @@ -621,45 +617,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato @Override public KeyPair generateKeyPair() { - GenerateKeyPairHelperResult result = new GenerateKeyPairHelperResult(0, null); - for (int i = 0; i < 2; i++) { - /** - * NOTE: There is no need to delay between re-tries because the call to - * GenerateRkpKey.notifyEmpty() will delay for a while before returning. - */ - result = generateKeyPairHelper(); - if (result.rkpStatus == KeyStoreException.RKP_SUCCESS && result.keyPair != null) { - return result.keyPair; - } - } - - // RKP failure - if (result.rkpStatus != KeyStoreException.RKP_SUCCESS) { - KeyStoreException ksException = new KeyStoreException(ResponseCode.OUT_OF_KEYS, - "Could not get RKP keys", result.rkpStatus); - throw new ProviderException("Failed to provision new attestation keys.", ksException); - } - - return result.keyPair; - } - - private static class GenerateKeyPairHelperResult { - // Zero indicates success, non-zero indicates failure. Values should be - // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE}, - // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE}, - // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY} - // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_SOFTWARE_REBOOT} - public final int rkpStatus; - @Nullable - public final KeyPair keyPair; - - private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) { - this.rkpStatus = rkpStatus; - this.keyPair = keyPair; - } - } - - private GenerateKeyPairHelperResult generateKeyPairHelper() { if (mKeyStore == null || mSpec == null) { throw new IllegalStateException("Not initialized"); } @@ -697,26 +654,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato AndroidKeyStorePublicKey publicKey = AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse( descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm); - GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread - .currentApplication()); - try { - if (mSpec.getAttestationChallenge() != null) { - keyGen.notifyKeyGenerated(securityLevel); - } - } catch (RemoteException e) { - // This is not really an error state, and necessarily does not apply to non RKP - // systems or hybrid systems where RKP is not currently turned on. - Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e); - } success = true; - KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey()); - return new GenerateKeyPairHelperResult(0, kp); + return new KeyPair(publicKey, publicKey.getPrivateKey()); } catch (KeyStoreException e) { switch (e.getErrorCode()) { case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE: throw new StrongBoxUnavailableException("Failed to generated key pair.", e); - case ResponseCode.OUT_OF_KEYS: - return checkIfRetryableOrThrow(e, securityLevel); default: ProviderException p = new ProviderException("Failed to generate key pair.", e); if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) { @@ -742,55 +685,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } } - // In case keystore reports OUT_OF_KEYS, call this handler in an attempt to remotely provision - // some keys. - GenerateKeyPairHelperResult checkIfRetryableOrThrow(KeyStoreException e, int securityLevel) { - GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread - .currentApplication()); - KeyStoreException ksException; - try { - final int keyGenStatus = keyGen.notifyEmpty(securityLevel); - // Default stance: temporary error. This is a hint to the caller to try again with - // exponential back-off. - int rkpStatus; - switch (keyGenStatus) { - case IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY: - rkpStatus = KeyStoreException.RKP_FETCHING_PENDING_CONNECTIVITY; - break; - case IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED: - rkpStatus = KeyStoreException.RKP_SERVER_REFUSED_ISSUANCE; - break; - case IGenerateRkpKeyService.Status.OK: - // Explicitly return not-OK here so we retry in generateKeyPair. All other cases - // should throw because a retry doesn't make sense if we didn't actually - // provision fresh keys. - return new GenerateKeyPairHelperResult( - KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null); - case IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR: - case IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR: - case IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR: - case IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR: - case IGenerateRkpKeyService.Status.INTERNAL_ERROR: - default: - // These errors really should never happen. The best we can do is assume they - // are transient and hint to the caller to retry with back-off. - rkpStatus = KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE; - break; - } - ksException = new KeyStoreException( - ResponseCode.OUT_OF_KEYS, - "Out of RKP keys due to IGenerateRkpKeyService status: " + keyGenStatus, - rkpStatus); - } catch (RemoteException f) { - ksException = new KeyStoreException( - ResponseCode.OUT_OF_KEYS, - "Remote exception: " + f.getMessage(), - KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE); - } - ksException.initCause(e); - throw new ProviderException("Failed to provision new attestation keys.", ksException); - } - private void addAttestationParameters(@NonNull List<KeyParameter> params) throws ProviderException, IllegalArgumentException, DeviceIdAttestationException { byte[] challenge = mSpec.getAttestationChallenge(); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java index e9b66aafc262..3bb2564807b6 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java @@ -288,16 +288,34 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } + private static boolean isMgfDigestTagPresentInKeyProperties( + Authorization[] keyCharacteristics) { + for (Authorization authorization : keyCharacteristics) { + if (authorization.keyParameter.tag == KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST) { + return true; + } + } + + return false; + } + @Override protected final void addAlgorithmSpecificParametersToBegin( - @NonNull List<KeyParameter> parameters) { - super.addAlgorithmSpecificParametersToBegin(parameters); + @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) { + super.addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics); parameters.add(KeyStore2ParameterUtils.makeEnum( KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest )); - parameters.add(KeyStore2ParameterUtils.makeEnum( - KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest - )); + // Only add the KM_TAG_RSA_OAEP_MGF_DIGEST tag to begin() if the MGF Digest is + // present in the key properties. Keys generated prior to Android 14 did not have + // this tag (Keystore didn't add it) so specifying any MGF digest tag would cause + // a begin() operation (on an Android 14 device) to fail (with a key that was generated + // on Android 13 or below). + if (isMgfDigestTagPresentInKeyProperties(keyCharacteristics)) { + parameters.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest + )); + } } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS index ccbb9cf298a2..a3803ed82844 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS @@ -1,3 +1,4 @@ # WM shell sub-module freeform owners atsjenk@google.com +jorgegil@google.com madym@google.com diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS index 64dfc3ef845d..deebad545c5e 100644 --- a/libs/WindowManager/Shell/tests/OWNERS +++ b/libs/WindowManager/Shell/tests/OWNERS @@ -8,3 +8,4 @@ madym@google.com hwwang@google.com chenghsiuchang@google.com atsjenk@google.com +jorgegil@google.com diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h index 3dbf997dc367..38ece5c1546f 100644 --- a/libs/androidfw/include/androidfw/ObbFile.h +++ b/libs/androidfw/include/androidfw/ObbFile.h @@ -43,10 +43,6 @@ public: bool removeFrom(const char* filename); bool removeFrom(int fd); - const char* getFileName() const { - return mFileName; - } - const String8 getPackageName() const { return mPackageName; } @@ -127,8 +123,6 @@ private: /* The encryption salt. */ unsigned char mSalt[8]; - const char* mFileName; - size_t mFooterStart; bool parseObbFile(int fd); diff --git a/libs/hwui/AndroidTest.xml b/libs/hwui/AndroidTest.xml index 911315f81a8a..75f61f5f7f9d 100644 --- a/libs/hwui/AndroidTest.xml +++ b/libs/hwui/AndroidTest.xml @@ -21,6 +21,7 @@ <option name="push" value="hwuimacro->/data/local/tmp/benchmarktest/hwuimacro" /> </target_preparer> <option name="test-suite-tag" value="apct" /> + <option name="not-shardable" value="true" /> <test class="com.android.tradefed.testtype.GTest" > <option name="native-test-device-path" value="/data/local/tmp/nativetest" /> <option name="module-name" value="hwui_unit_tests" /> diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp index ce5ac382aeff..f632d093d9f3 100644 --- a/libs/hwui/jni/FontFamily.cpp +++ b/libs/hwui/jni/FontFamily.cpp @@ -44,6 +44,7 @@ namespace android { +namespace { struct NativeFamilyBuilder { NativeFamilyBuilder(uint32_t langId, int variant) : langId(langId), variant(static_cast<minikin::FamilyVariant>(variant)) {} @@ -52,6 +53,7 @@ struct NativeFamilyBuilder { std::vector<std::shared_ptr<minikin::Font>> fonts; std::vector<minikin::FontVariation> axes; }; +} // namespace static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) { return reinterpret_cast<NativeFamilyBuilder*>(ptr); diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp index b68213549938..ac1c05ed6afe 100644 --- a/libs/hwui/jni/fonts/FontFamily.cpp +++ b/libs/hwui/jni/fonts/FontFamily.cpp @@ -29,9 +29,11 @@ namespace android { +namespace { struct NativeFamilyBuilder { std::vector<std::shared_ptr<minikin::Font>> fonts; }; +} // namespace static inline NativeFamilyBuilder* toBuilder(jlong ptr) { return reinterpret_cast<NativeFamilyBuilder*>(ptr); diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index 8e350d5012a5..b5c1b490182f 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -53,6 +53,8 @@ SkiaOpenGLPipeline::~SkiaOpenGLPipeline() { } MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() { + bool wasSurfaceless = mEglManager.isCurrent(EGL_NO_SURFACE); + // In case the surface was destroyed (e.g. a previous trimMemory call) we // need to recreate it here. if (!isSurfaceReady() && mNativeWindow) { @@ -63,6 +65,40 @@ MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() { if (!mEglManager.makeCurrent(mEglSurface, &error)) { return MakeCurrentResult::AlreadyCurrent; } + + EGLint majorVersion = 0; + eglQueryContext(eglGetCurrentDisplay(), eglGetCurrentContext(), EGL_CONTEXT_CLIENT_VERSION, &majorVersion); + + // Make sure read/draw buffer state of default framebuffer is GL_BACK for ES 3.X. Vendor implementations + // disagree on the draw/read buffer state if the default framebuffer transitions from a surface + // to EGL_NO_SURFACE and vice-versa. There was a related discussion within Khronos on this topic. + // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13534. + // The discussion was not resolved with a clear consensus + if (error == 0 && (majorVersion > 2) && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) { + GLint curReadFB = 0; + GLint curDrawFB = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curReadFB); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curDrawFB); + + GLint buffer = GL_NONE; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glGetIntegerv(GL_DRAW_BUFFER0, &buffer); + if (buffer == GL_NONE) { + const GLenum drawBuffer = GL_BACK; + glDrawBuffers(1, &drawBuffer); + } + + glGetIntegerv(GL_READ_BUFFER, &buffer); + if (buffer == GL_NONE) { + glReadBuffer(GL_BACK); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, curReadFB); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, curDrawFB); + + GL_CHECKPOINT(LOW); + } + return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded; } diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index f85bdee18967..094a33f3f2ba 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -25,6 +25,8 @@ import android.media.AudioFormat; import android.media.AudioSystem; import android.os.Build; +import com.android.internal.annotations.VisibleForTesting; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -252,10 +254,10 @@ public class AudioMix { if (o == null || getClass() != o.getClass()) return false; final AudioMix that = (AudioMix) o; - return (this.mRouteFlags == that.mRouteFlags) - && (this.mRule == that.mRule) - && (this.mMixType == that.mMixType) - && (this.mFormat == that.mFormat); + return Objects.equals(this.mRouteFlags, that.mRouteFlags) + && Objects.equals(this.mRule, that.mRule) + && Objects.equals(this.mMixType, that.mMixType) + && Objects.equals(this.mFormat, that.mFormat); } /** @hide */ @@ -340,7 +342,8 @@ public class AudioMix { * @param address * @return the same Builder instance. */ - Builder setDevice(int deviceType, String address) { + @VisibleForTesting + public Builder setDevice(int deviceType, String address) { mDeviceSystemType = deviceType; mDeviceAddress = address; return this; diff --git a/media/java/android/media/musicrecognition/OWNERS b/media/java/android/media/musicrecognition/OWNERS index 58f5d40dd8c3..037b04831260 100644 --- a/media/java/android/media/musicrecognition/OWNERS +++ b/media/java/android/media/musicrecognition/OWNERS @@ -1,6 +1,5 @@ # Bug component: 830636 -joannechung@google.com oni@google.com volnov@google.com diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h index c7530207d1fa..060abfdc1ee5 100644 --- a/media/jni/android_media_MediaCodecLinearBlock.h +++ b/media/jni/android_media_MediaCodecLinearBlock.h @@ -44,12 +44,19 @@ struct JMediaCodecLinearBlock { std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const { if (mBuffer) { + // TODO: if returned C2Buffer is different from mBuffer, we should + // find a way to connect the life cycle between this C2Buffer and + // mBuffer. if (mBuffer->data().type() != C2BufferData::LINEAR) { return nullptr; } C2ConstLinearBlock block = mBuffer->data().linearBlocks().front(); if (offset == 0 && size == block.capacity()) { - return mBuffer; + // Let C2Buffer be new one to queue to MediaCodec. It will allow + // the related input slot to be released by onWorkDone from C2 + // Component. Currently, the life cycle of mBuffer should be + // protected by different flows. + return std::make_shared<C2Buffer>(*mBuffer); } std::shared_ptr<C2Buffer> buffer = diff --git a/mime/java/Android.bp b/mime/java/Android.bp index 07cada8e1372..a267d6593f65 100644 --- a/mime/java/Android.bp +++ b/mime/java/Android.bp @@ -10,5 +10,8 @@ package { filegroup { name: "framework-mime-sources", srcs: ["**/*.java"], - visibility: ["//frameworks/base"], + visibility: [ + "//frameworks/base", + "//frameworks/base/api", + ], } diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp index 9e0a6eb476d3..294ca9cfd3b4 100644 --- a/native/android/storage_manager.cpp +++ b/native/android/storage_manager.cpp @@ -86,7 +86,7 @@ protected: return nullptr; } - String16 fileName(obbFile->getFileName()); + String16 fileName(canonicalPath); String16 packageName(obbFile->getPackageName()); size_t length; const unsigned char* salt = obbFile->getSalt(&length); diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml index 176534829222..cd404385d5a0 100644 --- a/packages/DynamicSystemInstallationService/AndroidManifest.xml +++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml @@ -39,6 +39,10 @@ <data android:scheme="http" /> <data android:scheme="https" /> </intent-filter> + <intent-filter> + <action android:name="android.os.image.action.START_INSTALL" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> </activity> <receiver diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 55626844594d..5e42f705cf4b 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -19,6 +19,7 @@ package com.android.dynsystem; import static android.os.AsyncTask.Status.FINISHED; import static android.os.AsyncTask.Status.PENDING; import static android.os.AsyncTask.Status.RUNNING; +import static android.os.image.DynamicSystemClient.ACTION_HIDE_NOTIFICATION; import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE; import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL; import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION; @@ -27,6 +28,8 @@ import static android.os.image.DynamicSystemClient.CAUSE_ERROR_IO; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED; import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED; +import static android.os.image.DynamicSystemClient.KEY_ENABLE_WHEN_COMPLETED; +import static android.os.image.DynamicSystemClient.KEY_ONE_SHOT; import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS; import static android.os.image.DynamicSystemClient.STATUS_IN_USE; import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED; @@ -77,8 +80,6 @@ public class DynamicSystemInstallationService extends Service private static final String TAG = "DynamicSystemInstallationService"; - // TODO (b/131866826): This is currently for test only. Will move this to System API. - static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; static final String KEY_DSU_SLOT = "KEY_DSU_SLOT"; static final String DEFAULT_DSU_SLOT = "dsu"; static final String KEY_PUBKEY = "KEY_PUBKEY"; @@ -172,6 +173,8 @@ public class DynamicSystemInstallationService extends Service // This is for testing only now private boolean mEnableWhenCompleted; + private boolean mOneShot; + private boolean mHideNotification; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; @@ -229,6 +232,8 @@ public class DynamicSystemInstallationService extends Service executeRebootToNormalCommand(); } else if (ACTION_NOTIFY_IF_IN_USE.equals(action)) { executeNotifyIfInUseCommand(); + } else if (ACTION_HIDE_NOTIFICATION.equals(action)) { + executeHideNotificationCommand(); } return Service.START_NOT_STICKY; @@ -318,6 +323,7 @@ public class DynamicSystemInstallationService extends Service long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0); long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0); mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false); + mOneShot = intent.getBooleanExtra(KEY_ONE_SHOT, true); String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT); String publicKey = intent.getStringExtra(KEY_PUBKEY); @@ -384,9 +390,9 @@ public class DynamicSystemInstallationService extends Service boolean enabled = false; if (mInstallTask != null && mInstallTask.isCompleted()) { - enabled = mInstallTask.commit(); + enabled = mInstallTask.commit(mOneShot); } else if (isDynamicSystemInstalled()) { - enabled = mDynSystem.setEnable(true, true); + enabled = mDynSystem.setEnable(true, mOneShot); } else { Log.e(TAG, "Trying to reboot to AOT while there is no complete installation"); return; @@ -439,12 +445,16 @@ public class DynamicSystemInstallationService extends Service private void executeNotifyIfInUseCommand() { switch (getStatus()) { case STATUS_IN_USE: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_READY: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_IN_PROGRESS: break; @@ -454,6 +464,16 @@ public class DynamicSystemInstallationService extends Service } } + private void executeHideNotificationCommand() { + mHideNotification = true; + switch (getStatus()) { + case STATUS_IN_USE: + case STATUS_READY: + stopForeground(STOP_FOREGROUND_REMOVE); + break; + } + } + private void resetTaskAndStop() { resetTaskAndStop(/* removeNotification= */ false); } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index a41399fb0d0d..42b620abe734 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -803,7 +803,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { return mIsCompleted; } - boolean commit() { - return mDynSystem.setEnable(true, true); + boolean commit(boolean oneShot) { + return mDynSystem.setEnable(true, oneShot); } } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java index 64e42cc595ec..b52272961e4b 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java @@ -16,6 +16,8 @@ package com.android.dynsystem; +import static android.os.image.DynamicSystemClient.KEY_KEYGUARD_USE_DEFAULT_STRINGS; + import android.app.Activity; import android.app.KeyguardManager; import android.content.Context; @@ -47,10 +49,7 @@ public class VerificationActivity extends Activity { KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); if (km != null) { - String title = getString(R.string.keyguard_title); - String description = getString(R.string.keyguard_description); - Intent intent = km.createConfirmDeviceCredentialIntent(title, description); - + Intent intent = createConfirmDeviceCredentialIntent(km); if (intent == null) { Log.d(TAG, "This device is not protected by a password/pin"); startInstallationService(); @@ -63,6 +62,23 @@ public class VerificationActivity extends Activity { } } + private Intent createConfirmDeviceCredentialIntent(KeyguardManager km) { + final boolean useDefaultStrings = + getIntent().getBooleanExtra(KEY_KEYGUARD_USE_DEFAULT_STRINGS, false); + final String title; + final String description; + if (useDefaultStrings) { + // Use default strings provided by keyguard manager + title = null; + description = null; + } else { + // Use custom strings provided by DSU + title = getString(R.string.keyguard_title); + description = getString(R.string.keyguard_description); + } + return km.createConfirmDeviceCredentialIntent(title, description); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) { diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp index 69a1d7fa59e4..ef0d122c7273 100644 --- a/packages/PrintSpooler/tests/outofprocess/Android.bp +++ b/packages/PrintSpooler/tests/outofprocess/Android.bp @@ -31,7 +31,7 @@ android_test { libs: ["android.test.runner.stubs"], static_libs: [ "androidx.test.rules", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "mockito-target-minus-junit4", "print-test-util-lib", ], diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java index 132545b2d5d2..1509b7077046 100644 --- a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java +++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java @@ -35,15 +35,15 @@ import android.print.test.services.AddPrintersActivity; import android.print.test.services.FirstPrintService; import android.print.test.services.PrinterDiscoverySessionCallbacks; import android.print.test.services.StubbablePrinterDiscoverySession; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; import android.util.Log; import androidx.test.filters.LargeTest; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java index 879181f0fbd6..2d958a919793 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java @@ -6,6 +6,7 @@ import android.annotation.SuppressLint; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -162,14 +163,21 @@ public class BluetoothUtils { resources, ((BitmapDrawable) pair.first).getBitmap()), pair.second); } + int hashCode; + if ((cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) { + hashCode = new Integer(cachedDevice.getGroupId()).hashCode(); + } else { + hashCode = cachedDevice.getAddress().hashCode(); + } + return new Pair<>(buildBtRainbowDrawable(context, - pair.first, cachedDevice.getAddress().hashCode()), pair.second); + pair.first, hashCode), pair.second); } /** * Build Bluetooth device icon with rainbow */ - public static Drawable buildBtRainbowDrawable(Context context, Drawable drawable, + private static Drawable buildBtRainbowDrawable(Context context, Drawable drawable, int hashCode) { final Resources resources = context.getResources(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index fe448fccae3a..6ef5d7347d31 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -576,9 +576,14 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> */ public void setName(String name) { // Prevent getName() to be set to null if setName(null) is called - if (name != null && !TextUtils.equals(name, getName())) { - mDevice.setAlias(name); - dispatchAttributesChanged(); + if (name == null || TextUtils.equals(name, getName())) { + return; + } + mDevice.setAlias(name); + dispatchAttributesChanged(); + + for (CachedBluetoothDevice cbd : mMemberDevices) { + cbd.setName(name); } } @@ -1497,8 +1502,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> refresh(); } - return new Pair<>(BluetoothUtils.buildBtRainbowDrawable( - mContext, pair.first, getAddress().hashCode()), pair.second); + return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this); } void releaseLruCache() { diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java index fb3f382af192..e91d697d4b86 100644 --- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java +++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java @@ -324,6 +324,7 @@ class LicenseHtmlGeneratorFromXml { if (!TextUtils.isEmpty(noticeHeader)) { writer.println(noticeHeader); + writer.println("<br/>"); } int count = 0; diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS index 0f888113d730..d901e2cec358 100644 --- a/packages/SettingsProvider/src/android/provider/settings/OWNERS +++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS @@ -1,4 +1,4 @@ # Bug component: 656484 -include platform/frameworks/base:/services/backup/OWNERS +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS index 0f888113d730..db4b27c8bc5a 100644 --- a/packages/SettingsProvider/test/src/android/provider/OWNERS +++ b/packages/SettingsProvider/test/src/android/provider/OWNERS @@ -1,4 +1,3 @@ # Bug component: 656484 -include platform/frameworks/base:/services/backup/OWNERS - +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 402d73c443a3..811b40943661 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -55,6 +55,7 @@ lynhan@google.com madym@google.com mankoff@google.com mateuszc@google.com +mgalhardo@google.com michaelmikhil@google.com michschn@google.com mkephart@google.com diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index 0f81b0b8d6e0..3889030d5566 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -298,10 +298,16 @@ constructor( ) { val view = openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground - ?: throw IllegalStateException( - "The animateFrom dialog was not animated using " + - "DialogLaunchAnimator.showFrom(View|Dialog)" - ) + if (view == null) { + Log.w( + TAG, + "Showing dialog $dialog normally as the dialog it is shown from was not shown " + + "using DialogLaunchAnimator" + ) + dialog.show() + return + } + showFromView( dialog, view, diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 3b71dc32b256..d10332bcbffb 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -78,7 +78,7 @@ android:layout_width="match_parent" android:clipChildren="false"> <ViewStub - android:id="@+id/operator_name" + android:id="@+id/operator_name_stub" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout="@layout/operator_name" /> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java index a16f30475654..8658c64e7993 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java @@ -52,7 +52,7 @@ public class KeyguardSimPinViewController private ProgressDialog mSimUnlockProgressDialog; private CheckSimPin mCheckSimPinThread; - private int mRemainingAttempts; + private int mRemainingAttempts = -1; // Below flag is set to true during power-up or when a new SIM card inserted on device. // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would // be displayed to inform user about the number of remaining PIN attempts left. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 93027c1914ee..92054b317637 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1840,6 +1840,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab state = TelephonyManager.SIM_STATE_PIN_REQUIRED; } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) { state = TelephonyManager.SIM_STATE_PUK_REQUIRED; + } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) { + state = TelephonyManager.SIM_STATE_PERM_DISABLED; } else { state = TelephonyManager.SIM_STATE_UNKNOWN; } @@ -2735,7 +2737,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean shouldListen = shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState && shouldListenUdfpsState - && shouldListenSideFpsState; + && shouldListenSideFpsState + && !isFingerprintLockedOut(); logListenerModelData( new KeyguardFingerprintListenModel( System.currentTimeMillis(), diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java index 03d999f697d0..9f948a7f92ff 100644 --- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java @@ -325,7 +325,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver { // TODO(b/140051051) final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System .getIntForUser(getContext().getContentResolver(), - SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT)); + SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean( + com.android.internal.R.bool.config_defaultBatteryPercentageSetting) + ? 1 : 0, UserHandle.USER_CURRENT)); boolean shouldShow = (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF) || mShowPercentMode == MODE_ON diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 9f3fd727be24..5ca7ba013bbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -636,9 +636,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private void initOperatorName() { int subId = SubscriptionManager.getDefaultDataSubscriptionId(); if (mCarrierConfigTracker.getShowOperatorNameInStatusBarConfig(subId)) { - ViewStub stub = mStatusBar.findViewById(R.id.operator_name); + View view = mStatusBar.findViewById(R.id.operator_name); mOperatorNameViewController = - mOperatorNameViewControllerFactory.create((OperatorNameView) stub.inflate()); + mOperatorNameViewControllerFactory.create((OperatorNameView) view); mOperatorNameViewController.init(); // This view should not be visible on lock-screen if (mKeyguardStateController.isShowing()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java index 730ecded58e2..8f9f0196abfa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone.fragment.dagger; import android.view.View; +import android.view.ViewStub; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; @@ -95,7 +96,7 @@ public interface StatusBarFragmentModule { @StatusBarFragmentScope @Named(OPERATOR_NAME_VIEW) static View provideOperatorNameView(@RootView PhoneStatusBarView view) { - return view.findViewById(R.id.operator_name); + return ((ViewStub) view.findViewById(R.id.operator_name_stub)).inflate(); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java index 05e566690f57..29f16c7b924a 100644 --- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java +++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java @@ -272,10 +272,10 @@ public class SystemUIToast implements ToastPlugin.Toast { private static boolean showApplicationIcon(ApplicationInfo appInfo, PackageManager packageManager) { - if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP)) { + if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP | FLAG_SYSTEM)) { return packageManager.getLaunchIntentForPackage(appInfo.packageName) != null; } - return !hasFlag(appInfo.flags, FLAG_SYSTEM); + return true; } private static boolean hasFlag(int flags, int flag) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 13cd328d00e0..73e11d7ef833 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -28,6 +28,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED; +import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING; import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT; import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT; @@ -1040,10 +1041,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked); assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked); - // Fingerprint should be restarted once its cancelled bc on lockout, the device - // can still detectFingerprint (and if it's not locked out, fingerprint can listen) + // Fingerprint should be cancelled on lockout if going to lockout state, else + // restarted if it's not assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState) - .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING); + .isEqualTo(fpLocked + ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt index cac4a0e5432c..82af0f418ea4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt @@ -260,6 +260,12 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { assertThat(touchSurface.visibility).isEqualTo(View.GONE) } + @Test + fun showFromDialogDoesNotCrashWhenShownFromRandomDialog() { + val dialog = createDialogAndShowFromDialog(animateFrom = TestDialog(context)) + dialog.dismiss() + } + private fun createAndShowDialog( animator: DialogLaunchAnimator = dialogLaunchAnimator, ): TestDialog { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 1e9c3b72f57c..c7a7959c915d 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1842,6 +1842,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub AccessibilityServiceInfo accessibilityServiceInfo; try { accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); + if (!accessibilityServiceInfo.isWithinParcelableSize()) { + Slog.e(LOG_TAG, "Skipping service " + + accessibilityServiceInfo.getResolveInfo().getComponentInfo() + + " because service info size is larger than safe parcelable limits."); + continue; + } if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) { // Restore the crashed attribute. accessibilityServiceInfo.crashed = true; diff --git a/services/backup/BACKUP_OWNERS b/services/backup/BACKUP_OWNERS new file mode 100644 index 000000000000..f8f4f4f4bf2e --- /dev/null +++ b/services/backup/BACKUP_OWNERS @@ -0,0 +1,10 @@ +# Bug component: 1193469 + +jstemmer@google.com +martinoh@google.com +millmore@google.com +niamhfw@google.com +piee@google.com +philippov@google.com +rthakohov@google.com +sarpm@google.com
\ No newline at end of file diff --git a/services/backup/OWNERS b/services/backup/OWNERS index 79709a3319c8..3bd2db13eea1 100644 --- a/services/backup/OWNERS +++ b/services/backup/OWNERS @@ -2,12 +2,4 @@ set noparent -bryanmawhinney@google.com -jstemmer@google.com -martinoh@google.com -millmore@google.com -niamhfw@google.com -piee@google.com -philippov@google.com -rthakohov@google.com -sarpm@google.com +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/services/core/Android.bp b/services/core/Android.bp index 6a14deabee4b..d885cd197387 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -155,6 +155,7 @@ java_library_static { "android.hardware.health-V2-java", // AIDL "android.hardware.health-translate-java", "android.hardware.light-V1-java", + "android.hardware.security.rkp-V3-java", "android.hardware.tv.cec-V1.1-java", "android.hardware.tv.hdmi.cec-V1-java", "android.hardware.tv.hdmi.connection-V1-java", @@ -171,6 +172,7 @@ java_library_static { "android.hardware.power-V3-java", "android.hidl.manager-V1.2-java", "capture_state_listener-aidl-java", + "cbor-java", "icu4j_calendar_astronomer", "netd-client", "overlayable_policy_aidl-java", diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index 27215b2fbf30..b0c1d05b0dd4 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -44,7 +44,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { private static final String TAG = "DynamicSystemService"; private static final long MINIMUM_SD_MB = (30L << 10); private static final int GSID_ROUGH_TIMEOUT_MS = 8192; - private static final String PATH_DEFAULT = "/data/gsi/"; + private static final String PATH_DEFAULT = "/data/gsi/dsu/"; private Context mContext; private String mInstallPath, mDsuSlot; private volatile IGsiService mGsiService; diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 409f0541eed7..123cd3288343 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -27,6 +27,7 @@ per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS per-file *Storage* = file:/core/java/android/os/storage/OWNERS per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 77a54a568859..1afda6572a21 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1578,57 +1578,62 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } - synchronized (mRecords) { - String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId - + " state=" + state; - if (VDBG) { - log(str); - } - mLocalLog.log(str); - // for service state updates, don't notify clients when subId is invalid. This prevents - // us from sending incorrect notifications like b/133140128 - // In the future, we can remove this logic for every notification here and add a - // callback so listeners know when their PhoneStateListener's subId becomes invalid, but - // for now we use the simplest fix. - if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) { - mServiceState[phoneId] = state; + final long callingIdentity = Binder.clearCallingIdentity(); + try { + synchronized (mRecords) { + String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + + phoneId + " state=" + state; + if (VDBG) { + log(str); + } + mLocalLog.log(str); + // for service state updates, don't notify clients when subId is invalid. This + // prevents us from sending incorrect notifications like b/133140128 + // In the future, we can remove this logic for every notification here and add a + // callback so listeners know when their PhoneStateListener's subId becomes invalid, + // but for now we use the simplest fix. + if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) { + mServiceState[phoneId] = state; - for (Record r : mRecords) { - if (VDBG) { - log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId - + " phoneId=" + phoneId + " state=" + state); - } - if (r.matchTelephonyCallbackEvent( - TelephonyCallback.EVENT_SERVICE_STATE_CHANGED) - && idMatch(r, subId, phoneId)) { + for (Record r : mRecords) { + if (VDBG) { + log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId + + " phoneId=" + phoneId + " state=" + state); + } + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_SERVICE_STATE_CHANGED) + && idMatch(r, subId, phoneId)) { - try { - ServiceState stateToSend; - if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { - stateToSend = new ServiceState(state); - } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { - stateToSend = state.createLocationInfoSanitizedCopy(false); - } else { - stateToSend = state.createLocationInfoSanitizedCopy(true); - } - if (DBG) { - log("notifyServiceStateForSubscriber: callback.onSSC r=" + r - + " subId=" + subId + " phoneId=" + phoneId - + " state=" + state); + try { + ServiceState stateToSend; + if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { + stateToSend = new ServiceState(state); + } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { + stateToSend = state.createLocationInfoSanitizedCopy(false); + } else { + stateToSend = state.createLocationInfoSanitizedCopy(true); + } + if (DBG) { + log("notifyServiceStateForSubscriber: callback.onSSC r=" + r + + " subId=" + subId + " phoneId=" + phoneId + + " state=" + stateToSend); + } + r.callback.onServiceStateChanged(stateToSend); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); } - r.callback.onServiceStateChanged(stateToSend); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); } } + } else { + log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId + + " or subId=" + subId); } - } else { - log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId - + " or subId=" + subId); + handleRemoveListLocked(); } - handleRemoveListLocked(); + broadcastServiceStateChanged(state, phoneId, subId); + } finally { + Binder.restoreCallingIdentity(callingIdentity); } - broadcastServiceStateChanged(state, phoneId, subId); } public void notifySimActivationStateChangedForPhoneId(int phoneId, int subId, @@ -3161,13 +3166,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { public static final String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR"; private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) { - final long ident = Binder.clearCallingIdentity(); try { mBatteryStats.notePhoneState(state.getState()); } catch (RemoteException re) { // Can't do much - } finally { - Binder.restoreCallingIdentity(ident); } // Send the broadcast exactly once to all possible disjoint sets of apps. @@ -3184,8 +3186,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not // READ_PHONE_STATE - if (Binder.withCleanCallingIdentity(() -> - LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) { + if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) { Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 89447b457c20..f8467410b3ba 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3091,7 +3091,7 @@ public class AccountManagerService } } - Intent intent = result.getParcelable(AccountManager.KEY_INTENT); + Intent intent = result.getParcelable(AccountManager.KEY_INTENT, Intent.class); if (intent != null && notifyOnAuthFailure && !customTokens) { /* * Make sure that the supplied intent is owned by the authenticator @@ -3516,8 +3516,7 @@ public class AccountManagerService Bundle.setDefusable(result, true); mNumResults++; Intent intent = null; - if (result != null - && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { + if (result != null) { if (!checkKeyIntent( Binder.getCallingUid(), result)) { @@ -4886,8 +4885,10 @@ public class AccountManagerService EventLog.writeEvent(0x534e4554, "250588548", authUid, ""); return false; } - Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); + if (intent == null) { + return true; + } // Explicitly set an empty ClipData to ensure that we don't offer to // promote any Uris contained inside for granting purposes if (intent.getClipData() == null) { @@ -4937,8 +4938,12 @@ public class AccountManagerService Bundle simulateBundle = p.readBundle(); p.recycle(); Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); - return (intent.filterEquals(simulateBundle.getParcelable(AccountManager.KEY_INTENT, - Intent.class))); + Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT, + Intent.class); + if (intent == null) { + return (simulateIntent == null); + } + return intent.filterEquals(simulateIntent); } private boolean isExportedSystemActivity(ActivityInfo activityInfo) { @@ -5087,8 +5092,7 @@ public class AccountManagerService } } } - if (result != null - && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { + if (result != null) { if (!checkKeyIntent( Binder.getCallingUid(), result)) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9669c060b716..c36e0700c723 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3420,6 +3420,11 @@ public final class ActiveServices { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + className + " is not an isolatedProcess"); } + if (!mAm.getPackageManagerInternal().isSameApp(callingPackage, callingUid, + userId)) { + throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + + "calling package not owned by calling UID "); + } // Run the service under the calling package's application. ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo( callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 99f186351f0f..148688fc4aa5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8496,7 +8496,9 @@ public class ActivityManagerService extends IActivityManager.Stub // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes, // debuggerd will terminate the process, but there's a backup where ActivityManager will // also kill it. Avoid that. - if (!recoverable) { + if (recoverable) { + mAppErrors.sendRecoverableCrashToAppExitInfo(r, crashInfo); + } else { mAppErrors.crashApplication(r, crashInfo); } } @@ -10782,6 +10784,13 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **"); pw.flush(); try { + if (pid == Process.myPid()) { + // Directly dump to target fd for local dump to avoid hang. + try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd.getInt$())) { + thread.dumpCacheInfo(pfd, args); + } + continue; + } TransferPipe tp = new TransferPipe(); try { thread.dumpCacheInfo(tp.getWriteFd(), args); @@ -13098,12 +13107,17 @@ public class ActivityManagerService extends IActivityManager.Stub public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage, String callerFeatureId, String receiverId, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { + enforceNotIsolatedCaller("registerReceiver"); + // Allow Sandbox process to register only unexported receivers. - if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) { - enforceNotIsolatedCaller("registerReceiver"); - } else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) { - enforceNotIsolatedOrSdkSandboxCaller("registerReceiver"); + boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0; + if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced() + && Process.isSdkSandboxUid(Binder.getCallingUid()) + && !unexported) { + throw new SecurityException("SDK sandbox process not allowed to call " + + "registerReceiver"); } + ArrayList<Intent> stickyIntents = null; ProcessRecord callerApp = null; final boolean visibleToInstantApps @@ -14666,6 +14680,17 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException(msg); } } + if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID + && callingUid != SYSTEM_UID && !hasActiveInstrumentationLocked(callingPid)) { + // If it's not debug build and not called from root/shell/system uid, reject it. + final String msg = "Permission Denial: instrumentation test " + + className + " from pid=" + callingPid + ", uid=" + callingUid + + ", pkgName=" + getPackageNameByPid(callingPid) + + " not allowed because it's not started from SHELL"; + Slog.wtfQuiet(TAG, msg); + reportStartInstrumentationFailureLocked(watcher, className, msg); + throw new SecurityException(msg); + } boolean disableHiddenApiChecks = ai.usesNonSdkApi() || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0; @@ -14888,6 +14913,29 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") + private boolean hasActiveInstrumentationLocked(int pid) { + if (pid == 0) { + return false; + } + synchronized (mPidsSelfLocked) { + ProcessRecord process = mPidsSelfLocked.get(pid); + return process != null && process.getActiveInstrumentation() != null; + } + } + + private String getPackageNameByPid(int pid) { + synchronized (mPidsSelfLocked) { + final ProcessRecord app = mPidsSelfLocked.get(pid); + + if (app != null && app.info != null) { + return app.info.packageName; + } + + return null; + } + } + private boolean isCallerShell() { final int callingUid = Binder.getCallingUid(); return callingUid == SHELL_UID || callingUid == ROOT_UID; diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 08c1de61d7fb..c475f008c831 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -553,6 +553,15 @@ class AppErrors { } } + void sendRecoverableCrashToAppExitInfo( + ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + if (r == null || crashInfo == null + || !"Native crash".equals(crashInfo.exceptionClassName)) return; + synchronized (mService) { + mService.mProcessList.noteAppRecoverableCrash(r); + } + } + /** * Bring up the "unexpected error" dialog box for a crashing app. * Deal with edge cases (intercepts from instrumented applications, diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java index 32d20718c192..df1f3c7ec774 100644 --- a/services/core/java/com/android/server/am/AppExitInfoTracker.java +++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java @@ -308,6 +308,16 @@ public final class AppExitInfoTracker { mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget(); } + void scheduleNoteAppRecoverableCrash(final ProcessRecord app) { + if (!mAppExitInfoLoaded.get() || app == null || app.info == null) return; + + ApplicationExitInfo raw = obtainRawRecord(app, System.currentTimeMillis()); + raw.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE); + raw.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN); + raw.setDescription("recoverable_crash"); + mKillHandler.obtainMessage(KillHandler.MSG_APP_RECOVERABLE_CRASH, raw).sendToTarget(); + } + void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason, final @SubReason int subReason, final String msg) { if (!mAppExitInfoLoaded.get()) { @@ -421,8 +431,24 @@ public final class AppExitInfoTracker { scheduleLogToStatsdLocked(info, true); } + /** + * Make note when ActivityManagerService gets a recoverable native crash, as the process isn't + * being killed but the crash should still be added to AppExitInfo. Also, because we're not + * crashing, don't log out to statsd. + */ + @VisibleForTesting + @GuardedBy("mLock") + void handleNoteAppRecoverableCrashLocked(final ApplicationExitInfo raw) { + addExitInfoLocked(raw, /* recoverable */ true); + } + @GuardedBy("mLock") private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) { + return addExitInfoLocked(raw, /* recoverable */ false); + } + + @GuardedBy("mLock") + private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw, boolean recoverable) { if (!mAppExitInfoLoaded.get()) { Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage"); return null; @@ -438,7 +464,7 @@ public final class AppExitInfoTracker { } } for (int i = 0; i < packages.length; i++) { - addExitInfoInnerLocked(packages[i], uid, info); + addExitInfoInnerLocked(packages[i], uid, info, recoverable); } schedulePersistProcessExitInfo(false); @@ -845,7 +871,8 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) { + private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info, + boolean recoverable) { AppExitInfoContainer container = mData.get(packageName, uid); if (container == null) { container = new AppExitInfoContainer(mAppExitInfoHistoryListSize); @@ -859,7 +886,11 @@ public final class AppExitInfoTracker { } mData.put(packageName, uid, container); } - container.addExitInfoLocked(info); + if (recoverable) { + container.addRecoverableCrashLocked(info); + } else { + container.addExitInfoLocked(info); + } } @GuardedBy("mLock") @@ -1284,38 +1315,40 @@ public final class AppExitInfoTracker { * A container class of {@link android.app.ApplicationExitInfo} */ final class AppExitInfoContainer { - private SparseArray<ApplicationExitInfo> mInfos; // index is pid + private SparseArray<ApplicationExitInfo> mInfos; // index is a pid + private SparseArray<ApplicationExitInfo> mRecoverableCrashes; // index is a pid private int mMaxCapacity; private int mUid; // Application uid, not isolated uid. AppExitInfoContainer(final int maxCapacity) { mInfos = new SparseArray<ApplicationExitInfo>(); + mRecoverableCrashes = new SparseArray<ApplicationExitInfo>(); mMaxCapacity = maxCapacity; } @GuardedBy("mLock") - void getExitInfoLocked(final int filterPid, final int maxNum, - ArrayList<ApplicationExitInfo> results) { + void getInfosLocked(SparseArray<ApplicationExitInfo> map, final int filterPid, + final int maxNum, ArrayList<ApplicationExitInfo> results) { if (filterPid > 0) { - ApplicationExitInfo r = mInfos.get(filterPid); + ApplicationExitInfo r = map.get(filterPid); if (r != null) { results.add(r); } } else { - final int numRep = mInfos.size(); + final int numRep = map.size(); if (maxNum <= 0 || numRep <= maxNum) { // Return all records. for (int i = 0; i < numRep; i++) { - results.add(mInfos.valueAt(i)); + results.add(map.valueAt(i)); } Collections.sort(results, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); } else { if (maxNum == 1) { // Most of the caller might be only interested with the most recent one - ApplicationExitInfo r = mInfos.valueAt(0); + ApplicationExitInfo r = map.valueAt(0); for (int i = 1; i < numRep; i++) { - ApplicationExitInfo t = mInfos.valueAt(i); + ApplicationExitInfo t = map.valueAt(i); if (r.getTimestamp() < t.getTimestamp()) { r = t; } @@ -1326,7 +1359,7 @@ public final class AppExitInfoTracker { ArrayList<ApplicationExitInfo> list = mTmpInfoList2; list.clear(); for (int i = 0; i < numRep; i++) { - list.add(mInfos.valueAt(i)); + list.add(map.valueAt(i)); } Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); @@ -1340,24 +1373,30 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - void addExitInfoLocked(ApplicationExitInfo info) { + void getExitInfoLocked(final int filterPid, final int maxNum, + ArrayList<ApplicationExitInfo> results) { + getInfosLocked(mInfos, filterPid, maxNum, results); + } + + @GuardedBy("mLock") + void addInfoLocked(SparseArray<ApplicationExitInfo> map, ApplicationExitInfo info) { int size; - if ((size = mInfos.size()) >= mMaxCapacity) { + if ((size = map.size()) >= mMaxCapacity) { int oldestIndex = -1; long oldestTimeStamp = Long.MAX_VALUE; for (int i = 0; i < size; i++) { - ApplicationExitInfo r = mInfos.valueAt(i); + ApplicationExitInfo r = map.valueAt(i); if (r.getTimestamp() < oldestTimeStamp) { oldestTimeStamp = r.getTimestamp(); oldestIndex = i; } } if (oldestIndex >= 0) { - final File traceFile = mInfos.valueAt(oldestIndex).getTraceFile(); + final File traceFile = map.valueAt(oldestIndex).getTraceFile(); if (traceFile != null) { traceFile.delete(); } - mInfos.removeAt(oldestIndex); + map.removeAt(oldestIndex); } } // Claim the state information if there is any @@ -1367,7 +1406,17 @@ public final class AppExitInfoTracker { mActiveAppStateSummary, uid, pid)); info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid)); info.setAppTraceRetriever(mAppTraceRetriever); - mInfos.append(pid, info); + map.append(pid, info); + } + + @GuardedBy("mLock") + void addExitInfoLocked(ApplicationExitInfo info) { + addInfoLocked(mInfos, info); + } + + @GuardedBy("mLock") + void addRecoverableCrashLocked(ApplicationExitInfo info) { + addInfoLocked(mRecoverableCrashes, info); } @GuardedBy("mLock") @@ -1382,9 +1431,9 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - void destroyLocked() { - for (int i = mInfos.size() - 1; i >= 0; i--) { - ApplicationExitInfo ai = mInfos.valueAt(i); + void destroyLocked(SparseArray<ApplicationExitInfo> map) { + for (int i = map.size() - 1; i >= 0; i--) { + ApplicationExitInfo ai = map.valueAt(i); final File traceFile = ai.getTraceFile(); if (traceFile != null) { traceFile.delete(); @@ -1395,24 +1444,37 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") + void destroyLocked() { + destroyLocked(mInfos); + destroyLocked(mRecoverableCrashes); + } + + @GuardedBy("mLock") void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) { - if (callback != null) { - for (int i = mInfos.size() - 1; i >= 0; i--) { - switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) { - case FOREACH_ACTION_REMOVE_ITEM: - final File traceFile = mInfos.valueAt(i).getTraceFile(); - if (traceFile != null) { - traceFile.delete(); - } - mInfos.removeAt(i); - break; - case FOREACH_ACTION_STOP_ITERATION: - i = 0; - break; - case FOREACH_ACTION_NONE: - default: - break; - } + if (callback == null) return; + for (int i = mInfos.size() - 1; i >= 0; i--) { + switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) { + case FOREACH_ACTION_STOP_ITERATION: return; + case FOREACH_ACTION_REMOVE_ITEM: + final File traceFile = mInfos.valueAt(i).getTraceFile(); + if (traceFile != null) { + traceFile.delete(); + } + mInfos.removeAt(i); + break; + } + } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + switch (callback.apply( + mRecoverableCrashes.keyAt(i), mRecoverableCrashes.valueAt(i))) { + case FOREACH_ACTION_STOP_ITERATION: return; + case FOREACH_ACTION_REMOVE_ITEM: + final File traceFile = mRecoverableCrashes.valueAt(i).getTraceFile(); + if (traceFile != null) { + traceFile.delete(); + } + mRecoverableCrashes.removeAt(i); + break; } } } @@ -1423,6 +1485,9 @@ public final class AppExitInfoTracker { for (int i = mInfos.size() - 1; i >= 0; i--) { list.add(mInfos.valueAt(i)); } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + list.add(mRecoverableCrashes.valueAt(i)); + } Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); int size = list.size(); for (int i = 0; i < size; i++) { @@ -1434,10 +1499,13 @@ public final class AppExitInfoTracker { void writeToProto(ProtoOutputStream proto, long fieldId) { long token = proto.start(fieldId); proto.write(AppsExitInfoProto.Package.User.UID, mUid); - int size = mInfos.size(); - for (int i = 0; i < size; i++) { + for (int i = 0; i < mInfos.size(); i++) { mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); } + for (int i = 0; i < mRecoverableCrashes.size(); i++) { + mRecoverableCrashes.valueAt(i).writeToProto( + proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH); + } proto.end(token); } @@ -1448,14 +1516,23 @@ public final class AppExitInfoTracker { next != ProtoInputStream.NO_MORE_FIELDS; next = proto.nextField()) { switch (next) { - case (int) AppsExitInfoProto.Package.User.UID: + case (int) AppsExitInfoProto.Package.User.UID: { mUid = proto.readInt(AppsExitInfoProto.Package.User.UID); break; - case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: + } + case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: { ApplicationExitInfo info = new ApplicationExitInfo(); info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); mInfos.put(info.getPid(), info); break; + } + case (int) AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH: { + ApplicationExitInfo info = new ApplicationExitInfo(); + info.readFromProto( + proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH); + mRecoverableCrashes.put(info.getPid(), info); + break; + } } } proto.end(token); @@ -1472,6 +1549,11 @@ public final class AppExitInfoTracker { list.add(mInfos.valueAt(i)); } } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + if (filterPid == 0 || filterPid == mRecoverableCrashes.keyAt(i)) { + list.add(mRecoverableCrashes.valueAt(i)); + } + } return list; } } @@ -1610,6 +1692,7 @@ public final class AppExitInfoTracker { static final int MSG_PROC_DIED = 4103; static final int MSG_APP_KILL = 4104; static final int MSG_STATSD_LOG = 4105; + static final int MSG_APP_RECOVERABLE_CRASH = 4106; KillHandler(Looper looper) { super(looper, null, true); @@ -1648,6 +1731,14 @@ public final class AppExitInfoTracker { } } break; + case MSG_APP_RECOVERABLE_CRASH: { + ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj; + synchronized (mLock) { + handleNoteAppRecoverableCrashLocked(raw); + } + recycleRawRecord(raw); + } + break; default: super.handleMessage(msg); } diff --git a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java index ff78355121d5..62680823588d 100644 --- a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java +++ b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java @@ -338,7 +338,7 @@ abstract class BaseAppStateTimeSlotEventsTracker pw.print(prefix); pw.print(mKeyNumOfEventsThreshold); pw.print('='); - pw.println(mDefaultNumOfEventsThreshold); + pw.println(mNumOfEventsThreshold); } pw.print(prefix); pw.print("event_time_slot_size="); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 702526a4beab..1a0d291d375c 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -399,7 +399,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } } - public void shutdown() { + public synchronized void shutdown() { mExecutorService.shutdownNow(); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 256df98ae760..d0607d567900 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -105,6 +105,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManagerInternal; import android.system.Os; +import android.system.OsConstants; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -2328,9 +2329,15 @@ public final class ProcessList { if (!regularZygote) { // webview and app zygote don't have the permission to create the nodes - if (Process.createProcessGroup(uid, startResult.pid) < 0) { - throw new AssertionError("Unable to create process group for " + app.processName - + " (" + startResult.pid + ")"); + final int res = Process.createProcessGroup(uid, startResult.pid); + if (res < 0) { + if (res == -OsConstants.ESRCH) { + Slog.e(ActivityManagerService.TAG, "Unable to create process group for " + + app.processName + " (" + startResult.pid + ")"); + } else { + throw new AssertionError("Unable to create process group for " + + app.processName + " (" + startResult.pid + ")"); + } } } @@ -5086,6 +5093,17 @@ public final class ProcessList { } /** + * Called by ActivityManagerService when a recoverable native crash occurs. + */ + @GuardedBy("mService") + void noteAppRecoverableCrash(final ProcessRecord app) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "note: " + app + " has a recoverable native crash"); + } + mAppExitInfoTracker.scheduleNoteAppRecoverableCrash(app); + } + + /** * Called by ActivityManagerService when it decides to kill an application process. */ @GuardedBy("mService") diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 8886f0a06a52..b8ff26ea3cc9 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -98,7 +98,6 @@ public class SettingsToPropertiesMapper { DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, DeviceConfig.NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT, DeviceConfig.NAMESPACE_SWCODEC_NATIVE, - DeviceConfig.NAMESPACE_TETHERING, DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE, DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT, DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE, diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS index cd281e06f40d..1bf2aeffdf0c 100644 --- a/services/core/java/com/android/server/biometrics/OWNERS +++ b/services/core/java/com/android/server/biometrics/OWNERS @@ -6,6 +6,10 @@ jaggies@google.com jbolinger@google.com jeffpu@google.com joshmccloskey@google.com +diyab@google.com +austindelgado@google.com +spdonghao@google.com +wenhuiy@google.com firewall@google.com jasonsfchang@google.com diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 598e2b990ea5..94b67cedf86c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -452,6 +452,13 @@ public class FingerprintService extends SystemService { return -1; } + if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { + // If this happens, something in KeyguardUpdateMonitor is wrong. This should only + // ever be invoked when the user is encrypted or lockdown. + Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown"); + return -1; + } + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFingerprint"); diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 1f82961efd22..6d4306198aa2 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -41,6 +41,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.RingBuffer; @@ -278,6 +279,11 @@ public class NetdEventListenerService extends BaseNetdEventListener { } } + private boolean hasWifiTransport(Network network) { + final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); + return nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI); + } + @Override public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader, byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) { @@ -286,12 +292,21 @@ public class NetdEventListenerService extends BaseNetdEventListener { throw new IllegalArgumentException("Prefix " + prefix + " required in format <nethandle>:<interface>"); } + final long netHandle = Long.parseLong(prefixParts[0]); + final Network network = Network.fromNetworkHandle(netHandle); final WakeupEvent event = new WakeupEvent(); event.iface = prefixParts[1]; event.uid = uid; event.ethertype = ethertype; - event.dstHwAddr = MacAddress.fromBytes(dstHw); + if (ArrayUtils.isEmpty(dstHw)) { + if (hasWifiTransport(network)) { + Log.e(TAG, "Empty mac address on WiFi transport, network: " + network); + } + event.dstHwAddr = null; + } else { + event.dstHwAddr = MacAddress.fromBytes(dstHw); + } event.srcIp = srcIp; event.dstIp = dstIp; event.ipNextHeader = ipNextHeader; @@ -306,14 +321,12 @@ public class NetdEventListenerService extends BaseNetdEventListener { final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class); if (bsi != null) { - final long netHandle = Long.parseLong(prefixParts[0]); final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs - System.currentTimeMillis(); - bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs, - event.uid); + bsi.noteCpuWakingNetworkPacket(network, elapsedMs, event.uid); } - final String dstMac = event.dstHwAddr.toString(); + final String dstMac = String.valueOf(event.dstHwAddr); FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED, uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index b25206d3b621..4208a12f91d4 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -85,6 +85,7 @@ import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.RouteInfo; import android.net.TelephonyNetworkSpecifier; +import android.net.TransportInfo; import android.net.UidRangeParcel; import android.net.UnderlyingNetworkInfo; import android.net.Uri; @@ -107,6 +108,8 @@ import android.net.ipsec.ike.exceptions.IkeNetworkLostException; import android.net.ipsec.ike.exceptions.IkeNonProtocolException; import android.net.ipsec.ike.exceptions.IkeProtocolException; import android.net.ipsec.ike.exceptions.IkeTimeoutException; +import android.net.vcn.VcnGatewayConnectionConfig; +import android.net.vcn.VcnTransportInfo; import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; @@ -152,6 +155,7 @@ import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.BinderUtils; +import com.android.net.module.util.LinkPropertiesUtils; import com.android.net.module.util.NetdUtils; import com.android.net.module.util.NetworkStackConstants; import com.android.server.DeviceIdleInternal; @@ -230,7 +234,35 @@ public class Vpn { * <p>If retries have exceeded the length of this array, the last entry in the array will be * used as a repeating interval. */ - private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L}; + private static final long[] IKEV2_VPN_RETRY_DELAYS_MS = + {1_000L, 2_000L, 5_000L, 30_000L, 60_000L, 300_000L, 900_000L}; + + /** + * A constant to pass to {@link IkeV2VpnRunner#scheduleStartIkeSession(long)} to mean the + * delay should be computed automatically with backoff. + */ + private static final long RETRY_DELAY_AUTO_BACKOFF = -1; + + /** + * How long to wait before trying to migrate the IKE connection when NetworkCapabilities or + * LinkProperties change in a way that may require migration. + * + * This delay is useful to avoid multiple migration tries (e.g. when a network changes + * both its NC and LP at the same time, e.g. when it first connects) and to minimize the + * cases where an old list of addresses is detected for the network. + * + * In practice, the IKE library reads the LinkProperties of the passed network with + * the synchronous {@link ConnectivityManager#getLinkProperties(Network)}, which means in + * most cases the race would resolve correctly, but this delay increases the chance that + * it correctly is. + * Further, using the synchronous method in the IKE library is actually dangerous because + * it is racy (it races with {@code IkeNetworkCallbackBase#onLost} and it should be fixed + * by using callbacks instead. When that happens, the race within IKE is fixed but the + * race between that callback and the one in IkeV2VpnRunner becomes a much bigger problem, + * and this delay will be necessary to ensure the correct link address list is used. + */ + private static final long IKE_DELAY_ON_NC_LP_CHANGE_MS = 300; + /** * Largest profile size allowable for Platform VPNs. * @@ -424,22 +456,22 @@ public class Vpn { private static class CarrierConfigInfo { public final String mccMnc; - public final int keepaliveDelayMs; + public final int keepaliveDelaySec; public final int encapType; public final int ipVersion; - CarrierConfigInfo(String mccMnc, int keepaliveDelayMs, + CarrierConfigInfo(String mccMnc, int keepaliveDelaySec, int encapType, int ipVersion) { this.mccMnc = mccMnc; - this.keepaliveDelayMs = keepaliveDelayMs; + this.keepaliveDelaySec = keepaliveDelaySec; this.encapType = encapType; this.ipVersion = ipVersion; } @Override public String toString() { - return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelayMs=" + keepaliveDelayMs + return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelaySec=" + keepaliveDelaySec + ", encapType=" + encapType + ", ipVersion=" + ipVersion + "]"; } } @@ -619,14 +651,14 @@ public class Vpn { /** * Retrieves the next retry delay * - * <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in + * <p>If retries have exceeded the size of IKEV2_VPN_RETRY_DELAYS_MS, the last entry in * the array will be used as a repeating interval. */ - public long getNextRetryDelaySeconds(int retryCount) { - if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) { - return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1]; + public long getNextRetryDelayMs(int retryCount) { + if (retryCount >= IKEV2_VPN_RETRY_DELAYS_MS.length) { + return IKEV2_VPN_RETRY_DELAYS_MS[IKEV2_VPN_RETRY_DELAYS_MS.length - 1]; } else { - return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount]; + return IKEV2_VPN_RETRY_DELAYS_MS[retryCount]; } } @@ -679,6 +711,14 @@ public class Vpn { boolean isIpv4) { return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4); } + + /** Verify the binder calling UID is the one passed in arguments */ + public void verifyCallingUidAndPackage(Context context, String packageName, int userId) { + final int callingUid = Binder.getCallingUid(); + if (getAppUid(context, packageName, userId) != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } } @VisibleForTesting @@ -726,7 +766,7 @@ public class Vpn { mUserManager = mContext.getSystemService(UserManager.class); mPackage = VpnConfig.LEGACY_VPN; - mOwnerUID = getAppUid(mPackage, mUserId); + mOwnerUID = getAppUid(mContext, mPackage, mUserId); mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage); try { @@ -823,7 +863,7 @@ public class Vpn { } /** - * Chooses whether to force all connections to go though VPN. + * Chooses whether to force all connections to go through VPN. * * Used to enable/disable legacy VPN lockdown. * @@ -831,7 +871,7 @@ public class Vpn { * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling * that function will be replaced and saved with the always-on state. * - * @param lockdown whether to prevent all traffic outside of a VPN. + * @param lockdown whether to prevent all traffic outside of the VPN. */ public synchronized void setLockdown(boolean lockdown) { enforceControlPermissionOrInternalCaller(); @@ -969,15 +1009,21 @@ public class Vpn { // Allow VpnManager app to temporarily run background services to handle this error. // If an app requires anything beyond this grace period, they MUST either declare // themselves as a foreground service, or schedule a job/workitem. - DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); - idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, - VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, - "VpnManager event"); + final long token = Binder.clearCallingIdentity(); try { - return mUserIdContext.startService(intent) != null; - } catch (RuntimeException e) { - Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e); - return false; + final DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); + idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, + VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, + "VpnManager event"); + + try { + return mUserIdContext.startService(intent) != null; + } catch (RuntimeException e) { + Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e); + return false; + } + } finally { + Binder.restoreCallingIdentity(token); } } @@ -1102,6 +1148,7 @@ public class Vpn { mAlwaysOn = false; } + final boolean oldLockdownState = mLockdown; mLockdown = (mAlwaysOn && lockdown); mLockdownAllowlist = (mLockdown && lockdownAllowlist != null) ? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist)) @@ -1112,6 +1159,13 @@ public class Vpn { if (isCurrentPreparedPackage(packageName)) { updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); setVpnForcedLocked(mLockdown); + + // Lockdown forces the VPN to be non-bypassable (see #agentConnect) because it makes + // no sense for a VPN to be bypassable when connected but not when not connected. + // As such, changes in lockdown need to restart the agent. + if (mNetworkAgent != null && oldLockdownState != mLockdown) { + startNewNetworkAgent(mNetworkAgent, "Lockdown mode changed"); + } } else { // Prepare this app. The notification will update as a side-effect of updateState(). // It also calls setVpnForcedLocked(). @@ -1349,7 +1403,8 @@ public class Vpn { // We can't just check that packageName matches mPackage, because if the app was uninstalled // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the // calling package may not be the same as the prepared package. Check both UID and package. - return getAppUid(packageName, mUserId) == mOwnerUID && mPackage.equals(packageName); + return getAppUid(mContext, packageName, mUserId) == mOwnerUID + && mPackage.equals(packageName); } /** Prepare the VPN for the given package. Does not perform permission checks. */ @@ -1390,7 +1445,7 @@ public class Vpn { Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); mPackage = newPackage; - mOwnerUID = getAppUid(newPackage, mUserId); + mOwnerUID = getAppUid(mContext, newPackage, mUserId); mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); try { mNms.allowProtect(mOwnerUID); @@ -1411,7 +1466,7 @@ public class Vpn { // Check if the caller is authorized. enforceControlPermissionOrInternalCaller(); - final int uid = getAppUid(packageName, mUserId); + final int uid = getAppUid(mContext, packageName, mUserId); if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { // Authorization for nonexistent packages (or fake ones) can't be updated. return false; @@ -1491,11 +1546,11 @@ public class Vpn { || isVpnServicePreConsented(context, packageName); } - private int getAppUid(final String app, final int userId) { + private static int getAppUid(final Context context, final String app, final int userId) { if (VpnConfig.LEGACY_VPN.equals(app)) { return Process.myUid(); } - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = context.getPackageManager(); final long token = Binder.clearCallingIdentity(); try { return pm.getPackageUidAsUser(app, userId); @@ -1624,6 +1679,10 @@ public class Vpn { */ private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { // NetworkAgentConfig cannot be updated without registering a new NetworkAgent. + // Strictly speaking, bypassability is affected by lockdown and therefore it's possible + // it doesn't actually change even if mConfig.allowBypass changed. It might be theoretically + // possible to do handover in this case, but this is far from obvious to VPN authors and + // it's simpler if the rule is just "can't update in place if you change allow bypass". if (oldConfig.allowBypass != mConfig.allowBypass) { Log.i(TAG, "Handover not possible due to changes to allowBypass"); return false; @@ -1665,10 +1724,11 @@ public class Vpn { mLegacyState = LegacyVpnInfo.STATE_CONNECTING; updateState(DetailedState.CONNECTING, "agentConnect"); + final boolean bypassable = mConfig.allowBypass && !mLockdown; final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder() .setLegacyType(ConnectivityManager.TYPE_VPN) .setLegacyTypeName("VPN") - .setBypassableVpn(mConfig.allowBypass && !mLockdown) + .setBypassableVpn(bypassable) .setVpnRequiresValidation(mConfig.requiresInternetValidation) .setLocalRoutesExcludedForVpn(mConfig.excludeLocalRoutes) .build(); @@ -1682,7 +1742,7 @@ public class Vpn { capsBuilder.setTransportInfo(new VpnTransportInfo( getActiveVpnType(), mConfig.session, - mConfig.allowBypass, + bypassable, expensive)); // Only apps targeting Q and above can explicitly declare themselves as metered. @@ -1713,6 +1773,10 @@ public class Vpn { Binder.restoreCallingIdentity(token); } updateState(DetailedState.CONNECTED, "agentConnect"); + if (isIkev2VpnRunner()) { + final IkeSessionWrapper session = ((IkeV2VpnRunner) mVpnRunner).mSession; + if (null != session) session.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); + } } private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) { @@ -1907,7 +1971,7 @@ public class Vpn { private SortedSet<Integer> getAppsUids(List<String> packageNames, int userId) { SortedSet<Integer> uids = new TreeSet<>(); for (String app : packageNames) { - int uid = getAppUid(app, userId); + int uid = getAppUid(mContext, app, userId); if (uid != -1) uids.add(uid); // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from // ConnectivityServiceTest. @@ -3226,7 +3290,6 @@ public class Vpn { prepareStatusIntent(); } agentConnect(this::onValidationStatus); - mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); return; // Link properties are already sent. } else { // Underlying networks also set in agentConnect() @@ -3343,7 +3406,6 @@ public class Vpn { if (!removedAddrs.isEmpty()) { startNewNetworkAgent( mNetworkAgent, "MTU too low for IPv6; restarting network agent"); - mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); for (LinkAddress removed : removedAddrs) { mTunnelIface.removeAddress( @@ -3391,6 +3453,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onDefaultNetworkChanged(@NonNull Network network) { + mEventChanges.log("[UnderlyingNW] Default network changed to " + network); Log.d(TAG, "onDefaultNetworkChanged: " + network); // If there is a new default network brought up, cancel the retry task to prevent @@ -3496,39 +3559,63 @@ public class Vpn { } private int guessEspIpVersionForNetwork() { - final CarrierConfigInfo carrierconfig = getCarrierConfig(); + if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) { + Log.d(TAG, "Running over VCN, esp IP version is auto"); + return ESP_IP_VERSION_AUTO; + } + final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); final int ipVersion = (carrierconfig != null) ? carrierconfig.ipVersion : ESP_IP_VERSION_AUTO; if (carrierconfig != null) { - Log.d(TAG, "Get customized IP version(" + ipVersion + ") on SIM(" + Log.d(TAG, "Get customized IP version (" + ipVersion + ") on SIM (mccmnc=" + carrierconfig.mccMnc + ")"); } return ipVersion; } private int guessEspEncapTypeForNetwork() { - final CarrierConfigInfo carrierconfig = getCarrierConfig(); + if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) { + Log.d(TAG, "Running over VCN, encap type is auto"); + return ESP_ENCAP_TYPE_AUTO; + } + final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); final int encapType = (carrierconfig != null) ? carrierconfig.encapType : ESP_ENCAP_TYPE_AUTO; if (carrierconfig != null) { - Log.d(TAG, "Get customized encap type(" + encapType + ") on SIM(" + Log.d(TAG, "Get customized encap type (" + encapType + ") on SIM (mccmnc=" + carrierconfig.mccMnc + ")"); } return encapType; } + private int guessNattKeepaliveTimerForNetwork() { - final CarrierConfigInfo carrierconfig = getCarrierConfig(); - final int natKeepalive = (carrierconfig != null) - ? carrierconfig.keepaliveDelayMs : AUTOMATIC_KEEPALIVE_DELAY_SECONDS; + final TransportInfo transportInfo = mUnderlyingNetworkCapabilities.getTransportInfo(); + if (transportInfo instanceof VcnTransportInfo) { + final int nattKeepaliveSec = + ((VcnTransportInfo) transportInfo).getMinUdpPort4500NatTimeoutSeconds(); + Log.d(TAG, "Running over VCN, keepalive timer : " + nattKeepaliveSec + "s"); + if (VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET + != nattKeepaliveSec) { + return nattKeepaliveSec; + } + // else fall back to carrier config, if any + } + final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); + final int nattKeepaliveSec = (carrierconfig != null) + ? carrierconfig.keepaliveDelaySec : AUTOMATIC_KEEPALIVE_DELAY_SECONDS; if (carrierconfig != null) { - Log.d(TAG, "Get customized keepalive(" + natKeepalive + ") on SIM(" + Log.d(TAG, "Get customized keepalive (" + nattKeepaliveSec + "s) on SIM (mccmnc=" + carrierconfig.mccMnc + ")"); } - return natKeepalive; + return nattKeepaliveSec; } - private CarrierConfigInfo getCarrierConfig() { + /** + * Returns the carrier config for the underlying network, or null if not a cell network. + */ + @Nullable + private CarrierConfigInfo getCarrierConfigForUnderlyingNetwork() { final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { Log.d(TAG, "Underlying network is not a cellular network"); @@ -3590,8 +3677,11 @@ public class Vpn { encapType = IkeSessionParams.ESP_ENCAP_TYPE_NONE; break; default: - ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO; - encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO; + // By default, PREFERRED_IKE_PROTOCOL_IPV4_UDP is used for safety. This is + // because some carriers' networks do not support IPv6 very well, and using + // IPv4 can help to prevent problems. + ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; break; } return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion); @@ -3621,13 +3711,14 @@ public class Vpn { final VpnTransportInfo info = new VpnTransportInfo( getActiveVpnType(), mConfig.session, - mConfig.allowBypass, + mConfig.allowBypass && !mLockdown, areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo()); if (ncUpdateRequired) { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) .setTransportInfo(info) .build(); + mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities); doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); } } @@ -3664,6 +3755,7 @@ public class Vpn { private void startIkeSession(@NonNull Network underlyingNetwork) { Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); + mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork); try { // Clear mInterface to prevent Ikev2VpnRunner being cleared when @@ -3709,13 +3801,20 @@ public class Vpn { } } - private void scheduleRetryNewIkeSession() { + /** + * Schedule starting an IKE session. + * @param delayMs the delay after which to try starting the session. This should be + * RETRY_DELAY_AUTO_BACKOFF for automatic retries with backoff. + */ + private void scheduleStartIkeSession(final long delayMs) { if (mScheduledHandleRetryIkeSessionFuture != null) { Log.d(TAG, "There is a pending retrying task, skip the new retrying task"); return; } - final long retryDelay = mDeps.getNextRetryDelaySeconds(mRetryCount++); - Log.d(TAG, "Retry new IKE session after " + retryDelay + " seconds."); + final long retryDelayMs = RETRY_DELAY_AUTO_BACKOFF != delayMs + ? delayMs + : mDeps.getNextRetryDelayMs(mRetryCount++); + Log.d(TAG, "Retry new IKE session after " + retryDelayMs + " milliseconds."); // If the default network is lost during the retry delay, the mActiveNetwork will be // null, and the new IKE session won't be established until there is a new default // network bringing up. @@ -3726,7 +3825,7 @@ public class Vpn { // Reset mScheduledHandleRetryIkeSessionFuture since it's already run on // executor thread. mScheduledHandleRetryIkeSessionFuture = null; - }, retryDelay, TimeUnit.SECONDS); + }, retryDelayMs, TimeUnit.MILLISECONDS); } /** Called when the NetworkCapabilities of underlying network is changed */ @@ -3735,20 +3834,26 @@ public class Vpn { + mUnderlyingNetworkCapabilities + " to " + nc); final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities; mUnderlyingNetworkCapabilities = nc; - if (oldNc == null) { - // A new default network is available. - startOrMigrateIkeSession(mActiveNetwork); - } else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { - // Renew carrierConfig values. - maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); + if (oldNc == null || !nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { + // A new default network is available, or the subscription has changed. + // Try to migrate the session, or failing that, start a new one. + scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); } } /** Called when the LinkProperties of underlying network is changed */ public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) { - mEventChanges.log("[UnderlyingNW] Lp changed from " - + mUnderlyingLinkProperties + " to " + lp); + final LinkProperties oldLp = mUnderlyingLinkProperties; + mEventChanges.log("[UnderlyingNW] Lp changed from " + oldLp + " to " + lp); mUnderlyingLinkProperties = lp; + if (oldLp == null || !LinkPropertiesUtils.isIdenticalAllLinkAddresses(oldLp, lp)) { + // If some of the link addresses changed, the IKE session may need to be migrated + // or restarted, for example if the available IP families have changed or if the + // source address used has gone away. See IkeConnectionController#onNetworkSetByUser + // and IkeConnectionController#selectAndSetRemoteAddress for where this ends up + // re-evaluating the session. + scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); + } } class VpnConnectivityDiagnosticsCallback @@ -3778,6 +3883,7 @@ public class Vpn { } public void onValidationStatus(int status) { + mEventChanges.log("[Validation] validation status " + status); if (status == NetworkAgent.VALIDATION_STATUS_VALID) { // No data stall now. Reset it. mExecutor.execute(() -> { @@ -3818,6 +3924,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onDefaultNetworkLost(@NonNull Network network) { + mEventChanges.log("[UnderlyingNW] Network lost " + network); // If the default network is torn down, there is no need to call // startOrMigrateIkeSession() since it will always check if there is an active network // can be used or not. @@ -3936,6 +4043,8 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onSessionLost(int token, @Nullable Exception exception) { + mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork + + (null == exception ? "" : " reason " + exception.getMessage())); Log.d(TAG, "onSessionLost() called for token " + token); if (!isActiveToken(token)) { @@ -4022,7 +4131,7 @@ public class Vpn { markFailedAndDisconnect(exception); return; } else { - scheduleRetryNewIkeSession(); + scheduleStartIkeSession(RETRY_DELAY_AUTO_BACKOFF); } // Close all obsolete state, but keep VPN alive incase a usable network comes up. @@ -4092,6 +4201,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ private void disconnectVpnRunner() { + mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork); mActiveNetwork = null; mUnderlyingNetworkCapabilities = null; mUnderlyingLinkProperties = null; @@ -4458,10 +4568,7 @@ public class Vpn { } private void verifyCallingUidAndPackage(String packageName) { - final int callingUid = Binder.getCallingUid(); - if (getAppUid(packageName, mUserId) != callingUid) { - throw new SecurityException(packageName + " does not belong to uid " + callingUid); - } + mDeps.verifyCallingUidAndPackage(mContext, packageName, mUserId); } @VisibleForTesting diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 54189bf7925e..237485bca1f9 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1670,9 +1670,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be // done in HighBrightnessModeController. if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR - && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0 - && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0) { - // We want to scale HDR brightness level with the SDR level + && (mBrightnessReasonTemp.modifier & BrightnessReason.MODIFIER_DIMMED) == 0 + && (mBrightnessReasonTemp.modifier & BrightnessReason.MODIFIER_LOW_POWER) + == 0) { + // We want to scale HDR brightness level with the SDR level, we also need to restore + // SDR brightness immediately when entering dim or low power mode. animateValue = mHbmController.getHdrBrightnessValue(); } diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 73131a1dc220..06dd5006188a 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -300,8 +300,11 @@ final class PersistentDataStore { } public boolean setBrightness(DisplayDevice displayDevice, float brightness) { + if (displayDevice == null || !displayDevice.hasStableUniqueId()) { + return false; + } final String displayDeviceUniqueId = displayDevice.getUniqueId(); - if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) { + if (displayDeviceUniqueId == null) { return false; } final DisplayState state = getDisplayState(displayDeviceUniqueId, true); diff --git a/services/core/java/com/android/server/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS index 0466d8a88053..4fea05d295b6 100644 --- a/services/core/java/com/android/server/infra/OWNERS +++ b/services/core/java/com/android/server/infra/OWNERS @@ -1,3 +1,3 @@ # Bug component: 655446 -include /core/java/android/service/cloudsearch/OWNERS +srazdan@google.com diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS index 00cd700541c0..6e5eb5631112 100644 --- a/services/core/java/com/android/server/inputmethod/OWNERS +++ b/services/core/java/com/android/server/inputmethod/OWNERS @@ -1,8 +1,8 @@ set noparent -ogunwale@google.com +roosa@google.com yukawa@google.com tarandeep@google.com -lumark@google.com -roosa@google.com -wilsonwu@google.com + +ogunwale@google.com #{LAST_RESORT_SUGGESTION} +jjaggi@google.com #{LAST_RESORT_SUGGESTION} diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 1235352b0590..f0aff2a503b0 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -300,6 +300,7 @@ public class LocationProviderManager extends public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException { BroadcastOptions options = BroadcastOptions.makeBasic(); options.setDontSendToRestrictedApps(true); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode), null, null, null, options.toBundle()); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index dcf19062834c..d2853370fa69 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -220,6 +220,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.SubscriptionPlan; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.text.format.DateUtils; @@ -801,6 +802,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } return buckets; } + + /** Require IPC call. Don't call when holding a lock. */ + int getDefaultDataSubId() { + return SubscriptionManager.getDefaultDataSubscriptionId(); + } + + /** Require IPC call. Don't call when holding a lock. */ + int getActivateDataSubId() { + return SubscriptionManager.getActiveDataSubscriptionId(); + } } @VisibleForTesting @@ -828,7 +839,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mSuppressDefaultPolicy = suppressDefaultPolicy; mDeps = Objects.requireNonNull(deps, "missing Dependencies"); - + mActiveDataSubIdListener = new ActiveDataSubIdListener(); mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy"); mAppOps = context.getSystemService(AppOpsManager.class); @@ -1088,6 +1099,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }); + // Listen for active data sub Id change, upon which data notifications is shown/hidden. + mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor, + mActiveDataSubIdListener); + // tell systemReady() that the service has been initialized initCompleteSignal.countDown(); } finally { @@ -1257,6 +1272,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** + * Listener that watches for active data sub Id change, upon which data notifications are + * shown/hidden. + */ + private final ActiveDataSubIdListener mActiveDataSubIdListener; + private class ActiveDataSubIdListener extends TelephonyCallback implements + TelephonyCallback.ActiveDataSubscriptionIdListener { + /** + * In most cases active data sub is the same as the default data sub, but if user enabled + * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH}, + * active data sub could be the non-default data sub. + * + * If the listener is initialized before the phone process is up, the IPC call to the + * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned, + * indicating the phone process is unable to determine a valid data sub Id at this point, in + * which case no data notifications should be shown anyway. Later on when an active data + * sub is known, notifications will be re-evaluated by this callback. + */ + private int mDefaultDataSubId = mDeps.getDefaultDataSubId(); + private int mActiveDataSubId = mDeps.getActivateDataSubId(); + // Only listen to active data sub change is sufficient because default data sub change + // leads to active data sub change as well. + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mActiveDataSubId = subId; + mDefaultDataSubId = mDeps.getDefaultDataSubId(); + synchronized (mNetworkPoliciesSecondLock) { + updateNotificationsNL(); + } + } + } + + /** * Listener that watches for {@link NetworkStatsManager} updates, which * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}. */ @@ -1445,6 +1492,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // ignore policies that aren't relevant to user if (subId == INVALID_SUBSCRIPTION_ID) continue; + // ignore if the data sub is neither default nor active for data at the moment. + if (subId != mActiveDataSubIdListener.mDefaultDataSubId + && subId != mActiveDataSubIdListener.mActiveDataSubId) continue; if (!policy.hasCycle()) continue; final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 65bd3f12a61a..0f13c2ca8bd8 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -108,7 +108,7 @@ public class PreferencesHelper implements RankingConfig { @VisibleForTesting static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000; @VisibleForTesting - static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 50000; + static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000; private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000; private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000; diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java index ffe0ca003817..b00cc1acee34 100644 --- a/services/core/java/com/android/server/pm/ApkChecksums.java +++ b/services/core/java/com/android/server/pm/ApkChecksums.java @@ -40,8 +40,6 @@ import android.content.pm.SigningDetails.SignatureSchemeVersion; import android.content.pm.parsing.ApkLiteParseUtils; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; -import android.os.Environment; -import android.os.FileUtils; import android.os.Handler; import android.os.RemoteException; import android.os.SystemClock; @@ -638,18 +636,9 @@ public class ApkChecksums { return null; } - private static boolean containsFile(File dir, String filePath) { - if (dir == null) { - return false; - } - return FileUtils.contains(dir.getAbsolutePath(), filePath); - } - private static ApkChecksum extractHashFromFS(String split, String filePath) { // verity first - // Skip /product folder. - // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules. - if (!containsFile(Environment.getProductDirectory(), filePath)) { + if (VerityUtils.hasFsverity(filePath)) { byte[] verityHash = VerityUtils.getFsverityDigest(filePath); if (verityHash != null) { return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, verityHash); diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 0de44bc5d6b3..3dac305cef5b 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -94,6 +94,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.ApplicationPackageManager; +import android.app.BroadcastOptions; import android.app.backup.IBackupManager; import android.content.ContentResolver; import android.content.Context; @@ -641,7 +642,10 @@ final class InstallPackageHelper { fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.installStatusToPublicStatus(returnCode)); try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */, + null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } @@ -2425,10 +2429,10 @@ final class InstallPackageHelper { // will be null whereas dataOwnerPkg will contain information about the package // which was uninstalled while keeping its data. AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName); + PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName); if (dataOwnerPkg == null) { - PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); - if (ps != null) { - dataOwnerPkg = ps.getPkg(); + if (dataOwnerPs != null) { + dataOwnerPkg = dataOwnerPs.getPkg(); } } @@ -2456,6 +2460,7 @@ final class InstallPackageHelper { if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPkg.isDebuggable())) { + // Downgrade is not permitted; a lower version of the app will not be allowed try { PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { @@ -2464,6 +2469,28 @@ final class InstallPackageHelper { return Pair.create( PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); } + } else if (dataOwnerPs.isSystem()) { + // Downgrade is permitted, but system apps can't be downgraded below + // the version preloaded onto the system image + final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr( + dataOwnerPs); + if (disabledPs != null) { + dataOwnerPkg = disabledPs.getPkg(); + } + if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) { + // Only restrict non-debuggable builds and non-debuggable version of the app + try { + PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite); + } catch (PackageManagerException e) { + String errorMsg = + "System app: " + packageName + " cannot be downgraded to" + + " older than its preloaded version on the system" + + " image. " + e.getMessage(); + Slog.w(TAG, errorMsg); + return Pair.create( + PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); + } + } } } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index bb23d89d218f..02cf4336b277 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -27,6 +27,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; import android.app.PackageDeleteObserver; @@ -1360,7 +1361,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { - mTarget.sendIntent(mContext, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (SendIntentException ignored) { } } @@ -1385,7 +1389,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements PackageManager.deleteStatusToString(returnCode, msg)); fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); try { - mTarget.sendIntent(mContext, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (SendIntentException ignored) { } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 7c2e3ea426b4..1823de8fcf66 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -54,6 +54,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.WorkerThread; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; import android.app.admin.DevicePolicyEventLogger; @@ -4274,7 +4275,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } @@ -4315,7 +4319,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } @@ -4349,7 +4356,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready"); } try { - target.sendIntent(context, 0, intent, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, intent, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8d2714cacf10..47860373156b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -53,6 +53,7 @@ import android.annotation.WorkerThread; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.ApplicationPackageManager; +import android.app.BroadcastOptions; import android.app.IActivityManager; import android.app.admin.IDevicePolicyManager; import android.app.admin.SecurityLog; @@ -4798,7 +4799,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService } if (pi != null) { try { - pi.sendIntent(null, success ? 1 : 0, null, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + pi.sendIntent(null, success ? 1 : 0, null /* intent */, + null /* onFinished*/, null /* handler */, + null /* requiredPermission */, options.toBundle()); } catch (SendIntentException e) { Slog.w(TAG, e); } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 714be185c972..be719e33dd00 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -38,7 +38,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.compat.annotation.ChangeId; -import android.compat.annotation.EnabledSince; +import android.compat.annotation.Disabled; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -155,7 +155,7 @@ public class PackageManagerServiceUtils { * allow 3P apps to trigger internal-only functionality. */ @ChangeId - @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) + @Disabled /* Revert enforcement: b/274147456 */ private static final long ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS = 161252188; /** diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 890c89152a7c..8507ad028a19 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -430,6 +430,7 @@ class ShortcutPackage extends ShortcutPackageItem { @NonNull List<ShortcutInfo> changedShortcuts) { Preconditions.checkArgument(newShortcut.isEnabled(), "pushDynamicShortcuts() cannot publish disabled shortcuts"); + ensureShortcutCountBeforePush(); newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); @@ -437,7 +438,7 @@ class ShortcutPackage extends ShortcutPackageItem { final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId()); boolean deleted = false; - if (oldShortcut == null) { + if (oldShortcut == null || !oldShortcut.isDynamic()) { final ShortcutService service = mShortcutUser.mService; final int maxShortcuts = service.getMaxActivityShortcuts(); @@ -446,18 +447,12 @@ class ShortcutPackage extends ShortcutPackageItem { final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity()); if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) { - Slog.e(TAG, "Error pushing shortcut. There are already " - + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts - + " shortcuts limit when pushing the new shortcut " + newShortcut - + ". Id of shortcuts currently available in system memory are " - + activityShortcuts.stream().map(ShortcutInfo::getId) - .collect(Collectors.joining(",", "[", "]"))); - // TODO: This should not have happened. If it does, identify the root cause where - // possible, otherwise bail-out early to prevent memory issue. + // Root cause was discovered in b/233155034, so this should not be happening. + service.wtf("Error pushing shortcut. There are already " + + activityShortcuts.size() + " shortcuts."); } if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) { // Max has reached. Delete the shortcut with lowest rank. - // Sort by isManifestShortcut() and getRank(). Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator); @@ -473,7 +468,8 @@ class ShortcutPackage extends ShortcutPackageItem { deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true, /*ignorePersistedShortcuts=*/ true) != null; } - } else { + } + if (oldShortcut != null) { // It's an update case. // Make sure the target is updatable. (i.e. should be mutable.) oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false); @@ -505,6 +501,32 @@ class ShortcutPackage extends ShortcutPackageItem { return deleted; } + private void ensureShortcutCountBeforePush() { + final ShortcutService service = mShortcutUser.mService; + // Ensure the total number of shortcuts doesn't exceed the hard limit per app. + final int maxShortcutPerApp = service.getMaxAppShortcuts(); + synchronized (mLock) { + final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si -> + !si.isPinned()).collect(Collectors.toList()); + if (appShortcuts.size() >= maxShortcutPerApp) { + // Max has reached. Removes shortcuts until they fall within the hard cap. + // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp(). + Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator); + + while (appShortcuts.size() >= maxShortcutPerApp) { + final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1); + if (shortcut.isDeclaredInManifest()) { + // All shortcuts are manifest shortcuts and cannot be removed. + throw new IllegalArgumentException(getPackageName() + " has published " + + appShortcuts.size() + " manifest shortcuts across different" + + " activities."); + } + forceDeleteShortcutInner(shortcut.getId()); + } + } + } + } + /** * Remove all shortcuts that aren't pinned, cached nor dynamic. * @@ -1367,6 +1389,61 @@ class ShortcutPackage extends ShortcutPackageItem { }; /** + * To sort by isManifestShortcut(), isDynamic(), getRank() and + * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts, + * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp. + * + * This is used to decide which shortcuts to remove when the total number of shortcuts retained + * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}. + * + * (Note the number of manifest shortcuts is always <= the max number, because if there are + * more, ShortcutParser would ignore the rest.) + */ + final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a, + ShortcutInfo b) -> { + if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) { + return -1; + } + if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) { + return 1; + } + if (a.isDynamic() && b.isDynamic()) { + return Integer.compare(a.getRank(), b.getRank()); + } + if (a.isDynamic()) { + return -1; + } + if (b.isDynamic()) { + return 1; + } + if (a.isCached() && b.isCached()) { + // if both shortcuts are cached, prioritize shortcuts cached by people tile, + if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE) + && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) { + return -1; + } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE) + && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) { + return 1; + } + // followed by bubbles. + if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES) + && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) { + return -1; + } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES) + && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) { + return 1; + } + } + if (a.isCached()) { + return -1; + } + if (b.isCached()) { + return 1; + } + return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp()); + }; + + /** * Build a list of shortcuts for each target activity and return as a map. The result won't * contain "floating" shortcuts because they don't belong on any activities. */ diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 0b20683185f0..f303fedde567 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -181,6 +181,9 @@ public class ShortcutService extends IShortcutService.Stub { static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15; @VisibleForTesting + static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100; + + @VisibleForTesting static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; @VisibleForTesting @@ -257,6 +260,11 @@ public class ShortcutService extends IShortcutService.Stub { String KEY_MAX_SHORTCUTS = "max_shortcuts"; /** + * Key name for the max shortcuts can be retained in system ram per app. (int) + */ + String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app"; + + /** * Key name for icon compression quality, 0-100. */ String KEY_ICON_QUALITY = "icon_quality"; @@ -329,11 +337,16 @@ public class ShortcutService extends IShortcutService.Stub { new SparseArray<>(); /** - * Max number of dynamic + manifest shortcuts that each application can have at a time. + * Max number of dynamic + manifest shortcuts that each activity can have at a time. */ private int mMaxShortcuts; /** + * Max number of shortcuts that can exists in system ram for each application. + */ + private int mMaxShortcutsPerApp; + + /** * Max number of updating API calls that each application can make during the interval. */ int mMaxUpdatesPerInterval; @@ -807,6 +820,9 @@ public class ShortcutService extends IShortcutService.Stub { mMaxShortcuts = Math.max(0, (int) parser.getLong( ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY)); + mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong( + ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP)); + final int iconDimensionDp = Math.max(1, injectIsLowRamDevice() ? (int) parser.getLong( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM, @@ -1759,6 +1775,13 @@ public class ShortcutService extends IShortcutService.Stub { } /** + * Return the max number of shortcuts can be retaiend in system ram for each application. + */ + int getMaxAppShortcuts() { + return mMaxShortcutsPerApp; + } + + /** * - Sends a notification to LauncherApps * - Write to file */ diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 7ce7f7ebf6cc..810fa5f1e4b3 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -247,6 +247,9 @@ public class ParsingPackageUtils { private static final String MAX_NUM_COMPONENTS_ERR_MSG = "Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS; + /** The maximum permission name length. */ + private static final int MAX_PERMISSION_NAME_LENGTH = 512; + @IntDef(flag = true, prefix = { "PARSE_" }, value = { PARSE_CHATTY, PARSE_COLLECT_CERTIFICATES, @@ -1275,6 +1278,11 @@ public class ParsingPackageUtils { // that may change. String name = sa.getNonResourceString( R.styleable.AndroidManifestUsesPermission_name); + if (TextUtils.length(name) > MAX_PERMISSION_NAME_LENGTH) { + return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "The name in the <uses-permission> is greater than " + + MAX_PERMISSION_NAME_LENGTH); + } int maxSdkVersion = 0; TypedValue val = sa.peekValue( diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index a2670eee0106..fd118d2d19a6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3349,8 +3349,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public void onKeyguardOccludedChangedLw(boolean occluded) { - if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { + public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) { + if (mKeyguardDelegate != null && waitAppTransition) { mPendingKeyguardOccluded = occluded; mKeyguardOccludedChanged = true; } else { diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 4f00992c713e..77007fa229a2 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -166,9 +166,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** * Called when the Keyguard occluded state changed. + * * @param occluded Whether Keyguard is currently occluded or not. */ - void onKeyguardOccludedChangedLw(boolean occluded); + void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition); /** * Applies a keyguard occlusion change if one happened. diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java index f586126196dd..7d148f6225be 100644 --- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java @@ -17,6 +17,7 @@ package com.android.server.security.rkp; import android.os.CancellationSignal; +import android.os.IBinder; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; import android.security.rkp.IGetKeyCallback; @@ -39,23 +40,23 @@ import java.util.concurrent.Executor; */ final class RemoteProvisioningRegistration extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; - private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mGetKeyOperations = + private final ConcurrentHashMap<IBinder, CancellationSignal> mGetKeyOperations = new ConcurrentHashMap<>(); - private final Set<IStoreUpgradedKeyCallback> mStoreUpgradedKeyOperations = - ConcurrentHashMap.newKeySet(); + private final Set<IBinder> mStoreUpgradedKeyOperations = ConcurrentHashMap.newKeySet(); private final RegistrationProxy mRegistration; private final Executor mExecutor; private class GetKeyReceiver implements OutcomeReceiver<RemotelyProvisionedKey, Exception> { IGetKeyCallback mCallback; + GetKeyReceiver(IGetKeyCallback callback) { mCallback = callback; } @Override public void onResult(RemotelyProvisionedKey result) { - mGetKeyOperations.remove(mCallback); - Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode()); + mGetKeyOperations.remove(mCallback.asBinder()); + Log.i(TAG, "Successfully fetched key for client " + mCallback.asBinder().hashCode()); android.security.rkp.RemotelyProvisionedKey parcelable = new android.security.rkp.RemotelyProvisionedKey(); parcelable.keyBlob = result.getKeyBlob(); @@ -65,19 +66,21 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void onError(Exception e) { - mGetKeyOperations.remove(mCallback); + mGetKeyOperations.remove(mCallback.asBinder()); if (e instanceof OperationCanceledException) { - Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode()); + Log.i(TAG, "Operation cancelled for client " + mCallback.asBinder().hashCode()); wrapCallback(mCallback::onCancel); } else if (e instanceof RkpProxyException) { - Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode() + ": " + Log.e(TAG, "RKP error fetching key for client " + mCallback.asBinder().hashCode() + + ": " + e.getMessage()); RkpProxyException rkpException = (RkpProxyException) e; wrapCallback(() -> mCallback.onError(toGetKeyError(rkpException), e.getMessage())); } else { - Log.e(TAG, "Unknown error fetching key for client " + mCallback.hashCode() + ": " - + e.getMessage()); + Log.e(TAG, + "Unknown error fetching key for client " + mCallback.asBinder().hashCode() + + ": " + e.getMessage()); wrapCallback(() -> mCallback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN, e.getMessage())); } @@ -108,20 +111,23 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void getKey(int keyId, IGetKeyCallback callback) { CancellationSignal cancellationSignal = new CancellationSignal(); - if (mGetKeyOperations.putIfAbsent(callback, cancellationSignal) != null) { - Log.e(TAG, "Client can only request one call at a time " + callback.hashCode()); + if (mGetKeyOperations.putIfAbsent(callback.asBinder(), cancellationSignal) != null) { + Log.e(TAG, + "Client can only request one call at a time " + callback.asBinder().hashCode()); throw new IllegalArgumentException( "Callback is already associated with an existing operation: " - + callback.hashCode()); + + callback.asBinder().hashCode()); } try { - Log.i(TAG, "Fetching key " + keyId + " for client " + callback.hashCode()); + Log.i(TAG, "Fetching key " + keyId + " for client " + callback.asBinder().hashCode()); mRegistration.getKeyAsync(keyId, cancellationSignal, mExecutor, new GetKeyReceiver(callback)); } catch (Exception e) { - Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e); - mGetKeyOperations.remove(callback); + Log.e(TAG, + "getKeyAsync threw an exception for client " + callback.asBinder().hashCode(), + e); + mGetKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN, e.getMessage())); } @@ -129,23 +135,23 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void cancelGetKey(IGetKeyCallback callback) { - CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback); + CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback.asBinder()); if (cancellationSignal == null) { throw new IllegalArgumentException( - "Invalid client in cancelGetKey: " + callback.hashCode()); + "Invalid client in cancelGetKey: " + callback.asBinder().hashCode()); } - Log.i(TAG, "Requesting cancellation for client " + callback.hashCode()); + Log.i(TAG, "Requesting cancellation for client " + callback.asBinder().hashCode()); cancellationSignal.cancel(); } @Override public void storeUpgradedKeyAsync(byte[] oldKeyBlob, byte[] newKeyBlob, IStoreUpgradedKeyCallback callback) { - if (!mStoreUpgradedKeyOperations.add(callback)) { + if (!mStoreUpgradedKeyOperations.add(callback.asBinder())) { throw new IllegalArgumentException( "Callback is already associated with an existing operation: " - + callback.hashCode()); + + callback.asBinder().hashCode()); } try { @@ -153,20 +159,20 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { new OutcomeReceiver<>() { @Override public void onResult(Void result) { - mStoreUpgradedKeyOperations.remove(callback); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(callback::onSuccess); } @Override public void onError(Exception e) { - mStoreUpgradedKeyOperations.remove(callback); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(e.getMessage())); } }); } catch (Exception e) { Log.e(TAG, "storeUpgradedKeyAsync threw an exception for client " - + callback.hashCode(), e); - mStoreUpgradedKeyOperations.remove(callback); + + callback.asBinder().hashCode(), e); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(e.getMessage())); } } diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java index cd1a968a8e89..2bd7383ddde0 100644 --- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java @@ -19,14 +19,18 @@ package com.android.server.security.rkp; import android.content.Context; import android.os.Binder; import android.os.OutcomeReceiver; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.security.rkp.IGetRegistrationCallback; import android.security.rkp.IRemoteProvisioning; import android.security.rkp.service.RegistrationProxy; import android.util.Log; +import com.android.internal.util.DumpUtils; import com.android.server.SystemService; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.time.Duration; import java.util.concurrent.Executor; @@ -57,7 +61,7 @@ public class RemoteProvisioningService extends SystemService { try { mCallback.onSuccess(new RemoteProvisioningRegistration(registration, mExecutor)); } catch (RemoteException e) { - Log.e(TAG, "Error calling success callback " + mCallback.hashCode(), e); + Log.e(TAG, "Error calling success callback " + mCallback.asBinder().hashCode(), e); } } @@ -66,7 +70,7 @@ public class RemoteProvisioningService extends SystemService { try { mCallback.onError(error.toString()); } catch (RemoteException e) { - Log.e(TAG, "Error calling error callback " + mCallback.hashCode(), e); + Log.e(TAG, "Error calling error callback " + mCallback.asBinder().hashCode(), e); } } } @@ -97,5 +101,18 @@ public class RemoteProvisioningService extends SystemService { Binder.restoreCallingIdentity(callingIdentity); } } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; + new RemoteProvisioningShellCommand().dump(pw); + } + + @Override + public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, + ParcelFileDescriptor err, String[] args) { + return new RemoteProvisioningShellCommand().exec(this, in.getFileDescriptor(), + out.getFileDescriptor(), err.getFileDescriptor(), args); + } } } diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java new file mode 100644 index 000000000000..bc3908452bc1 --- /dev/null +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.security.rkp; + +import android.hardware.security.keymint.DeviceInfo; +import android.hardware.security.keymint.IRemotelyProvisionedComponent; +import android.hardware.security.keymint.MacedPublicKey; +import android.hardware.security.keymint.ProtectedData; +import android.hardware.security.keymint.RpcHardwareInfo; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ShellCommand; +import android.util.IndentingPrintWriter; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.util.Base64; + +import co.nstant.in.cbor.CborDecoder; +import co.nstant.in.cbor.CborEncoder; +import co.nstant.in.cbor.CborException; +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.ByteString; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.Map; +import co.nstant.in.cbor.model.SimpleValue; +import co.nstant.in.cbor.model.UnsignedInteger; + +class RemoteProvisioningShellCommand extends ShellCommand { + private static final String USAGE = "usage: cmd remote_provisioning SUBCOMMAND [ARGS]\n" + + "help\n" + + " Show this message.\n" + + "dump\n" + + " Dump service diagnostics.\n" + + "list [--min-version MIN_VERSION]\n" + + " List the names of the IRemotelyProvisionedComponent instances.\n" + + "csr [--challenge CHALLENGE] NAME\n" + + " Generate and print a base64-encoded CSR from the named\n" + + " IRemotelyProvisionedComponent. A base64-encoded challenge can be provided,\n" + + " or else it defaults to an empty challenge.\n"; + + @VisibleForTesting + static final String EEK_ED25519_BASE64 = "goRDoQEnoFgqpAEBAycgBiFYIJm57t1e5FL2hcZMYtw+YatXSH11N" + + "ymtdoAy0rPLY1jZWEAeIghLpLekyNdOAw7+uK8UTKc7b6XN3Np5xitk/pk5r3bngPpmAIUNB5gqrJFcpyUUS" + + "QY0dcqKJ3rZ41pJ6wIDhEOhASegWE6lAQECWCDQrsEVyirPc65rzMvRlh1l6LHd10oaN7lDOpfVmd+YCAM4G" + + "CAEIVggvoXnRsSjQlpA2TY6phXQLFh+PdwzAjLS/F4ehyVfcmBYQJvPkOIuS6vRGLEOjl0gJ0uEWP78MpB+c" + + "gWDvNeCvvpkeC1UEEvAMb9r6B414vAtzmwvT/L1T6XUg62WovGHWAQ="; + + @VisibleForTesting + static final String EEK_P256_BASE64 = "goRDoQEmoFhNpQECAyYgASFYIPcUituX9MxT79JkEcTjdR9mH6RxDGzP" + + "+glGgHSHVPKtIlggXn9b9uzk9hnM/xM3/Q+hyJPbGAZ2xF3m12p3hsMtr49YQC+XjkL7vgctlUeFR5NAsB/U" + + "m0ekxESp8qEHhxDHn8sR9L+f6Dvg5zRMFfx7w34zBfTRNDztAgRgehXgedOK/ySEQ6EBJqBYcaYBAgJYIDVz" + + "tz+gioCJsSZn6ct8daGvAmH8bmUDkTvTS30UlD5GAzgYIAEhWCDgQc8vDzQPHDMsQbDP1wwwVTXSHmpHE0su" + + "0UiWfiScaCJYIB/ORcX7YbqBIfnlBZubOQ52hoZHuB4vRfHOr9o/gGjbWECMs7p+ID4ysGjfYNEdffCsOI5R" + + "vP9s4Wc7Snm8Vnizmdh8igfY2rW1f3H02GvfMyc0e2XRKuuGmZirOrSAqr1Q"; + + private static final int ERROR = -1; + private static final int SUCCESS = 0; + + private final Injector mInjector; + + RemoteProvisioningShellCommand() { + this(new Injector()); + } + + @VisibleForTesting + RemoteProvisioningShellCommand(Injector injector) { + mInjector = injector; + } + + @Override + public void onHelp() { + getOutPrintWriter().print(USAGE); + } + + @Override + @SuppressWarnings("CatchAndPrintStackTrace") + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + try { + switch (cmd) { + case "list": + return list(); + case "csr": + return csr(); + default: + return handleDefaultCommands(cmd); + } + } catch (Exception e) { + e.printStackTrace(getErrPrintWriter()); + return ERROR; + } + } + + @SuppressWarnings("CatchAndPrintStackTrace") + void dump(PrintWriter pw) { + try { + IndentingPrintWriter ipw = new IndentingPrintWriter(pw); + for (String name : mInjector.getIrpcNames()) { + ipw.println(name + ":"); + ipw.increaseIndent(); + dumpRpcInstance(ipw, name); + ipw.decreaseIndent(); + } + } catch (Exception e) { + e.printStackTrace(pw); + } + } + + private void dumpRpcInstance(PrintWriter pw, String name) throws RemoteException { + RpcHardwareInfo info = mInjector.getIrpcBinder(name).getHardwareInfo(); + pw.println("hwVersion=" + info.versionNumber); + pw.println("rpcAuthorName=" + info.rpcAuthorName); + if (info.versionNumber < 3) { + pw.println("supportedEekCurve=" + info.supportedEekCurve); + } + pw.println("uniqueId=" + info.uniqueId); + if (info.versionNumber >= 3) { + pw.println("supportedNumKeysInCsr=" + info.supportedNumKeysInCsr); + } + } + + private int list() throws RemoteException { + for (String name : mInjector.getIrpcNames()) { + getOutPrintWriter().println(name); + } + return SUCCESS; + } + + private int csr() throws RemoteException, CborException { + byte[] challenge = {}; + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--challenge": + challenge = Base64.getDecoder().decode(getNextArgRequired()); + break; + default: + getErrPrintWriter().println("error: unknown option " + opt); + return ERROR; + } + } + String name = getNextArgRequired(); + + IRemotelyProvisionedComponent binder = mInjector.getIrpcBinder(name); + RpcHardwareInfo info = binder.getHardwareInfo(); + MacedPublicKey[] emptyKeys = new MacedPublicKey[] {}; + byte[] csrBytes; + switch (info.versionNumber) { + case 1: + case 2: + DeviceInfo deviceInfo = new DeviceInfo(); + ProtectedData protectedData = new ProtectedData(); + byte[] eek = getEekChain(info.supportedEekCurve); + byte[] keysToSignMac = binder.generateCertificateRequest( + /*testMode=*/false, emptyKeys, eek, challenge, deviceInfo, protectedData); + csrBytes = composeCertificateRequestV1( + deviceInfo, challenge, protectedData, keysToSignMac); + break; + case 3: + csrBytes = binder.generateCertificateRequestV2(emptyKeys, challenge); + break; + default: + getErrPrintWriter().println("error: unsupported hwVersion: " + info.versionNumber); + return ERROR; + } + getOutPrintWriter().println(Base64.getEncoder().encodeToString(csrBytes)); + return SUCCESS; + } + + private byte[] getEekChain(int supportedEekCurve) { + switch (supportedEekCurve) { + case RpcHardwareInfo.CURVE_25519: + return Base64.getDecoder().decode(EEK_ED25519_BASE64); + case RpcHardwareInfo.CURVE_P256: + return Base64.getDecoder().decode(EEK_P256_BASE64); + default: + throw new IllegalArgumentException("unsupported EEK curve: " + supportedEekCurve); + } + } + + private byte[] composeCertificateRequestV1(DeviceInfo deviceInfo, byte[] challenge, + ProtectedData protectedData, byte[] keysToSignMac) throws CborException { + Array info = new Array() + .add(decode(deviceInfo.deviceInfo)) + .add(new Map()); + + // COSE_Signature with the hmac-sha256 algorithm and without a payload. + Array mac = new Array() + .add(new ByteString(encode( + new Map().put(new UnsignedInteger(1), new UnsignedInteger(5))))) + .add(new Map()) + .add(SimpleValue.NULL) + .add(new ByteString(keysToSignMac)); + + Array csr = new Array() + .add(info) + .add(new ByteString(challenge)) + .add(decode(protectedData.protectedData)) + .add(mac); + + return encode(csr); + } + + private byte[] encode(DataItem item) throws CborException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new CborEncoder(baos).encode(item); + return baos.toByteArray(); + } + + private DataItem decode(byte[] data) throws CborException { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + return new CborDecoder(bais).decodeNext(); + } + + @VisibleForTesting + static class Injector { + String[] getIrpcNames() { + return ServiceManager.getDeclaredInstances(IRemotelyProvisionedComponent.DESCRIPTOR); + } + + IRemotelyProvisionedComponent getIrpcBinder(String name) { + String irpc = IRemotelyProvisionedComponent.DESCRIPTOR + "/" + name; + IRemotelyProvisionedComponent binder = + IRemotelyProvisionedComponent.Stub.asInterface( + ServiceManager.waitForDeclaredService(irpc)); + if (binder == null) { + throw new IllegalArgumentException("failed to find " + irpc); + } + return binder; + } + } +} diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index fd6c9743cb6b..b160af6a3e11 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -98,7 +98,7 @@ class AppTaskImpl extends IAppTask.Stub { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); } return mService.getRecentTasks().createRecentTaskInfo(task, - false /* stripExtras */); + false /* stripExtras */, true /* getTasksAllowed */); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 48258a11d13a..1d21b9d8c141 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -403,8 +403,10 @@ class KeyguardController { return; } - mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY)); - if (isKeyguardLocked(displayId)) { + final boolean waitAppTransition = isKeyguardLocked(displayId); + mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY), + waitAppTransition); + if (waitAppTransition) { mService.deferWindowLayout(); try { mRootWindowContainer.getDefaultDisplay() diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 4860762a5f7f..1fc061b2ca78 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -976,7 +976,7 @@ class RecentTasks { continue; } - res.add(createRecentTaskInfo(task, true /* stripExtras */)); + res.add(createRecentTaskInfo(task, true /* stripExtras */, getTasksAllowed)); } return res; } @@ -1895,7 +1895,8 @@ class RecentTasks { /** * Creates a new RecentTaskInfo from a Task. */ - ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) { + ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras, + boolean getTasksAllowed) { final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo(); // If the recent Task is detached, we consider it will be re-attached to the default // TaskDisplayArea because we currently only support recent overview in the default TDA. @@ -1907,6 +1908,9 @@ class RecentTasks { rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID; rti.persistentId = rti.taskId; rti.lastSnapshotData.set(tr.mLastTaskSnapshotData); + if (!getTasksAllowed) { + Task.trimIneffectiveInfo(tr, rti); + } // Fill in organized child task info for the task created by organizer. if (tr.mCreatedByOrganizer) { diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java index 43baebc7255a..e646f14a3e13 100644 --- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java +++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java @@ -114,9 +114,15 @@ public class RemoteDisplayChangeController { // timed-out, so run all continue callbacks and clear the list synchronized (mService.mGlobalLock) { for (int i = 0; i < mCallbacks.size(); ++i) { - mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */); + final ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i); + if (i == mCallbacks.size() - 1) { + // Clear all callbacks before calling the last one, so that if the callback + // itself calls {@link #isWaitingForRemoteDisplayChange()}, it will get + // {@code false}. After all, there is nothing pending after this one. + mCallbacks.clear(); + } + callback.onContinueRemoteDisplayChange(null /* transaction */); } - mCallbacks.clear(); } } diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java index 33f019e0c9fb..4e339f1867ae 100644 --- a/services/core/java/com/android/server/wm/RunningTasks.java +++ b/services/core/java/com/android/server/wm/RunningTasks.java @@ -177,6 +177,10 @@ class RunningTasks { } // Fill in some deprecated values rti.id = rti.taskId; + + if (!mAllowed) { + Task.trimIneffectiveInfo(task, rti); + } return rti; } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 25957f15bd20..e0e5ba8c6545 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3471,6 +3471,54 @@ class Task extends TaskFragment { info.isSleeping = shouldSleepActivities(); } + /** + * Removes the activity info if the activity belongs to a different uid, which is + * different from the app that hosts the task. + */ + static void trimIneffectiveInfo(Task task, TaskInfo info) { + final ActivityRecord baseActivity = task.getActivity(r -> !r.finishing, + false /* traverseTopToBottom */); + final int baseActivityUid = + baseActivity != null ? baseActivity.getUid() : task.effectiveUid; + + if (info.topActivityInfo != null + && task.effectiveUid != info.topActivityInfo.applicationInfo.uid) { + // Making a copy to prevent eliminating the info in the original ActivityRecord. + info.topActivityInfo = new ActivityInfo(info.topActivityInfo); + info.topActivityInfo.applicationInfo = + new ApplicationInfo(info.topActivityInfo.applicationInfo); + + // Strip the sensitive info. + info.topActivity = new ComponentName("", ""); + info.topActivityInfo.packageName = ""; + info.topActivityInfo.taskAffinity = ""; + info.topActivityInfo.processName = ""; + info.topActivityInfo.name = ""; + info.topActivityInfo.parentActivityName = ""; + info.topActivityInfo.targetActivity = ""; + info.topActivityInfo.splitName = ""; + info.topActivityInfo.applicationInfo.className = ""; + info.topActivityInfo.applicationInfo.credentialProtectedDataDir = ""; + info.topActivityInfo.applicationInfo.dataDir = ""; + info.topActivityInfo.applicationInfo.deviceProtectedDataDir = ""; + info.topActivityInfo.applicationInfo.manageSpaceActivityName = ""; + info.topActivityInfo.applicationInfo.nativeLibraryDir = ""; + info.topActivityInfo.applicationInfo.nativeLibraryRootDir = ""; + info.topActivityInfo.applicationInfo.processName = ""; + info.topActivityInfo.applicationInfo.publicSourceDir = ""; + info.topActivityInfo.applicationInfo.scanPublicSourceDir = ""; + info.topActivityInfo.applicationInfo.scanSourceDir = ""; + info.topActivityInfo.applicationInfo.sourceDir = ""; + info.topActivityInfo.applicationInfo.taskAffinity = ""; + info.topActivityInfo.applicationInfo.name = ""; + info.topActivityInfo.applicationInfo.packageName = ""; + } + + if (task.effectiveUid != baseActivityUid) { + info.baseActivity = new ComponentName("", ""); + } + } + @Nullable PictureInPictureParams getPictureInPictureParams() { final Task topTask = getTopMostTask(); if (topTask == null) return null; diff --git a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java index c09962843890..8c798759c890 100644 --- a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java +++ b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java @@ -26,8 +26,8 @@ import java.util.HashMap; final class TaskFpsCallbackController { private final Context mContext; - private final HashMap<ITaskFpsCallback, Long> mTaskFpsCallbacks; - private final HashMap<ITaskFpsCallback, IBinder.DeathRecipient> mDeathRecipients; + private final HashMap<IBinder, Long> mTaskFpsCallbacks; + private final HashMap<IBinder, IBinder.DeathRecipient> mDeathRecipients; TaskFpsCallbackController(Context context) { mContext = context; @@ -36,32 +36,42 @@ final class TaskFpsCallbackController { } void registerListener(int taskId, ITaskFpsCallback callback) { - if (mTaskFpsCallbacks.containsKey(callback)) { + if (callback == null) { + return; + } + + IBinder binder = callback.asBinder(); + if (mTaskFpsCallbacks.containsKey(binder)) { return; } final long nativeListener = nativeRegister(callback, taskId); - mTaskFpsCallbacks.put(callback, nativeListener); + mTaskFpsCallbacks.put(binder, nativeListener); final IBinder.DeathRecipient deathRecipient = () -> unregisterListener(callback); try { - callback.asBinder().linkToDeath(deathRecipient, 0); - mDeathRecipients.put(callback, deathRecipient); + binder.linkToDeath(deathRecipient, 0); + mDeathRecipients.put(binder, deathRecipient); } catch (RemoteException e) { // ignore } } void unregisterListener(ITaskFpsCallback callback) { - if (!mTaskFpsCallbacks.containsKey(callback)) { + if (callback == null) { + return; + } + + IBinder binder = callback.asBinder(); + if (!mTaskFpsCallbacks.containsKey(binder)) { return; } - callback.asBinder().unlinkToDeath(mDeathRecipients.get(callback), 0); - mDeathRecipients.remove(callback); + binder.unlinkToDeath(mDeathRecipients.get(binder), 0); + mDeathRecipients.remove(binder); - nativeUnregister(mTaskFpsCallbacks.get(callback)); - mTaskFpsCallbacks.remove(callback); + nativeUnregister(mTaskFpsCallbacks.get(binder)); + mTaskFpsCallbacks.remove(binder); } private static native long nativeRegister(ITaskFpsCallback callback, int taskId); diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index 2584b86f53db..d9acf4182736 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -27,3 +27,4 @@ per-file com_android_server_security_* = file:/core/java/android/security/OWNERS per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS per-file com_android_server_am_CachedAppOptimizer.cpp = timmurray@google.com, edgararriaga@google.com, dualli@google.com, carmenjackson@google.com, philipcuadra@google.com +per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS diff --git a/services/core/xsd/vts/OWNERS b/services/core/xsd/vts/OWNERS new file mode 100644 index 000000000000..9af2ebaba437 --- /dev/null +++ b/services/core/xsd/vts/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 151862 +sundongahn@google.com diff --git a/services/musicrecognition/OWNERS b/services/musicrecognition/OWNERS index 58f5d40dd8c3..037b04831260 100644 --- a/services/musicrecognition/OWNERS +++ b/services/musicrecognition/OWNERS @@ -1,6 +1,5 @@ # Bug component: 830636 -joannechung@google.com oni@google.com volnov@google.com diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index f05b1d47ac0b..8f23ae4ff33b 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -20,9 +20,11 @@ import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Handler; import android.os.IBinder.DeathRecipient; import android.os.Looper; @@ -53,7 +55,8 @@ public final class ProfcollectForwardingService extends SystemService { public static final String LOG_TAG = "ProfcollectForwardingService"; private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); - + private static final String INTENT_UPLOAD_PROFILES = + "com.android.server.profcollect.UPLOAD_PROFILES"; private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours. private IProfCollectd mIProfcollect; @@ -66,6 +69,16 @@ public final class ProfcollectForwardingService extends SystemService { } }; + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (INTENT_UPLOAD_PROFILES.equals(intent.getAction())) { + Log.d(LOG_TAG, "Received broadcast to pack and upload reports"); + packAndUploadReport(); + } + } + }; + public ProfcollectForwardingService(Context context) { super(context); @@ -73,6 +86,10 @@ public final class ProfcollectForwardingService extends SystemService { throw new AssertionError("only one service instance allowed"); } sSelfService = this; + + final IntentFilter filter = new IntentFilter(); + filter.addAction(INTENT_UPLOAD_PROFILES); + context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED); } /** @@ -296,7 +313,7 @@ public final class ProfcollectForwardingService extends SystemService { } if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) { - packProfileReport(); + packAndUploadReport(); } } @@ -307,7 +324,7 @@ public final class ProfcollectForwardingService extends SystemService { }); } - private void packProfileReport() { + private void packAndUploadReport() { if (mIProfcollect == null) { return; } diff --git a/services/tests/PackageManagerServiceTests/TEST_MAPPING b/services/tests/PackageManagerServiceTests/TEST_MAPPING index e98acb2bb6a9..5d96af9df1fb 100644 --- a/services/tests/PackageManagerServiceTests/TEST_MAPPING +++ b/services/tests/PackageManagerServiceTests/TEST_MAPPING @@ -55,23 +55,10 @@ // TODO(b/204133664) "exclude-filter": "com.android.server.pm.test.SdCardEjectionTests" }, - { - // TODO(b/272575212) - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataBinaryXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataTextXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderBinaryXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderTextXml" - }, - { + { // TODO(b/272714903) "exclude-filter": "com.android.server.pm.test.OverlayPathsUninstallSystemUpdatesTest#verify" - } + } ] } ], diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java index 1dcd0b936c86..df7be515774a 100644 --- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java +++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java @@ -23,8 +23,10 @@ import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.contains; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; @@ -32,6 +34,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.os.Binder; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; @@ -101,8 +104,10 @@ public class RemoteProvisioningRegistrationTest { .when(mRegistrationProxy).getKeyAsync(eq(42), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(42, callback); verify(callback).onSuccess(matches(expectedKey)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -114,8 +119,10 @@ public class RemoteProvisioningRegistrationTest { executor.execute(() -> receiver.onError(expectedException)))) .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq("oops!")); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -140,18 +147,28 @@ public class RemoteProvisioningRegistrationTest { executor.execute(() -> receiver.onError(expectedException)))) .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(error), contains(errorField.getName())); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } } @Test public void getKeyCancelDuringProxyOperation() throws Exception { + final Binder theBinder = new Binder(); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(theBinder).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> { - mRegistration.cancelGetKey(callback); + // Use a different callback object to ensure that the callback equivalence + // relies on the actual IBinder object. + IGetKeyCallback differentCallback = mock(IGetKeyCallback.class); + doReturn(theBinder).when(differentCallback).asBinder(); + mRegistration.cancelGetKey(differentCallback); + verify(differentCallback, atLeastOnce()).asBinder(); + verifyNoMoreInteractions(differentCallback); assertThat(cancelSignal.isCanceled()).isTrue(); executor.execute(() -> receiver.onError(new OperationCanceledException())); })) @@ -159,18 +176,21 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(Integer.MAX_VALUE, callback); verify(callback).onCancel(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void cancelGetKeyWithInvalidCallback() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); } @Test public void getKeyRejectsDuplicateCallback() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> { assertThrows(IllegalArgumentException.class, () -> @@ -181,12 +201,14 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(0, callback); verify(callback, times(1)).onSuccess(any()); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void getKeyCancelAfterCompleteFails() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> executor.execute(() -> @@ -197,6 +219,7 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(Integer.MIN_VALUE, callback); verify(callback).onSuccess(any()); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -208,10 +231,12 @@ public class RemoteProvisioningRegistrationTest { .getKeyAsync(anyInt(), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq(expectedException.getMessage())); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -224,8 +249,10 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onSuccess(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -239,8 +266,10 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onError(errorString); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -252,14 +281,17 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onError(errorString); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void storeUpgradedKeyDuplicateCallback() throws Exception { IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) -> { @@ -273,6 +305,7 @@ public class RemoteProvisioningRegistrationTest { mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onSuccess(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java new file mode 100644 index 000000000000..77c339646400 --- /dev/null +++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.security.rkp; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.hardware.security.keymint.DeviceInfo; +import android.hardware.security.keymint.IRemotelyProvisionedComponent; +import android.hardware.security.keymint.MacedPublicKey; +import android.hardware.security.keymint.ProtectedData; +import android.hardware.security.keymint.RpcHardwareInfo; +import android.os.Binder; +import android.os.FileUtils; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.Arrays; +import java.util.Base64; +import java.util.Map; + +@RunWith(AndroidJUnit4.class) +public class RemoteProvisioningShellCommandTest { + + private static class Injector extends RemoteProvisioningShellCommand.Injector { + + private final Map<String, IRemotelyProvisionedComponent> mIrpcs; + + Injector(Map irpcs) { + mIrpcs = irpcs; + } + + @Override + String[] getIrpcNames() { + return mIrpcs.keySet().toArray(new String[0]); + } + + @Override + IRemotelyProvisionedComponent getIrpcBinder(String name) { + IRemotelyProvisionedComponent irpc = mIrpcs.get(name); + if (irpc == null) { + throw new IllegalArgumentException("failed to find " + irpc); + } + return irpc; + } + } + + private static class CommandResult { + private int mCode; + private String mOut; + private String mErr; + + CommandResult(int code, String out, String err) { + mCode = code; + mOut = out; + mErr = err; + } + + int getCode() { + return mCode; + } + + String getOut() { + return mOut; + } + + String getErr() { + return mErr; + } + } + + private static CommandResult exec( + RemoteProvisioningShellCommand cmd, String[] args) throws Exception { + File in = File.createTempFile("rpsct_in_", null); + File out = File.createTempFile("rpsct_out_", null); + File err = File.createTempFile("rpsct_err_", null); + int code = cmd.exec( + new Binder(), + new FileInputStream(in).getFD(), + new FileOutputStream(out).getFD(), + new FileOutputStream(err).getFD(), + args); + return new CommandResult( + code, FileUtils.readTextFile(out, 0, null), FileUtils.readTextFile(err, 0, null)); + } + + @Test + public void list_zeroInstances() throws Exception { + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of())); + CommandResult res = exec(cmd, new String[] {"list"}); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + assertThat(res.getOut()).isEmpty(); + } + + @Test + public void list_oneInstances() throws Exception { + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of("default", mock(IRemotelyProvisionedComponent.class)))); + CommandResult res = exec(cmd, new String[] {"list"}); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + assertThat(Arrays.asList(res.getOut().split("\n"))).containsExactly("default"); + } + + @Test + public void list_twoInstances() throws Exception { + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of( + "default", mock(IRemotelyProvisionedComponent.class), + "strongbox", mock(IRemotelyProvisionedComponent.class)))); + CommandResult res = exec(cmd, new String[] {"list"}); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + assertThat(Arrays.asList(res.getOut().split("\n"))).containsExactly("default", "strongbox"); + } + + @Test + public void csr_hwVersion1_withChallenge() throws Exception { + IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class); + RpcHardwareInfo defaultInfo = new RpcHardwareInfo(); + defaultInfo.versionNumber = 1; + defaultInfo.supportedEekCurve = RpcHardwareInfo.CURVE_25519; + when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo); + doAnswer(invocation -> { + ((DeviceInfo) invocation.getArgument(4)).deviceInfo = new byte[] {0x00}; + ((ProtectedData) invocation.getArgument(5)).protectedData = new byte[] {0x00}; + return new byte[] {0x77, 0x77, 0x77, 0x77}; + }).when(defaultMock).generateCertificateRequest( + anyBoolean(), any(), any(), any(), any(), any()); + + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of("default", defaultMock))); + CommandResult res = exec(cmd, new String[] { + "csr", "--challenge", "dGVzdHRlc3R0ZXN0dGVzdA==", "default"}); + verify(defaultMock).generateCertificateRequest( + /*test_mode=*/eq(false), + eq(new MacedPublicKey[0]), + eq(Base64.getDecoder().decode(RemoteProvisioningShellCommand.EEK_ED25519_BASE64)), + eq(new byte[] { + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74}), + any(DeviceInfo.class), + any(ProtectedData.class)); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + } + + @Test + public void csr_hwVersion2_withChallenge() throws Exception { + IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class); + RpcHardwareInfo defaultInfo = new RpcHardwareInfo(); + defaultInfo.versionNumber = 2; + defaultInfo.supportedEekCurve = RpcHardwareInfo.CURVE_P256; + when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo); + doAnswer(invocation -> { + ((DeviceInfo) invocation.getArgument(4)).deviceInfo = new byte[] {0x00}; + ((ProtectedData) invocation.getArgument(5)).protectedData = new byte[] {0x00}; + return new byte[] {0x77, 0x77, 0x77, 0x77}; + }).when(defaultMock).generateCertificateRequest( + anyBoolean(), any(), any(), any(), any(), any()); + + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of("default", defaultMock))); + CommandResult res = exec(cmd, new String[] { + "csr", "--challenge", "dGVzdHRlc3R0ZXN0dGVzdA==", "default"}); + verify(defaultMock).generateCertificateRequest( + /*test_mode=*/eq(false), + eq(new MacedPublicKey[0]), + eq(Base64.getDecoder().decode(RemoteProvisioningShellCommand.EEK_P256_BASE64)), + eq(new byte[] { + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74}), + any(DeviceInfo.class), + any(ProtectedData.class)); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + } + + @Test + public void csr_hwVersion3_withoutChallenge() throws Exception { + IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class); + RpcHardwareInfo defaultInfo = new RpcHardwareInfo(); + defaultInfo.versionNumber = 3; + when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo); + when(defaultMock.generateCertificateRequestV2(any(), any())) + .thenReturn(new byte[] {0x68, 0x65, 0x6c, 0x6c, 0x6f}); + + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of("default", defaultMock))); + CommandResult res = exec(cmd, new String[] {"csr", "default"}); + verify(defaultMock).generateCertificateRequestV2(new MacedPublicKey[0], new byte[0]); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + assertThat(res.getOut()).isEqualTo("aGVsbG8=\n"); + } + + @Test + public void csr_hwVersion3_withChallenge() throws Exception { + IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class); + RpcHardwareInfo defaultInfo = new RpcHardwareInfo(); + defaultInfo.versionNumber = 3; + when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo); + when(defaultMock.generateCertificateRequestV2(any(), any())) + .thenReturn(new byte[] {0x68, 0x69}); + + RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand( + new Injector(Map.of("default", defaultMock))); + CommandResult res = exec(cmd, new String[] {"csr", "--challenge", "dHJpYWw=", "default"}); + verify(defaultMock).generateCertificateRequestV2( + new MacedPublicKey[0], new byte[] {0x74, 0x72, 0x69, 0x61, 0x6c}); + assertThat(res.getErr()).isEmpty(); + assertThat(res.getCode()).isEqualTo(0); + assertThat(res.getOut()).isEqualTo("aGk=\n"); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS b/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS new file mode 100644 index 000000000000..daa02111f71f --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS @@ -0,0 +1,3 @@ +ancr@google.com +harshitmahajan@google.com +robertogil@google.com diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index d622a8032485..40d99487fd9c 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -103,6 +103,9 @@ android_test { data: [ ":JobTestApp", ":StubTestApp", + ":SimpleServiceTestApp1", + ":SimpleServiceTestApp2", + ":SimpleServiceTestApp3", ], java_resources: [ diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index 035249e32d74..094bcfb6fcb4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -344,6 +344,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse(); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_succeedsWithCertFile() throws Exception { int uid = Binder.getCallingUid(); @@ -365,6 +366,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull(); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_updatesShouldCreatesnapshotOnCertUpdate() throws Exception { int uid = Binder.getCallingUid(); @@ -392,6 +394,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_triesToFilterRootAlias() throws Exception { int uid = Binder.getCallingUid(); @@ -413,6 +416,7 @@ public class RecoverableKeyStoreManagerTest { } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_usesProdCertificateForEmptyRootAlias() throws Exception { int uid = Binder.getCallingUid(); @@ -433,6 +437,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_usesProdCertificateForNullRootAlias() throws Exception { int uid = Binder.getCallingUid(); @@ -453,6 +458,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_regeneratesCounterId() throws Exception { int uid = Binder.getCallingUid(); @@ -483,6 +489,7 @@ public class RecoverableKeyStoreManagerTest { } } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_updatesWithLargerSerial() throws Exception { int uid = Binder.getCallingUid(); @@ -500,6 +507,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse(); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_throwsExceptionOnSmallerSerial() throws Exception { int uid = Binder.getCallingUid(); @@ -565,6 +573,7 @@ public class RecoverableKeyStoreManagerTest { TestData.getInsecureCertPathForEndpoint1()); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryService_ignoresTheSameSerial() throws Exception { int uid = Binder.getCallingUid(); @@ -615,6 +624,7 @@ public class RecoverableKeyStoreManagerTest { } } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryServiceWithSigFile_succeeds() throws Exception { int uid = Binder.getCallingUid(); @@ -630,6 +640,7 @@ public class RecoverableKeyStoreManagerTest { assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull(); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void initRecoveryServiceWithSigFile_usesProdCertificateForNullRootAlias() throws Exception { @@ -723,6 +734,7 @@ public class RecoverableKeyStoreManagerTest { eq(Manifest.permission.RECOVER_KEYSTORE), any()); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void startRecoverySessionWithCertPath_storesTheSessionInfo() throws Exception { mRecoverableKeyStoreManager.startRecoverySessionWithCertPath( @@ -740,6 +752,7 @@ public class RecoverableKeyStoreManagerTest { assertEquals(KEY_CLAIMANT_LENGTH_BYTES, entry.getKeyClaimant().length); } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void startRecoverySessionWithCertPath_checksPermissionFirst() throws Exception { mRecoverableKeyStoreManager.startRecoverySessionWithCertPath( @@ -809,6 +822,7 @@ public class RecoverableKeyStoreManagerTest { } } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void startRecoverySession_throwsIfBadNumberOfSecrets() throws Exception { try { @@ -825,6 +839,7 @@ public class RecoverableKeyStoreManagerTest { } } + @Ignore("Causing breakages so ignoring to resolve, b/281583079") @Test public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception { byte[] vaultParams = TEST_VAULT_PARAMS.clone(); diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 7c7e2ee53f3c..012596e4327e 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -151,6 +151,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionPlan; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.MediumTest; import android.text.TextUtils; @@ -241,6 +242,7 @@ public class NetworkPolicyManagerServiceTest { private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey"; private static final String TEST_IMSI = "310210"; private static final int TEST_SUB_ID = 42; + private static final int TEST_SUB_ID2 = 24; private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS); private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI) @@ -282,6 +284,8 @@ public class NetworkPolicyManagerServiceTest { private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); + private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener; + private ActivityManagerInternal mActivityManagerInternal; private PackageManagerInternal mPackageManagerInternal; @@ -357,6 +361,8 @@ public class NetworkPolicyManagerServiceTest { private class TestDependencies extends NetworkPolicyManagerService.Dependencies { private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>(); + private int mMockDefaultDataSubId; + private int mMockedActiveDataSubId; TestDependencies(Context context) { super(context); @@ -394,6 +400,21 @@ public class NetworkPolicyManagerServiceTest { final NetworkStats.Bucket bucket = mMockedStats.get(uid); setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes); } + + void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) { + mMockDefaultDataSubId = defaultDataSubId; + mMockedActiveDataSubId = activeDataSubId; + } + + @Override + int getDefaultDataSubId() { + return mMockDefaultDataSubId; + } + + @Override + int getActivateDataSubId() { + return mMockedActiveDataSubId; + } } @Before @@ -551,6 +572,14 @@ public class NetworkPolicyManagerServiceTest { NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, ""); mDefaultWarningBytes = defaultPolicy.warningBytes; mDefaultLimitBytes = defaultPolicy.limitBytes; + + // Catch TelephonyCallback during systemReady(). + ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor = + ArgumentCaptor.forClass(TelephonyCallback.class); + verify(mTelephonyManager).registerTelephonyCallback(any(), + telephonyCallbackArgumentCaptor.capture()); + mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener) + telephonyCallbackArgumentCaptor.getValue(); } @After @@ -1243,6 +1272,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); + clearInvocations(mNotifManager); mService.updateNetworks(); @@ -1258,6 +1288,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); + clearInvocations(mNotifManager); mService.updateNetworks(); @@ -1275,6 +1306,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); expectDefaultCarrierConfig(); + clearInvocations(mNotifManager); mService.updateNetworks(); @@ -1291,6 +1323,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); + clearInvocations(mNotifManager); mService.updateNetworks(); @@ -1304,6 +1337,7 @@ public class NetworkPolicyManagerServiceTest { { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); + clearInvocations(mNotifManager); mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); @@ -1314,6 +1348,31 @@ public class NetworkPolicyManagerServiceTest { verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } + // The sub is no longer used for data(e.g. user uses another sub), hide the notifications. + { + reset(mTelephonyManager, mNetworkManager, mNotifManager); + + notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2); + verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED)); + } + // The sub is not active for data(e.g. due to auto data switch), but still default for data, + // show notification. + { + reset(mTelephonyManager, mNetworkManager, mNotifManager); + + notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2); + verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), + isA(Notification.class), eq(UserHandle.ALL)); + } + // The sub is active for data, but not the default(e.g. due to auto data switch), + // show notification. + { + reset(mTelephonyManager, mNetworkManager, mNotifManager); + + notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID); + verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), + isA(Notification.class), eq(UserHandle.ALL)); + } } @Test @@ -2377,6 +2436,7 @@ public class NetworkPolicyManagerServiceTest { String subscriberId) { when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( createSubscriptionInfoList(subscriptionId)); + notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId); TelephonyManager subTelephonyManager; subTelephonyManager = mock(TelephonyManager.class); @@ -2388,6 +2448,16 @@ public class NetworkPolicyManagerServiceTest { } /** + * Telephony Manager callback notifies data sub Id changes. + * @param defaultDataSubId The mock default data sub Id. + * @param activeDataSubId The mock active data sub Id. + */ + private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) { + mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId); + mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId); + } + + /** * Creates mock {@link SubscriptionInfo} from subscription id. */ private List<SubscriptionInfo> createSubscriptionInfoList(int subId) { diff --git a/services/tests/servicestests/utils/com/android/server/testutils/OWNERS b/services/tests/servicestests/utils/com/android/server/testutils/OWNERS new file mode 100644 index 000000000000..bdacf7f37d3f --- /dev/null +++ b/services/tests/servicestests/utils/com/android/server/testutils/OWNERS @@ -0,0 +1 @@ +per-file *Transaction.java = file:/services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file diff --git a/services/tests/uiservicestests/OWNERS b/services/tests/uiservicestests/OWNERS new file mode 100644 index 000000000000..c0cbea98cc57 --- /dev/null +++ b/services/tests/uiservicestests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS
\ No newline at end of file diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index adf694c2a88d..db6ac0b432b3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -30,6 +30,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static android.os.Process.NOBODY_UID; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -1220,20 +1221,35 @@ public class RecentTasksTest extends WindowTestsBase { @Test public void testCreateRecentTaskInfo_detachedTask() { - final Task task = createTaskBuilder(".Task").setCreateActivity(true).build(); + final Task task = createTaskBuilder(".Task").build(); + final ComponentName componentName = getUniqueComponentName(); + new ActivityBuilder(mSupervisor.mService) + .setTask(task) + .setUid(NOBODY_UID) + .setComponent(componentName) + .build(); final TaskDisplayArea tda = task.getDisplayArea(); assertTrue(task.isAttached()); assertTrue(task.supportsMultiWindow()); - RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true); + RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + false /* getTasksAllowed */); + + assertFalse(info.topActivity.equals(componentName)); + assertFalse(info.topActivityInfo.packageName.equals(componentName.getPackageName())); + assertFalse(info.baseActivity.equals(componentName)); + // The task can be put in split screen even if it is not attached now. task.removeImmediately(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); @@ -1242,7 +1258,8 @@ public class RecentTasksTest extends WindowTestsBase { doReturn(false).when(tda).supportsNonResizableMultiWindow(); doReturn(false).when(task).isResizeable(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertFalse(info.supportsMultiWindow); @@ -1250,7 +1267,8 @@ public class RecentTasksTest extends WindowTestsBase { // the device supports it. doReturn(true).when(tda).supportsNonResizableMultiWindow(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index d2cb7ba5d311..e2db2e6b19e1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -222,7 +222,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public void onKeyguardOccludedChangedLw(boolean occluded) { + public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) { } public void setSafeMode(boolean safeMode) { diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index 42a5af7fdce3..3a8ef3370a53 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -71,6 +71,7 @@ public final class UsbAlsaManager { private static final int USB_VENDORID_SONY = 0x054C; private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4; private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC; + private static final int USB_PRODUCTID_PS5CONTROLLER = 0x0CE6; private static final int USB_DENYLIST_OUTPUT = 0x0001; private static final int USB_DENYLIST_INPUT = 0x0002; @@ -93,6 +94,9 @@ public final class UsbAlsaManager { USB_DENYLIST_OUTPUT), new DenyListEntry(USB_VENDORID_SONY, USB_PRODUCTID_PS4CONTROLLER_ZCT2, + USB_DENYLIST_OUTPUT), + new DenyListEntry(USB_VENDORID_SONY, + USB_PRODUCTID_PS5CONTROLLER, USB_DENYLIST_OUTPUT)); private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) { diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index ec18c6a696b8..7a53447c1eee 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -555,6 +555,11 @@ public final class PhoneAccount implements Parcelable { /** * Sets the address. See {@link PhoneAccount#getAddress}. + * <p> + * Note: The entire URI value is limited to 256 characters. This check is + * enforced when registering the PhoneAccount via + * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an + * {@link IllegalArgumentException} to be thrown if URI is over 256. * * @param value The address of the phone account. * @return The builder. @@ -588,6 +593,10 @@ public final class PhoneAccount implements Parcelable { /** * Sets the icon. See {@link PhoneAccount#getIcon}. + * <p> + * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory. + * This check is enforced when registering the PhoneAccount via + * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} * * @param icon The icon to set. */ @@ -621,6 +630,10 @@ public final class PhoneAccount implements Parcelable { /** * Specifies an additional URI scheme supported by the {@link PhoneAccount}. * + * <p> + * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will + * cause an {@link IllegalArgumentException} to be thrown when the account is registered. + * * @param uriScheme The URI scheme. * @return The builder. */ @@ -634,6 +647,12 @@ public final class PhoneAccount implements Parcelable { /** * Specifies the URI schemes supported by the {@link PhoneAccount}. * + * <p> + * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is + * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any + * scheme will cause an {@link IllegalArgumentException} to be thrown when the account + * is registered. + * * @param uriSchemes The URI schemes. * @return The builder. */ diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 329849bd7682..c90b94dc64c1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3708,13 +3708,12 @@ public class CarrierConfigManager { * NR_SA - NR SA is unmetered for sub-6 frequencies * NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies * - * Note that this config only applies if an unmetered SubscriptionPlan is set via - * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set + * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link + * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)} * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}. * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered * regardless of the value of this config. - * TODO: remove other unmetered keys and replace with this * @hide */ public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY = @@ -3729,73 +3728,18 @@ public class CarrierConfigManager { * NR_SA - NR SA is unmetered when roaming for sub-6 frequencies * NR_SA_MMWAVE - NR SA is unmetered when roaming for mmwave frequencies * - * Note that this config only applies if an unmetered SubscriptionPlan is set via - * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set + * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link + * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)} * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}. * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered * when roaming regardless of the value of this config. - * TODO: remove KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL and replace with this * @hide */ public static final String KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY = "roaming_unmetered_network_types_string_array"; /** - * Whether NR (non-standalone) should be unmetered for all frequencies. - * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or - * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool"; - - /** - * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool"; - - /** - * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool"; - - /** - * Whether NR (non-standalone) should be unmetered when the device is roaming. - * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL}, - * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL}, - * and unmetered {@link SubscriptionPlan} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL = - "unmetered_nr_nsa_when_roaming_bool"; - - /** - * Whether NR (standalone) should be unmetered for all frequencies. - * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or - * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool"; - - /** - * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool"; - - /** - * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool"; - - /** * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable * this feature. * @hide @@ -9255,13 +9199,6 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[] { "NR_NSA", "NR_NSA_MMWAVE", "NR_SA", "NR_SA_MMWAVE"}); sDefaults.putStringArray(KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false); sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false); sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index d590ce22e9df..45c092e1fb0d 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -160,6 +160,10 @@ public class SubscriptionManager { private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY = "cache_key.telephony.subscription_manager_service"; + /** The temporarily cache key to indicate whether subscription manager service is enabled. */ + private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY = + "cache_key.telephony.subscription_manager_service_enabled"; + /** @hide */ public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings"; @@ -317,6 +321,12 @@ public class SubscriptionManager { CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY, INVALID_PHONE_INDEX); + //TODO: Removed before U AOSP public release. + private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled = + new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled, + CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY, + false); + /** * Generates a content {@link Uri} used to receive updates on simInfo change * on the given subscriptionId @@ -1335,8 +1345,6 @@ public class SubscriptionManager { private final Context mContext; - private static boolean sIsSubscriptionManagerServiceEnabled = false; - // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing // the Context and subId. private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = @@ -1422,9 +1430,6 @@ public class SubscriptionManager { public SubscriptionManager(Context context) { if (DBG) logd("SubscriptionManager created"); mContext = context; - - sIsSubscriptionManagerServiceEnabled = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_using_subscription_manager_service); } /** @@ -1433,8 +1438,9 @@ public class SubscriptionManager { * * @hide */ + //TODO: Removed before U AOSP public release. public static boolean isSubscriptionManagerServiceEnabled() { - return sIsSubscriptionManagerServiceEnabled; + return sIsSubscriptionManagerServiceEnabled.query(null); } private NetworkPolicyManager getNetworkPolicyManager() { @@ -3947,6 +3953,13 @@ public class SubscriptionManager { PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY); } + /** @hide */ + //TODO: Removed before U AOSP public release. + public static void invalidateSubscriptionManagerServiceEnabledCaches() { + PropertyInvalidatedCache.invalidateCache( + CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY); + } + /** * Allows a test process to disable client-side caching operations. * @@ -3968,6 +3981,8 @@ public class SubscriptionManager { sGetSlotIndexCache.disableLocal(); sGetSubIdCache.disableLocal(); sGetPhoneIdCache.disableLocal(); + + sIsSubscriptionManagerServiceEnabled.disableLocal(); } /** @@ -3990,6 +4005,8 @@ public class SubscriptionManager { sGetSlotIndexCache.clear(); sGetSubIdCache.clear(); sGetPhoneIdCache.clear(); + + sIsSubscriptionManagerServiceEnabled.clear(); } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fd5ec258d697..fa60031f2a66 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -311,6 +311,31 @@ public class TelephonyManager { public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; /** + * Convert srvcc handover state to string. + * + * @param state The srvcc handover state. + * @return The srvcc handover state in string format. + * + * @hide + */ + public static @NonNull String srvccStateToString(int state) { + switch (state) { + case TelephonyManager.SRVCC_STATE_HANDOVER_NONE: + return "NONE"; + case TelephonyManager.SRVCC_STATE_HANDOVER_STARTED: + return "STARTED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED: + return "COMPLETED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_FAILED: + return "FAILED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED: + return "CANCELED"; + default: + return "UNKNOWN(" + state + ")"; + } + } + + /** * A UICC card identifier used if the device does not support the operation. * For example, {@link #getCardIdForDefaultEuicc()} returns this value if the device has no * eUICC, or the eUICC cannot be read. diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java index 19f2a9bc67a3..b7617099bae3 100644 --- a/telephony/java/android/telephony/TelephonyScanManager.java +++ b/telephony/java/android/telephony/TelephonyScanManager.java @@ -153,8 +153,9 @@ public final class TelephonyScanManager { nsi = mScanInfo.get(message.arg2); } if (nsi == null) { - throw new RuntimeException( - "Failed to find NetworkScanInfo with id " + message.arg2); + Rlog.e(TAG, "Unexpceted message " + message.what + + " as there is no NetworkScanInfo with id " + message.arg2); + return; } final NetworkScanCallback callback = nsi.mCallback; diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 25a714a4bb81..defa046da503 100644 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -356,4 +356,11 @@ interface ISub { * @hide */ List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle); + + /** + * @return {@code true} if using SubscriptionManagerService instead of + * SubscriptionController. + */ + //TODO: Removed before U AOSP public release. + boolean isSubscriptionManagerServiceEnabled(); } diff --git a/tests/ActivityManagerPerfTests/utils/Android.bp b/tests/ActivityManagerPerfTests/utils/Android.bp index 99c43c8d8fca..5902c1cbda15 100644 --- a/tests/ActivityManagerPerfTests/utils/Android.bp +++ b/tests/ActivityManagerPerfTests/utils/Android.bp @@ -32,6 +32,6 @@ java_test { static_libs: [ "androidx.test.rules", "junit", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], } diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java index fc787bafa93a..9bd94f2a9a1e 100644 --- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java +++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java @@ -19,10 +19,10 @@ package com.android.frameworks.perftests.am.util; import android.content.Intent; import android.os.RemoteException; import android.os.ResultReceiver; -import android.support.test.uiautomator.UiDevice; import android.util.Log; import androidx.test.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import java.io.IOException; diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp index de9bbb6ef9fa..a92a6ae5a7a4 100644 --- a/tests/Input/Android.bp +++ b/tests/Input/Android.bp @@ -21,7 +21,7 @@ android_test { "services.core.unboosted", "testables", "truth-prebuilt", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], test_suites: ["device-tests"], } diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt index 1d65cc35c3bc..8025406499d8 100644 --- a/tests/Input/src/com/android/test/input/AnrTest.kt +++ b/tests/Input/src/com/android/test/input/AnrTest.kt @@ -27,14 +27,15 @@ import android.os.IInputConstants.UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLI import android.os.SystemClock import android.provider.Settings import android.provider.Settings.Global.HIDE_ERROR_DIALOGS -import android.support.test.uiautomator.By -import android.support.test.uiautomator.UiDevice -import android.support.test.uiautomator.UiObject2 -import android.support.test.uiautomator.Until import android.testing.PollingCheck import android.view.InputDevice import android.view.MotionEvent +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiObject2 +import androidx.test.uiautomator.Until + import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml index 947453d07bd9..ad0584724fdc 100644 --- a/tests/SharedLibraryLoadingTest/AndroidTest.xml +++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml @@ -22,7 +22,6 @@ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> - <option name="cleanup" value="false" /> <option name="remount-system" value="true" /> <option name="push" value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" /> diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp index ed86aa5f90ea..8542f885d645 100644 --- a/tests/WindowAnimationJank/Android.bp +++ b/tests/WindowAnimationJank/Android.bp @@ -25,7 +25,7 @@ android_test { name: "WindowAnimationJank", srcs: ["src/**/*.java"], static_libs: [ - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "androidx.test.janktesthelper", "junit", ], diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java index 25314644ca7e..48a359c4d0c6 100644 --- a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java +++ b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java @@ -18,11 +18,12 @@ import android.app.UiAutomation; import android.content.ComponentName; import android.content.Intent; import android.os.SystemClock; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.Until; + +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.Until; /** * Set of helpers to manipulate test activities. diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java index a8ace162c4d0..cb7c5112cba7 100644 --- a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java +++ b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java @@ -16,9 +16,8 @@ package android.windowanimationjank; -import android.support.test.uiautomator.UiDevice; - import androidx.test.jank.JankTestBase; +import androidx.test.uiautomator.UiDevice; /** * This adds additional system level jank monitor and its result is merged with primary monitor diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java index b94bb41c0988..d10ae307fdf4 100644 --- a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java +++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java @@ -47,6 +47,10 @@ public class FakePermissionEnforcer extends PermissionEnforcer { mGranted.remove(permission); } + public void revokeAll() { + mGranted.clear(); + } + private boolean granted(String permission) { return mGranted.contains(permission); } diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index 34e8edb0a47f..e7b37704f3ea 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -26,8 +26,8 @@ using android::StringPiece; namespace aapt { static ApiVersion sDevelopmentSdkLevel = 10000; -static const auto sDevelopmentSdkCodeNames = - std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"}); +static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>( + {"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake", "VanillaIceCream"}); static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { {0x021c, 1}, diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 0170c4a4c54b..2f5d8d19ebe5 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -206,6 +206,11 @@ class LinkCommand : public Command { AddOptionalFlag("--compile-sdk-version-name", "Version name to inject into the AndroidManifest.xml if none is present.", &options_.manifest_fixer_options.compile_sdk_version_codename); + AddOptionalSwitch( + "--no-compile-sdk-metadata", + "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n" + "including android:compileSdkVersion and platformBuildVersion.", + &options_.manifest_fixer_options.no_compile_sdk_metadata); AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", &shared_lib_); AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_); diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 42191912775a..f8e734724018 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -635,7 +635,7 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { root->InsertChild(0, std::move(uses_sdk)); } - if (options_.compile_sdk_version) { + if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) { xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion"); // Make sure we un-compile the value if it was set to something else. @@ -647,10 +647,9 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { // Make sure we un-compile the value if it was set to something else. attr->compiled_value = {}; attr->value = options_.compile_sdk_version.value(); - } - if (options_.compile_sdk_version_codename) { + if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) { xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename"); diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h index a8707d9d8623..70bfcfc1365a 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -68,11 +68,12 @@ struct ManifestFixerOptions { std::optional<std::string> revision_code_default; // The version of the framework being compiled against to set for 'android:compileSdkVersion' in - // the <manifest> tag. + // the <manifest> tag. Not used if no_compile_sdk_metadata is set. std::optional<std::string> compile_sdk_version; // The version codename of the framework being compiled against to set for - // 'android:compileSdkVersionCodename' in the <manifest> tag. + // 'android:compileSdkVersionCodename' in the <manifest> tag. Not used if no_compile_sdk_metadata + // is set. std::optional<std::string> compile_sdk_version_codename; // Whether validation errors should be treated only as warnings. If this is 'true', then an @@ -85,6 +86,9 @@ struct ManifestFixerOptions { // Whether to replace the manifest version with the the command line version bool replace_version = false; + + // Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes. + bool no_compile_sdk_metadata = false; }; // Verifies that the manifest is correctly formed and inserts defaults where specified with diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 098d0be7f87d..9204d2276a17 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -892,6 +892,35 @@ TEST_F(ManifestFixerTest, InsertCompileSdkVersions) { EXPECT_THAT(attr->value, StrEq("P")); } +TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) { + std::string input = R"(<manifest package="com.pkg" />)"; + ManifestFixerOptions options; + options.no_compile_sdk_metadata = true; + options.compile_sdk_version = {"28"}; + options.compile_sdk_version_codename = {"P"}; + + std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options); + ASSERT_THAT(manifest, NotNull()); + + // There should be a declaration of kSchemaAndroid, even when the input + // didn't have one. + EXPECT_EQ(manifest->root->namespace_decls.size(), 1); + EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android"); + EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid); + + xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute("", "platformBuildVersionCode"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute("", "platformBuildVersionName"); + ASSERT_THAT(attr, IsNull()); +} + TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) { std::string input = R"( <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android" diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index dd266ffe0f16..a2c1d6b4f784 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -383,13 +383,11 @@ static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination if (allDefaults) return false; emptyline(); - int policyCount = 0; printf("Privacy* %s[] = {\n", messageName.c_str()); for (size_t i=0; i<fieldsInOrder.size(); i++) { const FieldDescriptor* field = fieldsInOrder[i]; if (hasDefaultFlags[i]) continue; // NOLINT(clang-analyzer-core.uninitialized.Branch) printf(" &%s,\n", getFieldName(field).c_str()); - policyCount++; } printf(" NULL };\n"); emptyline(); diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt index dcfbe953f955..e03d92ab44a0 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt @@ -72,5 +72,78 @@ val EXCLUDED_CPP_INTERFACES = listOf( "Status", "IThermalService", "IPowerManager", - "ITunerResourceManager" + "ITunerResourceManager", + // b/278147400 + "IActivityManager", + "IUidObserver", + "IDrm", + "IVsyncCallback", + "IVsyncService", + "ICallback", + "IIPCTest", + "ISafeInterfaceTest", + "IGpuService", + "IConsumerListener", + "IGraphicBufferConsumer", + "ITransactionComposerListener", + "SensorEventConnection", + "SensorServer", + "ICamera", + "ICameraClient", + "ICameraRecordingProxy", + "ICameraRecordingProxyListener", + "ICrypto", + "IOMXObserver", + "IStreamListener", + "IStreamSource", + "IAudioService", + "IDataSource", + "IDrmClient", + "IMediaCodecList", + "IMediaDrmService", + "IMediaExtractor", + "IMediaExtractorService", + "IMediaHTTPConnection", + "IMediaHTTPService", + "IMediaLogService", + "IMediaMetadataRetriever", + "IMediaMetricsService", + "IMediaPlayer", + "IMediaPlayerClient", + "IMediaPlayerService", + "IMediaRecorder", + "IMediaRecorderClient", + "IMediaResourceMonitor", + "IMediaSource", + "IRemoteDisplay", + "IRemoteDisplayClient", + "IResourceManagerClient", + "IResourceManagerService", + "IComplexTypeInterface", + "IPermissionController", + "IPingResponder", + "IProcessInfoService", + "ISchedulingPolicyService", + "IStringConstants", + "IObbActionListener", + "IStorageEventListener", + "IStorageManager", + "IStorageShutdownObserver", + "IPersistentVrStateCallbacks", + "IVrManager", + "IVrStateCallbacks", + "ISurfaceComposer", + "IMemory", + "IMemoryHeap", + "IProcfsInspector", + "IAppOpsCallback", + "IAppOpsService", + "IBatteryStats", + "IResultReceiver", + "IShellCallback", + "IDrmManagerService", + "IDrmServiceListener", + "IAAudioClient", + "IAAudioService", + "VtsFuzzer", ) |