diff options
144 files changed, 2002 insertions, 1748 deletions
diff --git a/Android.bp b/Android.bp index 62d2632a8af6..93d1e4e5b020 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", ], } 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/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/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..08ff5348a286 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); 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/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/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/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/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/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/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/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/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/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..6919a76b84ba 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. @@ -1591,7 +1591,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 +1600,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/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/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/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/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/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/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/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/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/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index fe448fccae3a..6748e9cdb52e 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); } } 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/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 93027c1914ee..e7aa176e5d68 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2735,7 +2735,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/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/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/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..0eda49e6b874 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); } } @@ -14666,6 +14668,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 +14901,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/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..d23414485cd6 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. * @@ -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) + 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.keepaliveDelayMs : 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"); @@ -3621,13 +3708,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 +3752,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 +3798,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 +3822,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 +3831,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 +3880,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 +3921,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 +4040,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 +4128,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 +4198,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 +4565,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/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..6a40a3efd30f 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) { } } 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/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/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/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..475966ea00b8 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.getAction() == INTENT_UPLOAD_PROFILES) { + 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); } /** @@ -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/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/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/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/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/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", ) |