diff options
66 files changed, 648 insertions, 152 deletions
diff --git a/api/api.go b/api/api.go index e9f1feebd899..1bbf3709480a 100644 --- a/api/api.go +++ b/api/api.go @@ -514,7 +514,7 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { func combinedApisModuleFactory() android.Module { module := &CombinedApis{} module.AddProperties(&module.properties) - android.InitAndroidModule(module) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) }) return module } diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp index a6e27698e36c..b93227a60d99 100644 --- a/cmds/hid/Android.bp +++ b/cmds/hid/Android.bp @@ -22,5 +22,5 @@ java_binary { name: "hid", wrapper: "hid.sh", srcs: ["**/*.java"], - required: ["libhidcommand_jni"], + jni_libs: ["libhidcommand_jni"], } diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp index da497dcf908e..cec8a0d88b99 100644 --- a/cmds/uinput/Android.bp +++ b/cmds/uinput/Android.bp @@ -25,7 +25,7 @@ java_binary { "src/**/*.java", ":uinputcommand_aidl", ], - required: ["libuinputcommand_jni"], + jni_libs: ["libuinputcommand_jni"], } filegroup { diff --git a/core/api/current.txt b/core/api/current.txt index 67bfdb4c9fd3..e2feb2047d85 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -12163,6 +12163,7 @@ package android.content.pm { method public int getMemtagMode(); method public int getNativeHeapZeroInitialized(); method public int getRequestRawExternalStorageAccess(); + method @FlaggedApi("android.content.pm.audio_playback_capture_allowance") public boolean isAudioPlaybackCaptureAllowed(); method public boolean isProfileable(); method public boolean isProfileableByShell(); method public boolean isResourceOverlay(); @@ -21310,6 +21311,7 @@ package android.media { field public static final int ENCODING_AAC_XHE = 16; // 0x10 field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_AC4 = 17; // 0x11 + field @FlaggedApi("android.media.audio.dolby_ac4_level4_encoding_api") public static final int ENCODING_AC4_L4 = 32; // 0x20 field public static final int ENCODING_DEFAULT = 1; // 0x1 field public static final int ENCODING_DOLBY_MAT = 19; // 0x13 field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe @@ -26813,7 +26815,6 @@ package android.media.session { field public static final int STATE_FAST_FORWARDING = 4; // 0x4 field public static final int STATE_NONE = 0; // 0x0 field public static final int STATE_PAUSED = 2; // 0x2 - field @FlaggedApi("com.android.media.flags.enable_notifying_activity_manager_with_media_session_status_change") public static final int STATE_PLAYBACK_SUPPRESSED = 12; // 0xc field public static final int STATE_PLAYING = 3; // 0x3 field public static final int STATE_REWINDING = 5; // 0x5 field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b384326201fc..eb742faa5835 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -6188,7 +6188,7 @@ public final class ActivityThread extends ClientTransactionHandler } r.activity.mConfigChangeFlags |= configChanges; - r.mPreserveWindow = tmp.mPreserveWindow; + r.mPreserveWindow = r.activity.mWindowAdded && tmp.mPreserveWindow; r.activity.mChangingConfigurations = true; diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 6a599eae7de0..be5309cb3978 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -48,6 +48,9 @@ import android.os.SystemProperties; import android.os.TestLooperManager; import android.os.UserHandle; import android.os.UserManager; +import android.ravenwood.annotation.RavenwoodKeep; +import android.ravenwood.annotation.RavenwoodKeepPartialClass; +import android.ravenwood.annotation.RavenwoodReplace; import android.util.AndroidRuntimeException; import android.util.Log; import android.view.Display; @@ -80,7 +83,7 @@ import java.util.concurrent.TimeoutException; * implementation is described to the system through an AndroidManifest.xml's * <instrumentation> tag. */ -@android.ravenwood.annotation.RavenwoodKeepPartialClass +@RavenwoodKeepPartialClass public class Instrumentation { /** @@ -134,7 +137,7 @@ public class Instrumentation { private UiAutomation mUiAutomation; private final Object mAnimationCompleteLock = new Object(); - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep public Instrumentation() { } @@ -145,7 +148,7 @@ public class Instrumentation { * reflection, but it will serve as noticeable discouragement from * doing such a thing. */ - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep private void checkInstrumenting(String method) { // Check if we have an instrumentation context, as init should only get called by // the system in startup processes that are being instrumented. @@ -160,7 +163,7 @@ public class Instrumentation { * * @hide */ - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep public boolean isInstrumenting() { // Check if we have an instrumentation context, as init should only get called by // the system in startup processes that are being instrumented. @@ -324,7 +327,7 @@ public class Instrumentation { * * @see #getTargetContext */ - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep public Context getContext() { return mInstrContext; } @@ -349,7 +352,7 @@ public class Instrumentation { * * @see #getContext */ - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep public Context getTargetContext() { return mAppContext; } @@ -2405,10 +2408,11 @@ public class Instrumentation { * * @hide */ - @android.ravenwood.annotation.RavenwoodKeep - public final void basicInit(Context instrContext, Context appContext) { + @RavenwoodKeep + public final void basicInit(Context instrContext, Context appContext, UiAutomation ui) { mInstrContext = instrContext; mAppContext = appContext; + mUiAutomation = ui; } /** @hide */ @@ -2499,6 +2503,7 @@ public class Instrumentation { * * @see UiAutomation */ + @RavenwoodKeep public UiAutomation getUiAutomation() { return getUiAutomation(0); } @@ -2537,6 +2542,7 @@ public class Instrumentation { * * @see UiAutomation */ + @RavenwoodReplace public UiAutomation getUiAutomation(@UiAutomationFlags int flags) { boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed()); @@ -2567,11 +2573,15 @@ public class Instrumentation { return null; } + private UiAutomation getUiAutomation$ravenwood(@UiAutomationFlags int flags) { + return mUiAutomation; + } + /** * Takes control of the execution of messages on the specified looper until * {@link TestLooperManager#release} is called. */ - @android.ravenwood.annotation.RavenwoodKeep + @RavenwoodKeep public TestLooperManager acquireLooperManager(Looper looper) { checkInstrumenting("acquireLooperManager"); return new TestLooperManager(looper); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 495ae6026805..08ca33bafce5 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -2327,9 +2327,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Whether an app allows its playback audio to be captured by other apps. * * @return {@code true} if the app indicates that its audio can be captured by other apps. - * - * @hide */ + @FlaggedApi(Flags.FLAG_AUDIO_PLAYBACK_CAPTURE_ALLOWANCE) public boolean isAudioPlaybackCaptureAllowed() { return (privateFlags & PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE) != 0; } diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index d9b0e6dd2681..f332f7b4fc99 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -283,4 +283,13 @@ flag { namespace: "package_manager_service" description: "Feature flag to enable the feature to retrieve package info without installation with a file descriptor." bug: "340879905" +} + +flag { + name: "audio_playback_capture_allowance" + is_exported: true + namespace: "package_manager_service" + description: "Feature flag to enable the feature to retrieve info about audio playback capture allowance at manifest level." + bug: "362425551" + is_fixed_read_only: true }
\ No newline at end of file diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 43d3f5466ccf..f11625ed9d61 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -19,3 +19,6 @@ per-file DataSpace* = file:/graphics/java/android/graphics/OWNERS # OverlayProperties per-file OverlayProperties* = file:/graphics/java/android/graphics/OWNERS + +# Lut related files +per-file *Lut* = file:/graphics/java/android/graphics/OWNERS
\ No newline at end of file diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 7d3076d6611f..a1b75034442e 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -115,3 +115,10 @@ per-file OomKillRecord.java = file:/MEMORY_OWNERS # MessageQueue per-file MessageQueue.java = mfasheh@google.com, shayba@google.com per-file Message.java = mfasheh@google.com, shayba@google.com + +# Stats +per-file IStatsBootstrapAtomService.aidl = file:/services/core/java/com/android/server/stats/OWNERS +per-file StatsBootstrapAtom.aidl = file:/services/core/java/com/android/server/stats/OWNERS +per-file StatsBootstrapAtomValue.aidl = file:/services/core/java/com/android/server/stats/OWNERS +per-file StatsBootstrapAtomService.java = file:/services/core/java/com/android/server/stats/OWNERS +per-file StatsServiceManager.java = file:/services/core/java/com/android/server/stats/OWNERS diff --git a/core/java/android/os/StatsBootstrapAtomValue.aidl b/core/java/android/os/StatsBootstrapAtomValue.aidl index a90dfa404ee9..b59bc062648f 100644 --- a/core/java/android/os/StatsBootstrapAtomValue.aidl +++ b/core/java/android/os/StatsBootstrapAtomValue.aidl @@ -26,4 +26,5 @@ union StatsBootstrapAtomValue { float floatValue; String stringValue; byte[] bytesValue; + String[] stringArrayValue; }
\ No newline at end of file diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 23bd30a21c4c..d0c23becc45e 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -60,7 +60,7 @@ import java.time.ZoneOffset; * sleep (CPU off, display dark, device waiting for external input), * but is not affected by clock scaling, idle, or other power saving * mechanisms. This is the basis for most interval timing - * such as {@link Thread#sleep(long) Thread.sleep(millls)}, + * such as {@link Thread#sleep(long) Thread.sleep(millis)}, * {@link Object#wait(long) Object.wait(millis)}, and * {@link System#nanoTime System.nanoTime()}. This clock is guaranteed * to be monotonic, and is suitable for interval timing when the diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index a86c961e6785..aedf8e097e67 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -106,3 +106,10 @@ flag { description: "Clear StrongAuth on add credential" bug: "320817991" } + +flag { + name: "afl_api" + namespace: "platform_security" + description: "AFL feature" + bug: "365994454" +} diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 11ee286652a1..0a39389556d5 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -860,7 +860,7 @@ public final class InputMethodInfo implements Parcelable { * <p>e.g.<pre><code>startActivity(createStylusHandwritingSettingsActivityIntent());</code> * </pre></p> * - * @attr ref R.styleable#InputMethod_stylusHandwritingSettingsActivity + * @attr ref android.R.styleable#InputMethod_stylusHandwritingSettingsActivity * @see #getSettingsActivity() * @see #supportsStylusHandwriting() */ @@ -886,7 +886,7 @@ public final class InputMethodInfo implements Parcelable { * the IME language settings activity.</p> * <p>e.g.<pre><code>startActivity(createImeLanguageSettingsActivityIntent());</code></pre></p> * - * @attr ref R.styleable#InputMethod_languageSettingsActivity + * @attr ref android.R.styleable#InputMethod_languageSettingsActivity */ @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP) @Nullable diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 510a92d1b2ca..3f611c7efbdd 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -3636,7 +3636,7 @@ public class ListView extends AbsListView { * Returns the drawable that will be drawn between each item in the list. * * @return the current drawable drawn between list elements - * @attr ref R.styleable#ListView_divider + * @attr ref android.R.styleable#ListView_divider */ @InspectableProperty @Nullable @@ -3651,7 +3651,7 @@ public class ListView extends AbsListView { * height, you should also call {@link #setDividerHeight(int)}. * * @param divider the drawable to use - * @attr ref R.styleable#ListView_divider + * @attr ref android.R.styleable#ListView_divider */ public void setDivider(@Nullable Drawable divider) { if (divider != null) { diff --git a/core/java/android/window/OWNERS b/core/java/android/window/OWNERS index 2c61df96eb03..77c99b98cf4a 100644 --- a/core/java/android/window/OWNERS +++ b/core/java/android/window/OWNERS @@ -1,3 +1,5 @@ set noparent include /services/core/java/com/android/server/wm/OWNERS + +per-file DesktopModeFlags.java = file:/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS diff --git a/core/jni/OWNERS b/core/jni/OWNERS index af106235bd77..af393fdc5ad4 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -119,3 +119,4 @@ per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/O # ApplicationSharedMemory per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS +per-file *PropertyInvalidatedCache* = file:/PERFORMANCE_OWNERS diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index a9b19062b764..704aef3cd131 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -50,6 +50,7 @@ #define ENCODING_DTS_HD_MA 29 #define ENCODING_DTS_UHD_P2 30 #define ENCODING_DSD 31 +#define ENCODING_AC4_L4 32 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -95,6 +96,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_XHE; case ENCODING_AC4: return AUDIO_FORMAT_AC4; + case ENCODING_AC4_L4: + return AUDIO_FORMAT_AC4_L4; case ENCODING_E_AC3_JOC: return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: @@ -177,6 +180,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + case AUDIO_FORMAT_AC4_L4: + return ENCODING_AC4_L4; case AUDIO_FORMAT_E_AC3_JOC: return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_MAT: diff --git a/core/jni/android_view_WindowManagerGlobal.cpp b/core/jni/android_view_WindowManagerGlobal.cpp index abc621d8dc90..4202de39adb0 100644 --- a/core/jni/android_view_WindowManagerGlobal.cpp +++ b/core/jni/android_view_WindowManagerGlobal.cpp @@ -69,8 +69,8 @@ void removeInputChannel(const sp<IBinder>& clientToken) { JNIEnv* env = AndroidRuntime::getJNIEnv(); ScopedLocalRef<jobject> clientTokenObj(env, javaObjectForIBinder(env, clientToken)); - env->CallStaticObjectMethod(gWindowManagerGlobal.clazz, gWindowManagerGlobal.removeInputChannel, - clientTokenObj.get()); + env->CallStaticVoidMethod(gWindowManagerGlobal.clazz, gWindowManagerGlobal.removeInputChannel, + clientTokenObj.get()); } int register_android_view_WindowManagerGlobal(JNIEnv* env) { @@ -88,4 +88,4 @@ int register_android_view_WindowManagerGlobal(JNIEnv* env) { return NO_ERROR; } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 00be9fe564da..376118c8122c 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1529,6 +1529,11 @@ factory reset. --> <bool name="config_enableCredentialFactoryResetProtection">true</bool> + <!-- If true, then work around broken Weaver HALs that don't work reliably before the device has + fully booted. Setting this to true weakens a security feature; it should be done only when + necessary, though it is still better than not using Weaver at all. --> + <bool name="config_disableWeaverOnUnsecuredUsers">false</bool> + <!-- Control the behavior when the user long presses the home button. 0 - Nothing 1 - Launch all apps intent diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 06a4d550b204..9ab8ad83480e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3958,6 +3958,7 @@ <java-symbol type="string" name="foreground_service_multiple_separator" /> <java-symbol type="bool" name="config_enableCredentialFactoryResetProtection" /> + <java-symbol type="bool" name="config_disableWeaverOnUnsecuredUsers" /> <!-- ETWS primary messages --> <java-symbol type="string" name="etws_primary_default_message_earthquake" /> diff --git a/keystore/OWNERS b/keystore/OWNERS index 689177715711..ea783e7f0c06 100644 --- a/keystore/OWNERS +++ b/keystore/OWNERS @@ -1,5 +1,6 @@ # Bug component: 189335 +ascull@google.com drysdale@google.com -eranm@google.com jbires@google.com +sethmo@google.com swillden@google.com diff --git a/location/lib/Android.bp b/location/lib/Android.bp index b10019a94209..67d57749c894 100644 --- a/location/lib/Android.bp +++ b/location/lib/Android.bp @@ -29,6 +29,10 @@ java_sdk_library { libs: [ "androidx.annotation_annotation", ], + stub_only_libs: [ + // Needed for javadoc references. + "framework-location.stubs.system", + ], api_packages: [ "android.location", "com.android.location.provider", diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index c90c44152440..0da8371bc824 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -16,6 +16,9 @@ package android.media; +import static android.media.audio.Flags.FLAG_DOLBY_AC4_LEVEL4_ENCODING_API; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -309,7 +312,7 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_AAC_ELD = 15; /** Audio data format: AAC xHE compressed */ public static final int ENCODING_AAC_XHE = 16; - /** Audio data format: AC-4 sync frame transport format */ + /** Audio data format: AC-4 (levels 0-3) sync frame transport format */ public static final int ENCODING_AC4 = 17; /** Audio data format: E-AC-3-JOC compressed * E-AC-3-JOC streams can be decoded by downstream devices supporting {@link #ENCODING_E_AC3}. @@ -375,6 +378,9 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_DTS_UHD_P2 = 30; /** Audio data format: Direct Stream Digital */ public static final int ENCODING_DSD = 31; + /** Audio data format: AC-4 level 4 sync frame transport format */ + @FlaggedApi(FLAG_DOLBY_AC4_LEVEL4_ENCODING_API) + public static final int ENCODING_AC4_L4 = 32; /** @hide */ public static String toLogFriendlyEncoding(int enc) { @@ -413,6 +419,8 @@ public final class AudioFormat implements Parcelable { return "ENCODING_AAC_XHE"; case ENCODING_AC4: return "ENCODING_AC4"; + case ENCODING_AC4_L4: + return "ENCODING_AC4_L4"; case ENCODING_E_AC3_JOC: return "ENCODING_E_AC3_JOC"; case ENCODING_DOLBY_MAT: @@ -823,6 +831,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -863,6 +872,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -908,6 +918,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -950,6 +961,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -1238,6 +1250,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -1468,6 +1481,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_OPUS, @@ -1506,6 +1520,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_OPUS, @@ -1533,6 +1548,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_LC, ENCODING_DOLBY_TRUEHD, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_MPEGH_BL_L3, @@ -1554,6 +1570,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_LC, ENCODING_DOLBY_TRUEHD, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_MPEGH_BL_L3, @@ -1592,7 +1609,9 @@ public final class AudioFormat implements Parcelable { case ENCODING_DOLBY_TRUEHD: return "Dolby TrueHD"; case ENCODING_AC4: - return "Dolby AC-4"; + return "Dolby AC-4 levels 0-3"; + case ENCODING_AC4_L4: + return "Dolby AC-4 level 4"; case ENCODING_E_AC3_JOC: return "Dolby Atmos in Dolby Digital Plus"; case ENCODING_DOLBY_MAT: diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 2d0e7abbe890..7b8702fd5271 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -542,6 +542,8 @@ public class AudioSystem return "AUDIO_FORMAT_AAC_LATM_HE_V2"; // (AAC_LATM | AAC_SUB_HE_V2) case /* AUDIO_FORMAT_E_AC3_JOC */ 0xA000001: return "AUDIO_FORMAT_E_AC3_JOC"; // (E_AC3 | E_AC3_SUB_JOC) + case /* AUDIO_FORMAT_AC4_L4 */ 0x22000001: + return "AUDIO_FORMAT_AC4_L4"; // (AC4 | AC4_SUB_L4) case /* AUDIO_FORMAT_MAT_1_0 */ 0x24000001: return "AUDIO_FORMAT_MAT_1_0"; // (MAT | MAT_SUB_1_0) case /* AUDIO_FORMAT_MAT_2_0 */ 0x24000002: diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java index 80b606c9ec9e..5e55f64da985 100644 --- a/media/java/android/media/MediaMuxer.java +++ b/media/java/android/media/MediaMuxer.java @@ -34,7 +34,7 @@ import java.util.Map; /** * MediaMuxer facilitates muxing elementary streams. Currently MediaMuxer supports MP4, Webm - * and 3GP file as the output. It also supports muxing B-frames in MP4 since Android Nougat. + * and 3GP file as the output. It also supports muxing B-frames in MP4 since Android Nougat MR1. * <p> * It is generally used like this: * @@ -191,14 +191,14 @@ import java.util.Map; <td>○</td> <td>●</td> </tr> - <td align="center">Muxing B-Frames(bi-directional predicted frames)</td> + <td align="center">Muxing B-Frames (bi-directional predicted frames)</td> + <td>○</td> <td>○</td> <td>○</td> <td>○</td> <td>○</td> <td>○</td> <td>○</td> - <td>⁕</td> <td>⁕</td> <td>⁕</td> </tr> diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 47637b82111a..290d49b31eb7 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -15,10 +15,8 @@ */ package android.media.session; -import static com.android.media.flags.Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE; import android.annotation.DrawableRes; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.LongDef; import android.annotation.Nullable; @@ -187,13 +185,21 @@ public final class PlaybackState implements Parcelable { */ public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; - /** - * @hide - */ - @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, - STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING, - STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM, - STATE_PLAYBACK_SUPPRESSED}) + /** @hide */ + @IntDef({ + STATE_NONE, + STATE_STOPPED, + STATE_PAUSED, + STATE_PLAYING, + STATE_FAST_FORWARDING, + STATE_REWINDING, + STATE_BUFFERING, + STATE_ERROR, + STATE_CONNECTING, + STATE_SKIPPING_TO_PREVIOUS, + STATE_SKIPPING_TO_NEXT, + STATE_SKIPPING_TO_QUEUE_ITEM + }) @Retention(RetentionPolicy.SOURCE) public @interface State {} @@ -290,19 +296,6 @@ public final class PlaybackState implements Parcelable { public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11; /** - * State indicating that playback is paused due to an external transient interruption, like a - * phone call. - * - * <p>This state is different from {@link #STATE_PAUSED} in that it is deemed transitory, - * possibly allowing the service associated to the session in this state to run in the - * foreground. - * - * @see Builder#setState - */ - @FlaggedApi(FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE) - public static final int STATE_PLAYBACK_SUPPRESSED = 12; - - /** * Use this value for the position to indicate the position is not known. */ public static final long PLAYBACK_POSITION_UNKNOWN = -1; @@ -401,7 +394,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> */ @State @@ -525,7 +517,6 @@ public final class PlaybackState implements Parcelable { * <li>{@link #STATE_SKIPPING_TO_NEXT}</li> * <li>{@link #STATE_SKIPPING_TO_PREVIOUS}</li> * <li>{@link #STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li>{@link #STATE_PLAYBACK_SUPPRESSED}</li> * </ul> */ public boolean isActive() { @@ -538,7 +529,6 @@ public final class PlaybackState implements Parcelable { case PlaybackState.STATE_BUFFERING: case PlaybackState.STATE_CONNECTING: case PlaybackState.STATE_PLAYING: - case PlaybackState.STATE_PLAYBACK_SUPPRESSED: return true; } return false; @@ -584,8 +574,6 @@ public final class PlaybackState implements Parcelable { return "SKIPPING_TO_NEXT"; case STATE_SKIPPING_TO_QUEUE_ITEM: return "SKIPPING_TO_QUEUE_ITEM"; - case STATE_PLAYBACK_SUPPRESSED: - return "STATE_PLAYBACK_SUPPRESSED"; default: return "UNKNOWN"; } @@ -823,7 +811,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> * * @param state The current state of playback. @@ -868,7 +855,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> * * @param state The current state of playback. diff --git a/nfc/Android.bp b/nfc/Android.bp index db3dcb0631dd..7ad8c4c8de41 100644 --- a/nfc/Android.bp +++ b/nfc/Android.bp @@ -41,6 +41,10 @@ java_sdk_library { "framework-permission-s.stubs.module_lib", "framework-permission.stubs.module_lib", ], + stub_only_libs: [ + // Needed for javadoc references. + "framework-permission-s.stubs.module_lib", + ], static_libs: [ "android.nfc.flags-aconfig-java", "android.permission.flags-aconfig-java", diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java index 947746c94198..4b2fe49c41b4 100644 --- a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java @@ -45,8 +45,8 @@ import java.io.IOException; * This class should only be used in XML. * * @attr ref android.R.styleable#DrawableWrapper_drawable - * @attr ref R.styleable#AlphaTintDrawableWrapper_tint - * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha + * @attr ref android.R.styleable#AlphaTintDrawableWrapper_tint + * @attr ref android.R.styleable#AlphaTintDrawableWrapper_alpha */ public class AlphaTintDrawableWrapper extends InsetDrawable { private ColorStateList mTint; diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index 11b66fc3f1e5..9629a87c1057 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -154,6 +154,8 @@ java_library { "framework-annotations-lib", "ravenwood-helper-framework-runtime", "ravenwood-helper-libcore-runtime", + "hoststubgen-helper-runtime.ravenwood", + "mockito-ravenwood-prebuilt", ], visibility: ["//frameworks/base"], jarjar_rules: ":ravenwood-services-jarjar-rules", diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING index 86246e2dcc2a..72f62c5c29ee 100644 --- a/ravenwood/TEST_MAPPING +++ b/ravenwood/TEST_MAPPING @@ -5,7 +5,8 @@ { "name": "hoststubgen-test-tiny-test" }, { "name": "hoststubgen-invoke-test" }, { "name": "RavenwoodMockitoTest_device" }, - { "name": "RavenwoodBivalentTest_device" }, + // TODO(b/371215487): Re-enable when the test is fixed. + // { "name": "RavenwoodBivalentTest_device" }, { "name": "RavenwoodBivalentInstTest_nonself_inst" }, { "name": "RavenwoodBivalentInstTest_self_inst_device" }, diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index 805b0c161cb3..5894476b9201 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -21,9 +21,15 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOUR import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + import android.app.ActivityManager; import android.app.Instrumentation; import android.app.ResourcesManager; +import android.app.UiAutomation; import android.content.res.Resources; import android.os.Binder; import android.os.Build; @@ -38,6 +44,7 @@ import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.hoststubgen.hosthelper.HostTestUtils; import com.android.internal.os.RuntimeInit; import com.android.ravenwood.RavenwoodRuntimeNative; import com.android.ravenwood.common.RavenwoodCommonUtils; @@ -50,8 +57,10 @@ import org.junit.runner.Description; import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.util.Collections; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -123,6 +132,9 @@ public class RavenwoodRuntimeEnvironmentController { private static RavenwoodConfig sConfig; private static RavenwoodSystemProperties sProps; + // TODO: use the real UiAutomation class instead of a mock + private static UiAutomation sMockUiAutomation; + private static Set<String> sAdoptedPermissions = Collections.emptySet(); private static boolean sInitialized = false; /** @@ -167,6 +179,9 @@ public class RavenwoodRuntimeEnvironmentController { // This will let AndroidJUnit4 use the original runner. System.setProperty("android.junit.runner", "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); + + assertMockitoVersion(); + sMockUiAutomation = createMockUiAutomation(); } /** @@ -257,7 +272,7 @@ public class RavenwoodRuntimeEnvironmentController { // Prepare other fields. config.mInstrumentation = new Instrumentation(); - config.mInstrumentation.basicInit(config.mInstContext, config.mTargetContext); + config.mInstrumentation.basicInit(instContext, targetContext, sMockUiAutomation); InstrumentationRegistry.registerInstance(config.mInstrumentation, Bundle.EMPTY); RavenwoodSystemServer.init(config); @@ -296,12 +311,13 @@ public class RavenwoodRuntimeEnvironmentController { config.mInstrumentation = null; if (config.mInstContext != null) { ((RavenwoodContext) config.mInstContext).cleanUp(); + config.mInstContext = null; } if (config.mTargetContext != null) { ((RavenwoodContext) config.mTargetContext).cleanUp(); + config.mTargetContext = null; } - config.mInstContext = null; - config.mTargetContext = null; + sMockUiAutomation.dropShellPermissionIdentity(); if (config.mProvideMainThread) { Looper.getMainLooper().quit(); @@ -381,6 +397,53 @@ public class RavenwoodRuntimeEnvironmentController { } } + private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" + + " Your test or its dependencies use one of the \"mockito-target-*\"" + + " modules as static library, which is unusable on host side." + + " Please switch over to use \"mockito-ravenwood-prebuilt\" as shared library, or" + + " as a last resort, set `ravenizer: { strip_mockito: true }` in your test module."; + + /** + * Assert the Mockito version at runtime to ensure no incorrect Mockito classes are loaded. + */ + private static void assertMockitoVersion() { + // DexMaker should not exist + assertThrows( + MOCKITO_ERROR, + ClassNotFoundException.class, + () -> Class.forName("com.android.dx.DexMaker")); + // Mockito 2 should not exist + assertThrows( + MOCKITO_ERROR, + ClassNotFoundException.class, + () -> Class.forName("org.mockito.Matchers")); + } + + private static UiAutomation createMockUiAutomation() { + var mock = mock(UiAutomation.class, inv -> { + HostTestUtils.onThrowMethodCalled(); + return null; + }); + doAnswer(inv -> { + sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS; + return null; + }).when(mock).adoptShellPermissionIdentity(); + doAnswer(inv -> { + if (inv.getArgument(0) == null) { + sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS; + } else { + sAdoptedPermissions = (Set) Set.of(inv.getArguments()); + } + return null; + }).when(mock).adoptShellPermissionIdentity(any()); + doAnswer(inv -> { + sAdoptedPermissions = Collections.emptySet(); + return null; + }).when(mock).dropShellPermissionIdentity(); + doAnswer(inv -> sAdoptedPermissions).when(mock).getAdoptedShellPermissions(); + return mock; + } + @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { boolean result = write ? sProps.isKeyWritable(key) : sProps.isKeyReadable(key); diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodUiAutomationTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodUiAutomationTest.java new file mode 100644 index 000000000000..eb948279109b --- /dev/null +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodUiAutomationTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 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.ravenwoodtest.bivalenttest; + +import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; +import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import android.app.Instrumentation; +import android.app.UiAutomation; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.ravenwood.common.RavenwoodCommonUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Set; + +@RunWith(AndroidJUnit4.class) +public class RavenwoodUiAutomationTest { + + private Instrumentation mInstrumentation; + + @Before + public void setup() { + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + } + + @Test + public void testGetUiAutomation() { + assertNotNull(mInstrumentation.getUiAutomation()); + } + + @Test + public void testGetUiAutomationWithFlags() { + assertNotNull(mInstrumentation.getUiAutomation(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY)); + } + + @Test + public void testShellPermissionApis() { + var uiAutomation = mInstrumentation.getUiAutomation(); + assertTrue(uiAutomation.getAdoptedShellPermissions().isEmpty()); + uiAutomation.adoptShellPermissionIdentity(); + assertEquals(uiAutomation.getAdoptedShellPermissions(), UiAutomation.ALL_PERMISSIONS); + uiAutomation.adoptShellPermissionIdentity((String[]) null); + assertEquals(uiAutomation.getAdoptedShellPermissions(), UiAutomation.ALL_PERMISSIONS); + uiAutomation.adoptShellPermissionIdentity( + OVERRIDE_COMPAT_CHANGE_CONFIG, READ_COMPAT_CHANGE_CONFIG); + assertEquals(uiAutomation.getAdoptedShellPermissions(), + Set.of(OVERRIDE_COMPAT_CHANGE_CONFIG, READ_COMPAT_CHANGE_CONFIG)); + uiAutomation.dropShellPermissionIdentity(); + assertTrue(uiAutomation.getAdoptedShellPermissions().isEmpty()); + } + + @Test + public void testUnsupportedMethod() { + // Only unsupported on Ravenwood + assumeTrue(RavenwoodCommonUtils.isOnRavenwood()); + assertThrows(RuntimeException.class, + () -> mInstrumentation.getUiAutomation().executeShellCommand("echo ok")); + } +} diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java index dd6d259d5a34..31884b6bfc57 100644 --- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java @@ -16,11 +16,19 @@ package com.android.ravenwoodtest.coretest; import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; import org.junit.Test; public class RavenwoodMockitoTest { + private static class MockClass { + void foo() { + throw new RuntimeException("Unsupported!!"); + } + } + @Test public void checkMockitoClasses() { // DexMaker should not exist @@ -32,4 +40,11 @@ public class RavenwoodMockitoTest { ClassNotFoundException.class, () -> Class.forName("org.mockito.Matchers")); } + + @Test + public void checkMockitoActuallyWorks() { + var mock = mock(MockClass.class); + doNothing().when(mock).foo(); + mock.foo(); + } } diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt index 49f0b599762f..e67c730df069 100644 --- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt +++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt @@ -127,7 +127,7 @@ class Ravenizer { } } if (includeUnsupportedMockito(allClasses)) { - log.w("Unsupported Mockito detected in $inJar}!") + log.w("Unsupported Mockito detected in $inJar!") } stats.totalProcessTime = log.vTime("$executableName processing $inJar") { diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcController.java b/services/core/java/com/android/server/hdmi/HdmiEarcController.java index 46a8f039584b..1c947e9d626d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiEarcController.java +++ b/services/core/java/com/android/server/hdmi/HdmiEarcController.java @@ -87,8 +87,8 @@ final class HdmiEarcController { } catch (ServiceSpecificException sse) { HdmiLogger.error( "Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode); - } catch (RemoteException re) { - HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", e); } } @@ -96,8 +96,8 @@ final class HdmiEarcController { public boolean nativeIsEarcEnabled() { try { return mEarc.isEArcEnabled(); - } catch (RemoteException re) { - HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not read if eARC is enabled. Exception: ", e); return false; } } @@ -107,8 +107,8 @@ final class HdmiEarcController { mEarcCallback = callback; try { mEarc.setCallback(callback); - } catch (RemoteException re) { - HdmiLogger.error("Could not set callback. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not set callback. Exception: ", e); } } @@ -116,8 +116,8 @@ final class HdmiEarcController { public byte nativeGetState(int portId) { try { return mEarc.getState(portId); - } catch (RemoteException re) { - HdmiLogger.error("Could not get eARC state. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not get eARC state. Exception: ", e); return -1; } } @@ -126,9 +126,9 @@ final class HdmiEarcController { public byte[] nativeGetLastReportedAudioCapabilities(int portId) { try { return mEarc.getLastReportedAudioCapabilities(portId); - } catch (RemoteException re) { + } catch (RemoteException | NullPointerException e) { HdmiLogger.error( - "Could not read last reported audio capabilities. Exception: ", re); + "Could not read last reported audio capabilities. Exception: ", e); return null; } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 3780fbd61e79..bbdac5636fa4 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -99,6 +99,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ShellCallback; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -126,6 +127,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.LongSparseArray; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -253,6 +255,8 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String MIGRATED_KEYSTORE_NS = "migrated_keystore_namespace"; private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce"; private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys"; + private static final String MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS = + "migrated_weaver_disabled_on_unsecured_users"; // Duration that LockSettingsService will store the gatekeeper password for. This allows // multiple biometric enrollments without prompting the user to enter their password via @@ -309,6 +313,10 @@ public class LockSettingsService extends ILockSettings.Stub { @GuardedBy("mUserCreationAndRemovalLock") private boolean mThirdPartyAppsStarted; + // This list contains the (protectorId, userId) of any protectors that were by replaced by a + // migration and should be destroyed once rollback to the old build is no longer possible. + private ArrayList<Pair<Long, Integer>> mProtectorsToDestroyOnBootCompleted = new ArrayList<>(); + // Current password metrics for all secured users on the device. Updated when user unlocks the // device or changes password. Removed if user is stopped with its CE key evicted. @GuardedBy("this") @@ -363,6 +371,10 @@ public class LockSettingsService extends ILockSettings.Stub { mLockSettingsService.migrateOldDataAfterSystemReady(); mLockSettingsService.deleteRepairModePersistentDataIfNeeded(); } else if (phase == PHASE_BOOT_COMPLETED) { + // In the case of an upgrade, PHASE_BOOT_COMPLETED means that a rollback to the old + // build can no longer occur. This is the time to destroy any migrated protectors. + mLockSettingsService.destroyMigratedProtectors(); + mLockSettingsService.loadEscrowData(); } } @@ -1076,6 +1088,11 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage.deleteRepairModePersistentData(); } + private boolean isWeaverDisabledOnUnsecuredUsers() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers); + } + // This is called when Weaver is guaranteed to be available (if the device supports Weaver). // It does any synthetic password related work that was delayed from earlier in the boot. private void onThirdPartyAppsStarted() { @@ -1114,13 +1131,20 @@ public class LockSettingsService extends ILockSettings.Stub { // // - Upgrading from Android 14, where unsecured users didn't have Keystore super keys. // + // - Upgrading from a build with config_disableWeaverOnUnsecuredUsers=false to one with + // config_disableWeaverOnUnsecuredUsers=true. (We don't bother to proactively add + // Weaver for the reverse update to false, as it's too late to help in that case.) + // // The end result is that all users, regardless of whether they are secured or not, have - // a synthetic password with all keys initialized and protected by it. + // a synthetic password with all keys initialized and protected by it, and honoring + // config_disableWeaverOnUnsecuredUsers=true when applicable. // // Note: if this migration gets interrupted (e.g. by the device powering off), there // shouldn't be a problem since this will run again on the next boot, and // setCeStorageProtection() and initKeystoreSuperKeys(..., true) are idempotent. - if (!getBoolean(MIGRATED_SP_FULL, false, 0)) { + if (!getBoolean(MIGRATED_SP_FULL, false, 0) + || (isWeaverDisabledOnUnsecuredUsers() + && !getBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, false, 0))) { for (UserInfo user : mUserManager.getAliveUsers()) { removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); synchronized (mSpManager) { @@ -1128,6 +1152,9 @@ public class LockSettingsService extends ILockSettings.Stub { } } setBoolean(MIGRATED_SP_FULL, true, 0); + if (isWeaverDisabledOnUnsecuredUsers()) { + setBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, true, 0); + } } mThirdPartyAppsStarted = true; @@ -1151,13 +1178,61 @@ public class LockSettingsService extends ILockSettings.Stub { getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, null); SyntheticPassword sp = result.syntheticPassword; - if (sp == null) { + if (isWeaverDisabledOnUnsecuredUsers()) { + Slog.i(TAG, "config_disableWeaverOnUnsecuredUsers=true"); + + // If config_disableWeaverOnUnsecuredUsers=true, then the Weaver HAL may be buggy and + // need multiple retries before it works here to unwrap the SP, if the SP was already + // protected by Weaver. Note that the problematic HAL can also deadlock if called with + // the ActivityManagerService lock held, but that should not be a problem here since + // that lock isn't held here, unlike unlockUserKeyIfUnsecured() where it is. + for (int i = 0; i < 12 && sp == null; i++) { + Slog.e(TAG, "Failed to unwrap synthetic password. Waiting 5 seconds to retry."); + SystemClock.sleep(5000); + result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId, + LockscreenCredential.createNone(), userId, null); + sp = result.syntheticPassword; + } + if (sp == null) { + throw new IllegalStateException( + "Failed to unwrap synthetic password for unsecured user"); + } + // If the SP is protected by Weaver, then remove the Weaver protection in order to make + // config_disableWeaverOnUnsecuredUsers=true take effect. + if (result.usedWeaver) { + Slog.i(TAG, "Removing Weaver protection from the synthetic password"); + // Create a new protector, which will not use Weaver. + long newProtectorId = mSpManager.createLskfBasedProtector( + getGateKeeperService(), LockscreenCredential.createNone(), sp, userId); + + // Out of paranoia, make sure the new protector really works. + result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), + newProtectorId, LockscreenCredential.createNone(), userId, null); + sp = result.syntheticPassword; + if (sp == null) { + throw new IllegalStateException("New SP protector does not work"); + } + + // Replace the protector. Wait until PHASE_BOOT_COMPLETED to destroy the old + // protector, since the Weaver slot erasure and freeing cannot be rolled back. + setCurrentLskfBasedProtectorId(newProtectorId, userId); + mProtectorsToDestroyOnBootCompleted.add(new Pair(protectorId, userId)); + } else { + Slog.i(TAG, "Synthetic password is already not protected by Weaver"); + } + } else if (sp == null) { Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId); return; } - // While setCeStorageProtection() is idempotent, it does log some error messages when called - // again. Skip it if we know it was already handled by an earlier upgrade to Android 14. - if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { + + // Call setCeStorageProtection(), to re-encrypt the CE key with the SP if it's currently + // encrypted by an empty secret. Skip this if it was definitely already done as part of the + // upgrade to Android 14, since while setCeStorageProtection() is idempotent it does log + // some error messages when called again. Do not skip this if + // config_disableWeaverOnUnsecuredUsers=true, since in that case we'd like to recover from + // the case where an earlier upgrade to Android 14 incorrectly skipped this step. + if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null + || isWeaverDisabledOnUnsecuredUsers()) { Slogf.i(TAG, "Encrypting CE key of user %d with synthetic password", userId); setCeStorageProtection(userId, sp); } @@ -1165,6 +1240,17 @@ public class LockSettingsService extends ILockSettings.Stub { initKeystoreSuperKeys(userId, sp, /* allowExisting= */ true); } + private void destroyMigratedProtectors() { + if (!mProtectorsToDestroyOnBootCompleted.isEmpty()) { + synchronized (mSpManager) { + for (Pair<Long, Integer> pair : mProtectorsToDestroyOnBootCompleted) { + mSpManager.destroyLskfBasedProtector(pair.first, pair.second); + } + } + } + mProtectorsToDestroyOnBootCompleted = null; // The list is no longer needed. + } + /** * Returns the lowest password quality that still presents the same UI for entering it. * diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 3a429b041b3c..47788f2e7d2f 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -195,6 +195,8 @@ class SyntheticPasswordManager { // ERROR: password / token fails verification // RETRY: password / token verification is throttled at the moment. @Nullable public VerifyCredentialResponse gkResponse; + // For unlockLskfBasedProtector() this is set to true if the protector uses Weaver. + public boolean usedWeaver; } /** @@ -532,6 +534,11 @@ class SyntheticPasswordManager { Settings.Global.DEVICE_PROVISIONED, 0) != 0; } + private boolean isWeaverDisabledOnUnsecuredUsers() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers); + } + @VisibleForTesting protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException { try { @@ -1011,7 +1018,13 @@ class SyntheticPasswordManager { Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId); - final IWeaver weaver = getWeaverService(); + final IWeaver weaver; + if (credential.isNone() && isWeaverDisabledOnUnsecuredUsers()) { + weaver = null; + Slog.w(TAG, "Not using Weaver for unsecured user (disabled by config)"); + } else { + weaver = getWeaverService(); + } if (weaver != null) { // Weaver is available, so make the protector use it to verify the LSKF. Do this even // if the LSKF is empty, as that gives us support for securely deleting the protector. @@ -1404,6 +1417,7 @@ class SyntheticPasswordManager { int weaverSlot = loadWeaverSlot(protectorId, userId); if (weaverSlot != INVALID_WEAVER_SLOT) { // Protector uses Weaver to verify the LSKF + result.usedWeaver = true; final IWeaver weaver = getWeaverService(); if (weaver == null) { Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable"); diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java index c02b103f1d33..404c8411f750 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java @@ -19,7 +19,6 @@ package com.android.server.locksettings.recoverablekeystore.storage; import android.annotation.Nullable; import android.os.Environment; import android.security.keystore.recovery.KeyChainSnapshot; -import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; @@ -29,9 +28,11 @@ import com.android.server.locksettings.recoverablekeystore.serialization import com.android.server.locksettings.recoverablekeystore.serialization .KeyChainSnapshotParserException; import com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSerializer; +import com.android.server.utils.Slogf; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.cert.CertificateEncodingException; @@ -81,12 +82,14 @@ public class RecoverySnapshotStorage { public synchronized void put(int uid, KeyChainSnapshot snapshot) { mSnapshotByUid.put(uid, snapshot); - try { - writeToDisk(uid, snapshot); + File snapshotFile = getSnapshotFile(uid); + try (FileOutputStream fileOutputStream = new FileOutputStream(snapshotFile)) { + KeyChainSnapshotSerializer.serialize(snapshot, fileOutputStream); } catch (IOException | CertificateEncodingException e) { - Log.e(TAG, - String.format(Locale.US, "Error persisting snapshot for %d to disk", uid), - e); + // If we fail to write the latest snapshot, we should delete any older snapshot that + // happens to be around. Otherwise snapshot syncs might end up going 'back in time'. + snapshotFile.delete(); + Slogf.e(TAG, e, "Error persisting snapshot for %d to disk", uid); } } @@ -100,10 +103,17 @@ public class RecoverySnapshotStorage { return snapshot; } - try { - return readFromDisk(uid); + File snapshotFile = getSnapshotFile(uid); + try (FileInputStream fileInputStream = new FileInputStream(snapshotFile)) { + return KeyChainSnapshotDeserializer.deserialize(fileInputStream); + } catch (FileNotFoundException e) { + Slogf.i(TAG, "Snapshot for uid %d not found", uid); + return null; } catch (IOException | KeyChainSnapshotParserException e) { - Log.e(TAG, String.format(Locale.US, "Error reading snapshot for %d from disk", uid), e); + // If we fail to read the latest snapshot, we should delete it in case it is in some way + // corrupted. We can regenerate snapshots anyway. + snapshotFile.delete(); + Slogf.e(TAG, e, "Error reading snapshot for %d from disk", uid); return null; } } @@ -116,50 +126,6 @@ public class RecoverySnapshotStorage { getSnapshotFile(uid).delete(); } - /** - * Writes the snapshot for recovery agent {@code uid} to disk. - * - * @throws IOException if an IO error occurs writing to disk. - */ - private void writeToDisk(int uid, KeyChainSnapshot snapshot) - throws IOException, CertificateEncodingException { - File snapshotFile = getSnapshotFile(uid); - - try ( - FileOutputStream fileOutputStream = new FileOutputStream(snapshotFile) - ) { - KeyChainSnapshotSerializer.serialize(snapshot, fileOutputStream); - } catch (IOException | CertificateEncodingException e) { - // If we fail to write the latest snapshot, we should delete any older snapshot that - // happens to be around. Otherwise snapshot syncs might end up going 'back in time'. - snapshotFile.delete(); - throw e; - } - } - - /** - * Reads the last snapshot for recovery agent {@code uid} from disk. - * - * @return The snapshot, or null if none existed. - * @throws IOException if an IO error occurs reading from disk. - */ - @Nullable - private KeyChainSnapshot readFromDisk(int uid) - throws IOException, KeyChainSnapshotParserException { - File snapshotFile = getSnapshotFile(uid); - - try ( - FileInputStream fileInputStream = new FileInputStream(snapshotFile) - ) { - return KeyChainSnapshotDeserializer.deserialize(fileInputStream); - } catch (IOException | KeyChainSnapshotParserException e) { - // If we fail to read the latest snapshot, we should delete it in case it is in some way - // corrupted. We can regenerate snapshots anyway. - snapshotFile.delete(); - throw e; - } - } - private File getSnapshotFile(int uid) { File folder = getStorageFolder(); String fileName = getSnapshotFileName(uid); diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index 3bcaf58d0a13..f23d7823be94 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -96,12 +96,15 @@ public final class NativeTombstoneManager { mHandler = thread.getThreadHandler(); mWatcher = new TombstoneWatcher(); - mWatcher.startWatching(); } void onSystemReady() { registerForUserRemoval(); registerForPackageRemoval(); + // TombstoneWatcher depends on DropboxManagerService. + // DropboxManagerService started before systemReady. + // So it is good to call startWatching here. + mWatcher.startWatching(); BootReceiver.initDropboxRateLimiter(); diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 5d71439e8f46..458b46dab54c 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -592,7 +592,7 @@ public abstract class ApexManager { return apexSessionInfo; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + return null; } } @@ -607,7 +607,7 @@ public abstract class ApexManager { return result; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + return new SparseArray<>(0); } } @@ -619,7 +619,9 @@ public abstract class ApexManager { return apexInfoList; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, + "apexd verification failed : " + re.getMessage()); } catch (Exception e) { throw new PackageManagerException( PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, @@ -633,7 +635,7 @@ public abstract class ApexManager { return waitForApexService().getStagedApexInfos(params); } catch (RemoteException re) { Slog.w(TAG, "Unable to contact apexservice" + re.getMessage()); - throw new RuntimeException(re); + return new ApexInfo[0]; } catch (Exception e) { Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage()); return new ApexInfo[0]; @@ -646,7 +648,9 @@ public abstract class ApexManager { waitForApexService().markStagedSessionReady(sessionId); } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, + "Failed to mark apexd session as ready : " + re.getMessage()); } catch (Exception e) { throw new PackageManagerException( PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, diff --git a/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java index 0d420a535415..dcb47a7b60b6 100644 --- a/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java +++ b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java @@ -62,6 +62,9 @@ public class StatsBootstrapAtomService extends IStatsBootstrapAtomService.Stub { case StatsBootstrapAtomValue.bytesValue: builder.writeByteArray(value.getBytesValue()); break; + case StatsBootstrapAtomValue.stringArrayValue: + builder.writeStringArray(value.getStringArrayValue()); + break; default: Slog.e(TAG, "Unexpected value type " + value.getTag() + " when logging atom " + atom.atomId); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java index d08cdc718a82..769f071e3ddc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java @@ -265,19 +265,19 @@ public class ApexManagerTest { } @Test - public void testSubmitStagedSession_throwRunTimeException() throws RemoteException { + public void testSubmitStagedSession_throwPackageManagerExceptionOnRemoteException() + throws RemoteException { doThrow(RemoteException.class).when(mApexService).submitStagedSession(any(), any()); - assertThrows(RuntimeException.class, + assertThrows(PackageManagerException.class, () -> mApexManager.submitStagedSession(testParamsWithChildren())); } @Test - public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException { + public void testGetStagedApexInfos_returnsEmptyOnRemoteException() throws RemoteException { doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any()); - assertThrows(RuntimeException.class, - () -> mApexManager.getStagedApexInfos(testParamsWithChildren())); + assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0); } @Test @@ -298,10 +298,11 @@ public class ApexManagerTest { } @Test - public void testMarkStagedSessionReady_throwRunTimeException() throws RemoteException { + public void testMarkStagedSessionReady_throwPackageManagerExceptionOnRemoteException() + throws RemoteException { doThrow(RemoteException.class).when(mApexService).markStagedSessionReady(anyInt()); - assertThrows(RuntimeException.class, + assertThrows(PackageManagerException.class, () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID)); } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS index 5181af14ff65..aa22790022c5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS +++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS @@ -2,3 +2,4 @@ include /services/core/java/com/android/server/pm/OWNERS per-file BackgroundDexOptServiceUnitTest.java = file:/services/core/java/com/android/server/pm/dex/OWNERS per-file StagingManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com +per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java index 50f3a88cc3a2..5bcddc41eb87 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java @@ -1,6 +1,10 @@ package com.android.server.locksettings; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; @@ -56,4 +60,44 @@ public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { mService.initializeSyntheticPassword(userId); // This should allocate a Weaver slot. assertEquals(Sets.newHashSet(0), mPasswordSlotManager.getUsedSlots()); } + + private int getNumUsedWeaverSlots() { + return mPasswordSlotManager.getUsedSlots().size(); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_false() { + final int userId = PRIMARY_USER_ID; + when(mResources.getBoolean(eq( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers))) + .thenReturn(false); + assertEquals(0, getNumUsedWeaverSlots()); + mService.initializeSyntheticPassword(userId); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_true() { + final int userId = PRIMARY_USER_ID; + when(mResources.getBoolean(eq( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers))) + .thenReturn(true); + assertEquals(0, getNumUsedWeaverSlots()); + mService.initializeSyntheticPassword(userId); + assertEquals(0, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId)); + assertEquals(0, getNumUsedWeaverSlots()); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_defaultsToFalse() { + assertFalse(mResources.getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers)); + } } diff --git a/tests/FlickerTests/ActivityEmbedding/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS index 981b3168cdbb..981b3168cdbb 100644 --- a/tests/FlickerTests/ActivityEmbedding/OWNERS +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/Internal/src/com/android/internal/os/OWNERS b/tests/Internal/src/com/android/internal/os/OWNERS new file mode 100644 index 000000000000..64ffa463bac1 --- /dev/null +++ b/tests/Internal/src/com/android/internal/os/OWNERS @@ -0,0 +1,2 @@ +# ApplicationSharedMemory +per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS diff --git a/tests/Tracing/Android.bp b/tests/Tracing/Android.bp new file mode 100644 index 000000000000..f5c1ae57e8c2 --- /dev/null +++ b/tests/Tracing/Android.bp @@ -0,0 +1,33 @@ +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_team: "trendy_team_windowing_tools", + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "TracingTests", + proto: { + type: "nano", + }, + // Include some source files directly to be able to access package members + srcs: ["src/**/*.java"], + libs: ["android.test.runner.impl"], + static_libs: [ + "junit", + "androidx.test.rules", + "mockito-target-minus-junit4", + "truth", + "platform-test-annotations", + "flickerlib-parsers", + "perfetto_trace_java_protos", + "flickerlib-trace_processor_shell", + ], + java_resource_dirs: ["res"], + certificate: "platform", + platform_apis: true, + test_suites: ["device-tests"], +} diff --git a/tests/Tracing/AndroidManifest.xml b/tests/Tracing/AndroidManifest.xml new file mode 100644 index 000000000000..7254f81307ad --- /dev/null +++ b/tests/Tracing/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tracing.tests"> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.BIND_WALLPAPER"/> + <!-- Allow the test to connect to perfetto trace processor --> + <uses-permission android:name="android.permission.INTERNET"/> + <application + android:requestLegacyExternalStorage="true" + android:networkSecurityConfig="@xml/network_security_config"> + <uses-library android:name="android.test.runner"/> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.tracing.tests" + android:label="Tracing Tests"/> +</manifest> diff --git a/tests/Tracing/AndroidTest.xml b/tests/Tracing/AndroidTest.xml new file mode 100644 index 000000000000..9a404203ee18 --- /dev/null +++ b/tests/Tracing/AndroidTest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<configuration description="Runs tests for tracing classes/utilities."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="TracingTests.apk" /> + </target_preparer> + + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="framework-base-presubmit" /> + <option name="test-tag" value="TracingTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.tracing.tests" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> + + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path"/> + <option name="directory-keys" + value="/data/user/0/com.android.tracing.tests/files"/> + <option name="collect-on-run-ended-only" value="true"/> + <option name="clean-up" value="true"/> + </metrics_collector> +</configuration>
\ No newline at end of file diff --git a/tests/Internal/src/com/android/internal/protolog/OWNERS b/tests/Tracing/OWNERS index 18cf2be9f7df..4a5033800b8e 100644 --- a/tests/Internal/src/com/android/internal/protolog/OWNERS +++ b/tests/Tracing/OWNERS @@ -1,3 +1,3 @@ -# ProtoLog owners +# Tracing owners # Bug component: 1157642 include platform/development:/tools/winscope/OWNERS diff --git a/tests/Tracing/TEST_MAPPING b/tests/Tracing/TEST_MAPPING new file mode 100644 index 000000000000..7f58fceee24d --- /dev/null +++ b/tests/Tracing/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "postsubmit": [ + { + "name": "TracingTests" + } + ] +}
\ No newline at end of file diff --git a/tests/Tracing/res/xml/network_security_config.xml b/tests/Tracing/res/xml/network_security_config.xml new file mode 100644 index 000000000000..fdf1dbbe7672 --- /dev/null +++ b/tests/Tracing/res/xml/network_security_config.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 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. + --> +<network-security-config> + <domain-config cleartextTrafficPermitted="true"> + <domain includeSubdomains="true">localhost</domain> + </domain-config> +</network-security-config> diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogImplTest.java index 5a27593c7a36..e9ff691151fe 100644 --- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogImplTest.java @@ -181,7 +181,6 @@ public class LegacyProtoLogImplTest { verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( LogLevel.INFO), eq("test 5")); - verify(mReader, never()).getViewerString(anyLong()); } @Test diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java index dbd85d38b7f2..253965337824 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java @@ -38,7 +38,7 @@ import java.util.zip.GZIPOutputStream; @SmallTest @Presubmit @RunWith(JUnit4.class) -public class ProtoLogViewerConfigReaderTest { +public class LegacyProtoLogViewerConfigReaderTest { private static final String TEST_VIEWER_CONFIG = "{\n" + " \"version\": \"1.0.0\",\n" + " \"messages\": {\n" diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java index 1d7b6b348e10..1d7b6b348e10 100644 --- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogImplTest.java index 60456f9ea10f..60456f9ea10f 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogImplTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtologDataSourceTest.java index be9fb1b309f6..be9fb1b309f6 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtologDataSourceTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java b/tests/Tracing/src/com/android/internal/protolog/common/LogDataTypeTest.java index 9c2f74eabe02..9c2f74eabe02 100644 --- a/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/common/LogDataTypeTest.java |