diff options
71 files changed, 1241 insertions, 355 deletions
diff --git a/Android.bp b/Android.bp index ebdb1a1a9082..5f02a15ad185 100644 --- a/Android.bp +++ b/Android.bp @@ -205,6 +205,7 @@ java_library { "apex_aidl_interface-java", "packagemanager_aidl-java", "framework-protos", + "libtombstone_proto_java", "updatable-driver-protos", "ota_metadata_proto_java", "android.hidl.base-V1.0-java", @@ -647,6 +648,7 @@ java_library { lint: { baseline_filename: "lint-baseline.xml", }, + apex_available: ["com.android.wifi"], } filegroup { diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp index e7adf203334e..d03bbd249b00 100644 --- a/ProtoLibraries.bp +++ b/ProtoLibraries.bp @@ -34,7 +34,6 @@ gensrcs { ":ipconnectivity-proto-src", ":libstats_atom_enum_protos", ":libstats_atom_message_protos", - ":libtombstone_proto-src", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], diff --git a/STABILITY_OWNERS b/STABILITY_OWNERS new file mode 100644 index 000000000000..a7ecb4dfdd44 --- /dev/null +++ b/STABILITY_OWNERS @@ -0,0 +1,2 @@ +gaillard@google.com + diff --git a/TEST_MAPPING b/TEST_MAPPING index eef3d27d19e6..8338c3340ac4 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -125,6 +125,9 @@ }, { "name": "vts_treble_vintf_vendor_test" + }, + { + "name": "CtsStrictJavaPackagesTestCases" } ], "postsubmit-managedprofile-stress": [ diff --git a/WEAR_OWNERS b/WEAR_OWNERS index 4f3bc27c380f..4127f996da03 100644 --- a/WEAR_OWNERS +++ b/WEAR_OWNERS @@ -4,3 +4,9 @@ yeabkal@google.com adsule@google.com andriyn@google.com yfz@google.com +con@google.com +leetodd@google.com +sadrul@google.com +rwmyers@google.com +nalmalki@google.com +shijianli@google.com diff --git a/api/Android.bp b/api/Android.bp index 53988cd373b8..00841264c0f1 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -458,3 +458,12 @@ genrule { targets: ["droid"], }, } + +phony_rule { + name: "checkapi", + phony_deps: [ + "frameworks-base-api-current-compat", + "frameworks-base-api-system-current-compat", + "frameworks-base-api-module-lib-current-compat", + ], +} diff --git a/api/Android.mk b/api/Android.mk deleted file mode 100644 index ce5f995033c5..000000000000 --- a/api/Android.mk +++ /dev/null @@ -1,2 +0,0 @@ -.PHONY: checkapi -checkapi: frameworks-base-api-current-compat frameworks-base-api-system-current-compat frameworks-base-api-module-lib-current-compat diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 28b2d4b5e3ee..ef1fa6097056 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -900,10 +900,19 @@ droidstubs { ], api_levels_sdk_type: "system", extensions_info_file: ":sdk-extensions-info", + dists: [ + // Make the api-versions.xml file for the system API available in the + // sdk build target. + { + targets: ["sdk"], + dest: "api-versions_system.xml", + tag: ".api_versions.xml", + }, + ], } // This module can be built with: -// m out/soong/.intermediates/frameworks/base/api_versions_module_lib/android_common/metalava/api-versions.xml +// m out/soong/.intermediates/frameworks/base/api/api_versions_module_lib/android_common/metalava/api-versions.xml droidstubs { name: "api_versions_module_lib", srcs: [":android_module_stubs_current_with_test_libs{.jar}"], diff --git a/core/api/current.txt b/core/api/current.txt index c600df19a379..48f58c09871d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -29120,6 +29120,8 @@ package android.nfc { method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported(); method public boolean isSecureNfcEnabled(); method public boolean isSecureNfcSupported(); + method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity); + method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int); field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED"; field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; @@ -29135,6 +29137,13 @@ package android.nfc { field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME"; field public static final String EXTRA_TAG = "android.nfc.extra.TAG"; + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_DISABLE = 0; // 0x0 + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_KEEP = -1; // 0xffffffff + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_A = 1; // 0x1 + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_B = 2; // 0x2 + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_F = 4; // 0x4 + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_DISABLE = 0; // 0x0 + field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_KEEP = -1; // 0xffffffff field public static final int FLAG_READER_NFC_A = 1; // 0x1 field public static final int FLAG_READER_NFC_B = 2; // 0x2 field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10 diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 4c2e4fc05949..8eca0fe4b775 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10925,7 +10925,7 @@ package android.os { method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static int rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException; method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException; - method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException; + method @Deprecated public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException; field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME = 2000; // 0x7d0 field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED = 3000; // 0xbb8 field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE = 5000; // 0x1388 diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index f33d2991329a..4823f447f22b 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -1311,8 +1311,9 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim if (!node.mEnded) { float durationScale = ValueAnimator.getDurationScale(); durationScale = durationScale == 0 ? 1 : durationScale; - node.mEnded = node.mAnimation.pulseAnimationFrame( - (long) (animPlayTime * durationScale)); + if (node.mAnimation.pulseAnimationFrame((long) (animPlayTime * durationScale))) { + node.mEnded = true; + } } } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index f6beec179d57..85879ac56194 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -86,4 +86,5 @@ interface INfcAdapter boolean enableReaderOption(boolean enable); boolean isObserveModeSupported(); boolean setObserveMode(boolean enabled); + void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags); } diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl index 191385a3c13d..f4b46046bc3e 100644 --- a/core/java/android/nfc/INfcCardEmulation.aidl +++ b/core/java/android/nfc/INfcCardEmulation.aidl @@ -43,4 +43,7 @@ interface INfcCardEmulation ApduServiceInfo getPreferredPaymentService(int userHandle); boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status); boolean isDefaultPaymentRegistered(); + + boolean overrideRoutingTable(int userHandle, String protocol, String technology); + boolean recoverRoutingTable(int userHandle); } diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index 8d75cac531fb..f03fc0af86b3 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -112,6 +112,9 @@ public final class NfcActivityManager extends IAppCallback.Stub Bundle readerModeExtras = null; Binder token; + int mPollTech = NfcAdapter.FLAG_USE_ALL_TECH; + int mListenTech = NfcAdapter.FLAG_USE_ALL_TECH; + public NfcActivityState(Activity activity) { if (activity.isDestroyed()) { throw new IllegalStateException("activity is already destroyed"); @@ -132,6 +135,9 @@ public final class NfcActivityManager extends IAppCallback.Stub readerModeFlags = 0; readerModeExtras = null; token = null; + + mPollTech = NfcAdapter.FLAG_USE_ALL_TECH; + mListenTech = NfcAdapter.FLAG_USE_ALL_TECH; } @Override public String toString() { @@ -278,6 +284,9 @@ public final class NfcActivityManager extends IAppCallback.Stub int readerModeFlags = 0; Bundle readerModeExtras = null; Binder token; + int pollTech; + int listenTech; + synchronized (NfcActivityManager.this) { NfcActivityState state = findActivityState(activity); if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state); @@ -286,9 +295,15 @@ public final class NfcActivityManager extends IAppCallback.Stub token = state.token; readerModeFlags = state.readerModeFlags; readerModeExtras = state.readerModeExtras; + + pollTech = state.mPollTech; + listenTech = state.mListenTech; } if (readerModeFlags != 0) { setReaderMode(token, readerModeFlags, readerModeExtras); + } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH + || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) { + changeDiscoveryTech(token, pollTech, listenTech); } requestNfcServiceCallback(); } @@ -298,6 +313,9 @@ public final class NfcActivityManager extends IAppCallback.Stub public void onActivityPaused(Activity activity) { boolean readerModeFlagsSet; Binder token; + int pollTech; + int listenTech; + synchronized (NfcActivityManager.this) { NfcActivityState state = findActivityState(activity); if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state); @@ -305,10 +323,17 @@ public final class NfcActivityManager extends IAppCallback.Stub state.resumed = false; token = state.token; readerModeFlagsSet = state.readerModeFlags != 0; + + pollTech = state.mPollTech; + listenTech = state.mListenTech; } if (readerModeFlagsSet) { // Restore default p2p modes setReaderMode(token, 0, null); + } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH + || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) { + changeDiscoveryTech(token, + NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH); } } @@ -333,4 +358,53 @@ public final class NfcActivityManager extends IAppCallback.Stub } } + /** setDiscoveryTechnology() implementation */ + public void setDiscoveryTech(Activity activity, int pollTech, int listenTech) { + boolean isResumed; + Binder token; + boolean readerModeFlagsSet; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + readerModeFlagsSet = state.readerModeFlags != 0; + state.mListenTech = listenTech; + state.mPollTech = pollTech; + token = state.token; + isResumed = state.resumed; + } + if (!readerModeFlagsSet && isResumed) { + changeDiscoveryTech(token, pollTech, listenTech); + } else if (readerModeFlagsSet) { + throw new IllegalStateException("Cannot be used when the Reader Mode is enabled"); + } + } + + /** resetDiscoveryTechnology() implementation */ + public void resetDiscoveryTech(Activity activity) { + boolean isResumed; + Binder token; + boolean readerModeFlagsSet; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + readerModeFlagsSet = state.readerModeFlags != 0; + state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH; + state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH; + token = state.token; + isResumed = state.resumed; + } + if (readerModeFlagsSet) { + disableReaderMode(activity); + } else if (isResumed) { + changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH); + } + + } + + private void changeDiscoveryTech(Binder token, int pollTech, int listenTech) { + try { + NfcAdapter.sService.updateDiscoveryTechnology(token, pollTech, listenTech); + } catch (RemoteException e) { + mAdapter.attemptDeadServiceRecovery(e); + } + } + } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index f407fb73534f..979855e5e25c 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -332,6 +332,19 @@ public final class NfcAdapter { */ public static final int FLAG_READER_NFC_BARCODE = 0x10; + /** @hide */ + @IntDef(flag = true, prefix = {"FLAG_READER_"}, value = { + FLAG_READER_KEEP, + FLAG_READER_DISABLE, + FLAG_READER_NFC_A, + FLAG_READER_NFC_B, + FLAG_READER_NFC_F, + FLAG_READER_NFC_V, + FLAG_READER_NFC_BARCODE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PollTechnology {} + /** * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> @@ -359,6 +372,76 @@ public final class NfcAdapter { public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; /** + * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag enables listening for Nfc-A technology. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1; + + /** + * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag enables listening for Nfc-B technology. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1; + + /** + * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag enables listening for Nfc-F technology. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2; + + /** + * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag disables listening. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_LISTEN_DISABLE = 0x0; + + /** + * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag disables polling. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_READER_DISABLE = 0x0; + + /** + * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag makes listening to use current flags. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_LISTEN_KEEP = -1; + + /** + * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. + * <p> + * Setting this flag makes polling to use current flags. + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public static final int FLAG_READER_KEEP = -1; + + /** @hide */ + public static final int FLAG_USE_ALL_TECH = 0xff; + + /** @hide */ + @IntDef(flag = true, prefix = {"FLAG_LISTEN_"}, value = { + FLAG_LISTEN_KEEP, + FLAG_LISTEN_DISABLE, + FLAG_LISTEN_NFC_PASSIVE_A, + FLAG_LISTEN_NFC_PASSIVE_B, + FLAG_LISTEN_NFC_PASSIVE_F + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ListenTechnology {} + + /** * @hide * @removed */ @@ -436,11 +519,13 @@ public final class NfcAdapter { @Retention(RetentionPolicy.SOURCE) public @interface TagIntentAppPreferenceResult {} - // Guarded by NfcAdapter.class + // Guarded by sLock static boolean sIsInitialized = false; static boolean sHasNfcFeature; static boolean sHasCeFeature; + static Object sLock = new Object(); + // Final after first constructor, except for // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort // recovery @@ -1230,7 +1315,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public void setBeamPushUris(Uri[] uris, Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1300,7 +1385,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1385,7 +1470,7 @@ public final class NfcAdapter { @UnsupportedAppUsage public void setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1399,7 +1484,7 @@ public final class NfcAdapter { @SystemApi @UnsupportedAppUsage public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1478,7 +1563,7 @@ public final class NfcAdapter { @UnsupportedAppUsage public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1529,7 +1614,7 @@ public final class NfcAdapter { @UnsupportedAppUsage public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, Activity activity, Activity ... activities) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1572,7 +1657,7 @@ public final class NfcAdapter { */ public void enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1607,7 +1692,7 @@ public final class NfcAdapter { * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void disableForegroundDispatch(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1643,7 +1728,7 @@ public final class NfcAdapter { */ public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, Bundle extras) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1660,7 +1745,7 @@ public final class NfcAdapter { * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void disableReaderMode(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1688,7 +1773,7 @@ public final class NfcAdapter { @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @SuppressLint("VisiblySynchronized") public void setReaderMode(boolean enablePolling) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1703,6 +1788,80 @@ public final class NfcAdapter { } /** + * Set the NFC controller to enable specific poll/listen technologies, + * as specified in parameters, while this Activity is in the foreground. + * + * Use {@link #FLAG_READER_KEEP} to keep current polling technology. + * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology. + * Use {@link #FLAG_READER_DISABLE} to disable polling. + * Use {@link #FLAG_LISTEN_DISABLE} to disable listening. + * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes. + * </p> + * The pollTechnology, listenTechnology parameters can be one or several of below list. + * <pre> + * Poll Listen + * Passive A 0x01 (NFC_A) 0x01 (NFC_PASSIVE_A) + * Passive B 0x02 (NFC_B) 0x02 (NFC_PASSIVE_B) + * Passive F 0x04 (NFC_F) 0x04 (NFC_PASSIVE_F) + * ISO 15693 0x08 (NFC_V) - + * Kovio 0x10 (NFC_BARCODE) - + * </pre> + * <p>Example usage in an Activity that requires to disable poll, + * keep current listen technologies: + * <pre> + * protected void onResume() { + * mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext()); + * mNfcAdapter.setDiscoveryTechnology(this, + * NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP); + * }</pre></p> + * @param activity The Activity that requests NFC controller to enable specific technologies. + * @param pollTechnology Flags indicating poll technologies. + * @param listenTechnology Flags indicating listen technologies. + * @throws UnsupportedOperationException if FEATURE_NFC, + * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable. + */ + + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public void setDiscoveryTechnology(@NonNull Activity activity, + @PollTechnology int pollTechnology, @ListenTechnology int listenTechnology) { + if (listenTechnology == FLAG_LISTEN_DISABLE) { + synchronized (sLock) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } + mNfcActivityManager.enableReaderMode(activity, null, pollTechnology, null); + return; + } + if (pollTechnology == FLAG_READER_DISABLE) { + synchronized (sLock) { + if (!sHasCeFeature) { + throw new UnsupportedOperationException(); + } + } + } else { + synchronized (sLock) { + if (!sHasNfcFeature || !sHasCeFeature) { + throw new UnsupportedOperationException(); + } + } + } + mNfcActivityManager.setDiscoveryTech(activity, pollTechnology, listenTechnology); + } + + /** + * Restore the poll/listen technologies of NFC controller, + * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)} + * + * @param activity The Activity that requests to changed technologies. + */ + + @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) + public void resetDiscoveryTechnology(@NonNull Activity activity) { + mNfcActivityManager.resetDiscoveryTech(activity); + } + + /** * Manually invoke Android Beam to share data. * * <p>The Android Beam animation is normally only shown when two NFC-capable @@ -1732,7 +1891,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public boolean invokeBeam(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1770,7 +1929,7 @@ public final class NfcAdapter { @Deprecated @UnsupportedAppUsage public void enableForegroundNdefPush(Activity activity, NdefMessage message) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -1800,7 +1959,7 @@ public final class NfcAdapter { @Deprecated @UnsupportedAppUsage public void disableForegroundNdefPush(Activity activity) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -2080,7 +2239,7 @@ public final class NfcAdapter { @java.lang.Deprecated @UnsupportedAppUsage public boolean isNdefPushEnabled() { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -2194,7 +2353,7 @@ public final class NfcAdapter { @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, String[] tagTechnologies) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } @@ -2243,7 +2402,7 @@ public final class NfcAdapter { @SystemApi @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { - synchronized (NfcAdapter.class) { + synchronized (sLock) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 58b6179691e9..ad86d70db967 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -998,6 +998,87 @@ public final class CardEmulation { } } + /** + * Setting NFC controller routing table, which includes Protocol Route and Technology Route, + * while this Activity is in the foreground. + * + * The parameter set to null can be used to keep current values for that entry. + * <p> + * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route: + * <pre> + * protected void onResume() { + * mNfcAdapter.overrideRoutingTable(this , "ESE" , null); + * }</pre> + * </p> + * Also activities must call this method when it goes to the background, + * with all parameters set to null. + * @param activity The Activity that requests NFC controller routing table to be changed. + * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE". + * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE". + * @return true if operation is successful and false otherwise + * + * This is a high risk API and only included to support mainline effort + * @hide + */ + public boolean overrideRoutingTable(Activity activity, String protocol, String technology) { + if (activity == null) { + throw new NullPointerException("activity or service or category is null"); + } + if (!activity.isResumed()) { + throw new IllegalArgumentException("Activity must be resumed."); + } + try { + return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology); + } catch (RemoteException e) { + // Try one more time + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return false; + } + try { + return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to reach CardEmulationService."); + return false; + } + } + } + + /** + * Restore the NFC controller routing table, + * which was changed by {@link #overrideRoutingTable(Activity, String, String)} + * + * @param activity The Activity that requested NFC controller routing table to be changed. + * @return true if operation is successful and false otherwise + * + * @hide + */ + public boolean recoverRoutingTable(Activity activity) { + if (activity == null) { + throw new NullPointerException("activity is null"); + } + if (!activity.isResumed()) { + throw new IllegalArgumentException("Activity must be resumed."); + } + try { + return sService.recoverRoutingTable(UserHandle.myUserId()); + } catch (RemoteException e) { + // Try one more time + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return false; + } + try { + return sService.recoverRoutingTable(UserHandle.myUserId()); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to reach CardEmulationService."); + return false; + } + } + } + void recoverService() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); sService = adapter.getCardEmulationService(); diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig index 0d073cc6c819..11be905c41ca 100644 --- a/core/java/android/nfc/flags.aconfig +++ b/core/java/android/nfc/flags.aconfig @@ -55,3 +55,10 @@ flag { description: "Enable sending broadcasts to Wallet role holder when a tag enters/leaves the field." bug: "306203494" } + +flag { + name: "enable_nfc_set_discovery_tech" + namespace: "nfc" + description: "Flag for NFC set discovery tech API" + bug: "300351519" +} diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index a9b7257a5406..58717179d64d 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1315,9 +1315,7 @@ public class Build { if (IS_ENG) return true; if (IS_TREBLE_ENABLED) { - // If we can run this code, the device should already pass AVB. - // So, we don't need to check AVB here. - int result = VintfObject.verifyWithoutAvb(); + int result = VintfObject.verifyBuildAtBoot(); if (result != 0) { Slog.e(TAG, "Vendor interface is incompatible, error=" diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl index 61b24aa55e30..b7649ba9700b 100644 --- a/core/java/android/os/ISystemConfig.aidl +++ b/core/java/android/os/ISystemConfig.aidl @@ -52,4 +52,9 @@ interface ISystemConfig { * @see SystemConfigManager#getDefaultVrComponents */ List<ComponentName> getDefaultVrComponents(); + + /** + * @see SystemConfigManager#getPreventUserDisablePackages + */ + List<String> getPreventUserDisablePackages(); } diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 7f60a2097153..2145c1aa82c8 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -90,4 +90,8 @@ per-file CoolingDevice.java = file:/THERMAL_OWNERS per-file Temperature.java = file:/THERMAL_OWNERS # SecurityStateManager -per-file *SecurityStateManager* = file:/SECURITY_STATE_OWNERS
\ No newline at end of file +per-file *SecurityStateManager* = file:/SECURITY_STATE_OWNERS + +# SystemConfig +per-file ISystemConfig.aidl = file:/PACKAGE_MANAGER_OWNERS +per-file SystemConfigManager.java = file:/PACKAGE_MANAGER_OWNERS diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index a3b836adfc8b..d002fe1d6cc0 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -18,8 +18,6 @@ package android.os; import static android.view.Display.DEFAULT_DISPLAY; -import static java.nio.charset.StandardCharsets.UTF_8; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -47,11 +45,8 @@ import android.text.format.DateFormat; import android.util.Log; import android.view.Display; -import libcore.io.Streams; - import java.io.ByteArrayInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; @@ -73,7 +68,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; import sun.security.pkcs.PKCS7; import sun.security.pkcs.SignerInfo; @@ -423,72 +417,43 @@ public class RecoverySystem { } finally { raf.close(); } - - // Additionally verify the package compatibility. - if (!readAndVerifyPackageCompatibilityEntry(packageFile)) { - throw new SignatureException("package compatibility verification failed"); - } } /** * Verifies the compatibility entry from an {@link InputStream}. * - * @return the verification result. + * @param inputStream The stream that contains the package compatibility info. + * @throws IOException Never. + * @return {@code true}. + * @deprecated This function no longer checks {@code inputStream} and + * unconditionally returns true. Instead, check compatibility when the + * OTA package is generated. */ - @UnsupportedAppUsage + @Deprecated + @UnsupportedAppUsage( + publicAlternatives = "Use {@code true} directly", + maxTargetSdk = Build.VERSION_CODES.VANILLA_ICE_CREAM) private static boolean verifyPackageCompatibility(InputStream inputStream) throws IOException { - ArrayList<String> list = new ArrayList<>(); - ZipInputStream zis = new ZipInputStream(inputStream); - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - long entrySize = entry.getSize(); - if (entrySize > Integer.MAX_VALUE || entrySize < 0) { - throw new IOException( - "invalid entry size (" + entrySize + ") in the compatibility file"); - } - byte[] bytes = new byte[(int) entrySize]; - Streams.readFully(zis, bytes); - list.add(new String(bytes, UTF_8)); - } - if (list.isEmpty()) { - throw new IOException("no entries found in the compatibility file"); - } - return (VintfObject.verify(list.toArray(new String[list.size()])) == 0); - } - - /** - * Reads and verifies the compatibility entry in an OTA zip package. The compatibility entry is - * a zip file (inside the OTA package zip). - * - * @return {@code true} if the entry doesn't exist or verification passes. - */ - private static boolean readAndVerifyPackageCompatibilityEntry(File packageFile) - throws IOException { - try (ZipFile zip = new ZipFile(packageFile)) { - ZipEntry entry = zip.getEntry("compatibility.zip"); - if (entry == null) { - return true; - } - InputStream inputStream = zip.getInputStream(entry); - return verifyPackageCompatibility(inputStream); - } + return true; } /** * Verifies the package compatibility info against the current system. * * @param compatibilityFile the {@link File} that contains the package compatibility info. - * @throws IOException if there were any errors reading the compatibility file. - * @return the compatibility verification result. + * @throws IOException Never. + * @return {@code true} + * @deprecated This function no longer checks {@code compatibilityFile} and + * unconditionally returns true. Instead, check compatibility when the + * OTA package is generated. * * {@hide} */ + @Deprecated @SystemApi @SuppressLint("RequiresPermission") public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException { - try (InputStream inputStream = new FileInputStream(compatibilityFile)) { - return verifyPackageCompatibility(inputStream); - } + return true; } /** diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java index 77843d9fbb0a..21ffbf18dbc3 100644 --- a/core/java/android/os/SystemConfigManager.java +++ b/core/java/android/os/SystemConfigManager.java @@ -161,4 +161,18 @@ public class SystemConfigManager { } return Collections.emptyList(); } + + /** + * Return the packages that are prevented from being disabled, where if + * disabled it would result in a non-functioning system or similar. + * @hide + */ + @NonNull + public List<String> getPreventUserDisablePackages() { + try { + return mInterface.getPreventUserDisablePackages(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 1f11197afeee..4fc5131617b2 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -18,7 +18,6 @@ package android.os; import android.annotation.NonNull; import android.annotation.TestApi; -import android.util.Slog; import java.util.Map; @@ -44,44 +43,8 @@ public class VintfObject { public static native String[] report(); /** - * Verify that the given metadata for an OTA package is compatible with - * this device. - * - * @param packageInfo a list of serialized form of HalManifest's / - * CompatibilityMatri'ces (XML). - * @return = 0 if success (compatible) - * > 0 if incompatible - * < 0 if any error (mount partition fails, illformed XML, etc.) - * - * @deprecated Checking compatibility against an OTA package is no longer - * supported because the format of VINTF metadata in the OTA package may not - * be recognized by the current system. - * - * <p> - * <ul> - * <li>This function always returns 0 for non-empty {@code packageInfo}. - * </li> - * <li>This function returns the result of {@link #verifyWithoutAvb} for - * null or empty {@code packageInfo}.</li> - * </ul> - * - * @hide - */ - @Deprecated - public static int verify(String[] packageInfo) { - if (packageInfo != null && packageInfo.length > 0) { - Slog.w(LOG_TAG, "VintfObject.verify() with non-empty packageInfo is deprecated. " - + "Skipping compatibility checks for update package."); - return 0; - } - Slog.w(LOG_TAG, "VintfObject.verify() is deprecated. Call verifyWithoutAvb() instead."); - return verifyWithoutAvb(); - } - - /** - * Verify Vintf compatibility on the device without checking AVB - * (Android Verified Boot). It is useful to verify a running system - * image where AVB check is irrelevant. + * Verify Vintf compatibility on the device at boot time. Certain checks + * like kernel checks, AVB checks are disabled. * * @return = 0 if success (compatible) * > 0 if incompatible @@ -89,7 +52,7 @@ public class VintfObject { * * @hide */ - public static native int verifyWithoutAvb(); + public static native int verifyBuildAtBoot(); /** * @return a list of HAL names and versions that is supported by this diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index 3ecf74e75367..54ed73c34830 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -134,16 +134,16 @@ interface IStorageManager { @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS") void setDebugFlags(int flags, int mask) = 60; @EnforcePermission("STORAGE_INTERNAL") - void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) = 61; + void createUserStorageKeys(int userId, boolean ephemeral) = 61; @EnforcePermission("STORAGE_INTERNAL") void destroyUserStorageKeys(int userId) = 62; @EnforcePermission("STORAGE_INTERNAL") - void unlockCeStorage(int userId, int serialNumber, in byte[] secret) = 63; + void unlockCeStorage(int userId, in byte[] secret) = 63; @EnforcePermission("STORAGE_INTERNAL") void lockCeStorage(int userId) = 64; boolean isCeStorageUnlocked(int userId) = 65; @EnforcePermission("STORAGE_INTERNAL") - void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66; + void prepareUserStorage(in String volumeUuid, int userId, int flags) = 66; @EnforcePermission("STORAGE_INTERNAL") void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67; @EnforcePermission("STORAGE_INTERNAL") diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 4b9bd47ce851..eb1db3eaa06e 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1602,14 +1602,13 @@ public class StorageManager { * This is only intended to be called by UserManagerService, as part of creating a user. * * @param userId ID of the user - * @param serialNumber serial number of the user * @param ephemeral whether the user is ephemeral * @throws RuntimeException on error. The user's keys already existing is considered an error. * @hide */ - public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) { + public void createUserStorageKeys(int userId, boolean ephemeral) { try { - mStorageManager.createUserStorageKeys(userId, serialNumber, ephemeral); + mStorageManager.createUserStorageKeys(userId, ephemeral); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1653,9 +1652,9 @@ public class StorageManager { } /** {@hide} */ - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { + public void prepareUserStorage(String volumeUuid, int userId, int flags) { try { - mStorageManager.prepareUserStorage(volumeUuid, userId, serialNumber, flags); + mStorageManager.prepareUserStorage(volumeUuid, userId, flags); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS deleted file mode 100644 index 1c2d19d94871..000000000000 --- a/core/java/com/android/server/OWNERS +++ /dev/null @@ -1 +0,0 @@ -per-file SystemConfig.java = file:/PACKAGE_MANAGER_OWNERS diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 1baea2aecc3c..b6517117ca62 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -46,6 +46,7 @@ using vintf::toXml; using vintf::Version; using vintf::VintfObject; using vintf::Vndk; +using vintf::CheckFlags::ENABLE_ALL_CHECKS; template<typename V> static inline jobjectArray toJavaStringArray(JNIEnv* env, const V& v) { @@ -93,12 +94,13 @@ static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass) return toJavaStringArray(env, cStrings); } -static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) { +static jint android_os_VintfObject_verifyBuildAtBoot(JNIEnv* env, jclass) { std::string error; - int32_t status = VintfObject::GetInstance()->checkCompatibility(&error, - ::android::vintf::CheckFlags::DISABLE_AVB_CHECK); + int32_t status = + VintfObject::GetInstance() + ->checkCompatibility(&error, ENABLE_ALL_CHECKS.disableAvb().disableKernel()); if (status) - LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error; + LOG(WARNING) << "VintfObject.verifyBuildAtBoot() returns " << status << ": " << error; return status; } @@ -170,7 +172,7 @@ static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersi static const JNINativeMethod gVintfObjectMethods[] = { {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report}, - {"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb}, + {"verifyBuildAtBoot", "()I", (void*)android_os_VintfObject_verifyBuildAtBoot}, {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions}, {"getSepolicyVersion", "()Ljava/lang/String;", diff --git a/core/jni/hwbinder/EphemeralStorage.cpp b/core/jni/hwbinder/EphemeralStorage.cpp index 95bb42ea57c6..ef0750c815d7 100644 --- a/core/jni/hwbinder/EphemeralStorage.cpp +++ b/core/jni/hwbinder/EphemeralStorage.cpp @@ -164,7 +164,7 @@ void EphemeralStorage::release(JNIEnv *env) { } default: - CHECK(!"Should not be here"); + CHECK(!"Should not be here") << "Item type: " << item.mType; } } diff --git a/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java index 43266a51502b..cb3f99c37a4f 100644 --- a/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java +++ b/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java @@ -17,6 +17,7 @@ package android.animation; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.util.PollingCheck; @@ -343,6 +344,20 @@ public class AnimatorSetCallsTest { } @Test + public void childAnimatorCancelsDuringUpdate_animatorSetIsEnded() throws Throwable { + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + animation.cancel(); + } + }); + mActivity.runOnUiThread(() -> { + mSet1.start(); + assertFalse(mSet1.isRunning()); + }); + } + + @Test public void reentrantStart() throws Throwable { CountDownLatch latch = new CountDownLatch(3); AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { diff --git a/data/keyboards/Android.bp b/data/keyboards/Android.bp new file mode 100644 index 000000000000..f15c1535a667 --- /dev/null +++ b/data/keyboards/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2010 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. + +genrule { + name: "validate_framework_keymaps", + srcs: [ + "*.kl", + "*.kcm", + "*.idc", + ], + tools: ["validatekeymaps"], + out: ["stamp"], + cmd: "$(location validatekeymaps) -q $(in) " + + "&& touch $(out)", + dist: { + targets: ["droidcore"], + }, +} diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk deleted file mode 100644 index 6ae88007f0f5..000000000000 --- a/data/keyboards/Android.mk +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2010 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. - -# This makefile performs build time validation of framework keymap files. - -LOCAL_PATH := $(call my-dir) - -include $(LOCAL_PATH)/common.mk - -# Validate all key maps. -include $(CLEAR_VARS) - -LOCAL_MODULE := validate_framework_keymaps -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE -intermediates := $(call intermediates-dir-for,ETC,$(LOCAL_MODULE),,COMMON) -LOCAL_BUILT_MODULE := $(intermediates)/stamp - -validatekeymaps := $(HOST_OUT_EXECUTABLES)/validatekeymaps$(HOST_EXECUTABLE_SUFFIX) -$(LOCAL_BUILT_MODULE): PRIVATE_VALIDATEKEYMAPS := $(validatekeymaps) -$(LOCAL_BUILT_MODULE) : $(framework_keylayouts) $(framework_keycharmaps) $(framework_keyconfigs) | $(validatekeymaps) - $(hide) $(PRIVATE_VALIDATEKEYMAPS) -q $^ - $(hide) mkdir -p $(dir $@) && touch $@ - -# Run validatekeymaps uncondionally for platform build. -droidcore : $(LOCAL_BUILT_MODULE) - -# Reset temp vars. -validatekeymaps := -framework_keylayouts := -framework_keycharmaps := -framework_keyconfigs := diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk deleted file mode 100644 index d75b691bd585..000000000000 --- a/data/keyboards/common.mk +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2010 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. - -# This is the list of framework provided keylayouts and key character maps to include. -# Used by Android.mk and keyboards.mk. - -framework_keylayouts := $(wildcard $(LOCAL_PATH)/*.kl) - -framework_keycharmaps := $(wildcard $(LOCAL_PATH)/*.kcm) - -framework_keyconfigs := $(wildcard $(LOCAL_PATH)/*.idc) diff --git a/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml b/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml new file mode 100644 index 000000000000..2161a62ada9c --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 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. +*/ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="17dp" + android:height="17dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M22,10h-2v8h2V10z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M22,20h-2v2h2V20z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml new file mode 100644 index 000000000000..2161a62ada9c --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 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. +*/ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="17dp" + android:height="17dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M22,10h-2v8h2V10z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M22,20h-2v2h2V20z"/> +</vector> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 344e56cf570f..ae7c170fe8c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -118,15 +118,25 @@ public class StatusBarSignalPolicy implements SignalCallback, private void updateVpn() { boolean vpnVisible = mSecurityController.isVpnEnabled(); - int vpnIconId = currentVpnIconId(mSecurityController.isVpnBranded()); + int vpnIconId = currentVpnIconId( + mSecurityController.isVpnBranded(), + mSecurityController.isVpnValidated()); mIconController.setIcon(mSlotVpn, vpnIconId, mContext.getResources().getString(R.string.accessibility_vpn_on)); mIconController.setIconVisibility(mSlotVpn, vpnVisible); } - private int currentVpnIconId(boolean isBranded) { - return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic; + private int currentVpnIconId(boolean isBranded, boolean isValidated) { + if (isBranded) { + return isValidated + ? R.drawable.stat_sys_branded_vpn + : R.drawable.stat_sys_no_internet_branded_vpn; + } else { + return isValidated + ? R.drawable.stat_sys_vpn_ic + : R.drawable.stat_sys_no_internet_vpn_ic; + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java index 3be14bc867a1..10bf0680b567 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java @@ -48,6 +48,8 @@ public interface SecurityController extends CallbackController<SecurityControlle boolean isNetworkLoggingEnabled(); boolean isVpnEnabled(); boolean isVpnRestricted(); + /** Whether the VPN network is validated. */ + boolean isVpnValidated(); /** Whether the VPN app should use branded VPN iconography. */ boolean isVpnBranded(); String getPrimaryVpnName(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 03656f000c07..ada219635efb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -15,6 +15,9 @@ */ package com.android.systemui.statusbar.policy; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; + import android.annotation.Nullable; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; @@ -32,7 +35,9 @@ import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.LinkProperties; import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.VpnManager; import android.os.Handler; @@ -76,7 +81,10 @@ public class SecurityControllerImpl implements SecurityController { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final NetworkRequest REQUEST = - new NetworkRequest.Builder().clearCapabilities().build(); + new NetworkRequest.Builder() + .clearCapabilities() + .addTransportType(TRANSPORT_VPN) + .build(); private static final int NO_NETWORK = -1; private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; @@ -99,6 +107,8 @@ public class SecurityControllerImpl implements SecurityController { private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>(); private int mCurrentUserId; private int mVpnUserId; + @GuardedBy("mNetworkProperties") + private final SparseArray<NetworkProperties> mNetworkProperties = new SparseArray<>(); // Key: userId, Value: whether the user has CACerts installed // Needs to be cached here since the query has to be asynchronous @@ -162,6 +172,21 @@ public class SecurityControllerImpl implements SecurityController { pw.print(mCurrentVpns.valueAt(i).user); } pw.println("}"); + pw.print(" mNetworkProperties={"); + synchronized (mNetworkProperties) { + for (int i = 0; i < mNetworkProperties.size(); ++i) { + if (i > 0) { + pw.print(", "); + } + pw.print(mNetworkProperties.keyAt(i)); + pw.print("={"); + pw.print(mNetworkProperties.valueAt(i).interfaceName); + pw.print(", "); + pw.print(mNetworkProperties.valueAt(i).validated); + pw.print("}"); + } + } + pw.println("}"); } @Override @@ -304,6 +329,26 @@ public class SecurityControllerImpl implements SecurityController { } @Override + public boolean isVpnValidated() { + // Prioritize reporting the network status of the parent user. + final VpnConfig primaryVpnConfig = mCurrentVpns.get(mVpnUserId); + if (primaryVpnConfig != null) { + return getVpnValidationStatus(primaryVpnConfig); + } + // Identify any Unvalidated status in each active VPN network within other profiles. + for (int profileId : mUserManager.getEnabledProfileIds(mVpnUserId)) { + final VpnConfig vpnConfig = mCurrentVpns.get(profileId); + if (vpnConfig == null) { + continue; + } + if (!getVpnValidationStatus(vpnConfig)) { + return false; + } + } + return true; + } + + @Override public boolean hasCACertInCurrentUser() { Boolean hasCACerts = mHasCACerts.get(mCurrentUserId); return hasCACerts != null && hasCACerts.booleanValue(); @@ -491,11 +536,74 @@ public class SecurityControllerImpl implements SecurityController { @Override public void onLost(Network network) { if (DEBUG) Log.d(TAG, "onLost " + network.getNetId()); + synchronized (mNetworkProperties) { + mNetworkProperties.delete(network.getNetId()); + } updateState(); fireCallbacks(); }; + + + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { + if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + network.getNetId()); + final NetworkProperties properties; + synchronized (mNetworkProperties) { + properties = mNetworkProperties.get(network.getNetId()); + } + // When a new network appears, the system first notifies the application about + // its capabilities through onCapabilitiesChanged. This initial notification + // will be skipped because the interface information is included in the + // subsequent onLinkPropertiesChanged call. After validating the network, the + // system might send another onCapabilitiesChanged notification if the network + // becomes validated. + if (properties == null) { + return; + } + final boolean validated = nc.hasCapability(NET_CAPABILITY_VALIDATED); + if (properties.validated != validated) { + properties.validated = validated; + fireCallbacks(); + } + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + if (DEBUG) Log.d(TAG, "onLinkPropertiesChanged " + network.getNetId()); + final String interfaceName = linkProperties.getInterfaceName(); + if (interfaceName == null) { + Log.w(TAG, "onLinkPropertiesChanged event with null interface"); + return; + } + synchronized (mNetworkProperties) { + final NetworkProperties properties = mNetworkProperties.get(network.getNetId()); + if (properties == null) { + mNetworkProperties.put( + network.getNetId(), + new NetworkProperties(interfaceName, false)); + } else { + properties.interfaceName = interfaceName; + } + } + } }; + /** + * Retrieve the validation status of the VPN network associated with the given VpnConfig. + */ + private boolean getVpnValidationStatus(@NonNull VpnConfig vpnConfig) { + synchronized (mNetworkProperties) { + // Find the network has the same interface as the VpnConfig + for (int i = 0; i < mNetworkProperties.size(); ++i) { + if (mNetworkProperties.valueAt(i).interfaceName.equals(vpnConfig.interfaze)) { + return mNetworkProperties.valueAt(i).validated; + } + } + } + // If no matching network is found, consider it validated. + return true; + } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) { @@ -506,4 +614,17 @@ public class SecurityControllerImpl implements SecurityController { } } }; + + /** + * A data class to hold specific Network properties received through the NetworkCallback. + */ + private static class NetworkProperties { + public String interfaceName; + public boolean validated; + + NetworkProperties(@NonNull String interfaceName, boolean validated) { + this.interfaceName = interfaceName; + this.validated = validated; + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java index c35bc69bf15b..bcc9272b45f8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.policy; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -213,7 +214,8 @@ public class SecurityControllerTest extends SysuiTestCase { public void testNetworkRequest() { verify(mConnectivityManager, times(1)).registerNetworkCallback(argThat( (NetworkRequest request) -> - request.equals(new NetworkRequest.Builder().clearCapabilities().build()) + request.equals(new NetworkRequest.Builder() + .clearCapabilities().addTransportType(TRANSPORT_VPN).build()) ), any(NetworkCallback.class)); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt index 021e7dff9120..ac90a45450d0 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt @@ -77,6 +77,8 @@ class FakeSecurityController( override fun isVpnBranded(): Boolean = fakeState.isVpnBranded + override fun isVpnValidated(): Boolean = fakeState.isVpnValidated + override fun getPrimaryVpnName(): String? = fakeState.primaryVpnName override fun getWorkProfileVpnName(): String? = fakeState.workProfileVpnName @@ -110,6 +112,7 @@ class FakeSecurityController( var isVpnEnabled: Boolean = false, var isVpnRestricted: Boolean = false, var isVpnBranded: Boolean = false, + var isVpnValidated: Boolean = false, var primaryVpnName: String? = null, var workProfileVpnName: String? = null, var hasCACertInCurrentUser: Boolean = false, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java index 76199e3168da..791165d97795 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java @@ -109,6 +109,11 @@ public class FakeSecurityController extends BaseLeakChecker<SecurityControllerCa } @Override + public boolean isVpnValidated() { + return false; + } + + @Override public String getPrimaryVpnName() { return null; } diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index 926d7a4d3ea6..5cdfca7392e3 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -48,6 +48,8 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.am.DropboxRateLimiter; +import com.android.server.os.TombstoneProtos; +import com.android.server.os.TombstoneProtos.Tombstone; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -60,11 +62,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; +import java.util.AbstractMap; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * Performs a number of miscellaneous, non-system-critical actions @@ -327,12 +332,12 @@ public class BootReceiver extends BroadcastReceiver { * * @param ctx Context * @param tombstone path to the tombstone - * @param proto whether the tombstone is stored as proto + * @param tombstoneProto the parsed proto tombstone * @param processName the name of the process corresponding to the tombstone * @param tmpFileLock the lock for reading/writing tmp files */ public static void addTombstoneToDropBox( - Context ctx, File tombstone, boolean proto, String processName, + Context ctx, File tombstone, Tombstone tombstoneProto, String processName, ReentrantLock tmpFileLock) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); if (db == null) { @@ -342,31 +347,33 @@ public class BootReceiver extends BroadcastReceiver { // Check if we should rate limit and abort early if needed. DropboxRateLimiter.RateLimitResult rateLimitResult = - sDropboxRateLimiter.shouldRateLimit( - proto ? TAG_TOMBSTONE_PROTO_WITH_HEADERS : TAG_TOMBSTONE, processName); + sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE_PROTO_WITH_HEADERS, processName); if (rateLimitResult.shouldRateLimit()) return; HashMap<String, Long> timestamps = readTimestamps(); try { - if (proto) { - if (recordFileTimestamp(tombstone, timestamps)) { - // We need to attach the count indicating the number of dropped dropbox entries - // due to rate limiting. Do this by enclosing the proto tombsstone in a - // container proto that has the dropped entry count and the proto tombstone as - // bytes (to avoid the complexity of reading and writing nested protos). - tmpFileLock.lock(); - try { - addAugmentedProtoToDropbox(tombstone, db, rateLimitResult); - } finally { - tmpFileLock.unlock(); - } + // Remove the memory data from the proto. + Tombstone tombstoneProtoWithoutMemory = removeMemoryFromTombstone(tombstoneProto); + + final byte[] tombstoneBytes = tombstoneProtoWithoutMemory.toByteArray(); + + // Use JNI to call the c++ proto to text converter and add the headers to the tombstone. + String tombstoneWithoutMemory = new StringBuilder(getBootHeadersToLogAndUpdate()) + .append(rateLimitResult.createHeader()) + .append(getTombstoneText(tombstoneBytes)) + .toString(); + + // Add the tombstone without memory data to dropbox. + db.addText(TAG_TOMBSTONE, tombstoneWithoutMemory); + + // Add the tombstone proto to dropbox. + if (recordFileTimestamp(tombstone, timestamps)) { + tmpFileLock.lock(); + try { + addAugmentedProtoToDropbox(tombstone, tombstoneBytes, db, rateLimitResult); + } finally { + tmpFileLock.unlock(); } - } else { - // Add the header indicating how many events have been dropped due to rate limiting. - final String headers = getBootHeadersToLogAndUpdate() - + rateLimitResult.createHeader(); - addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, - TAG_TOMBSTONE); } } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); @@ -375,11 +382,8 @@ public class BootReceiver extends BroadcastReceiver { } private static void addAugmentedProtoToDropbox( - File tombstone, DropBoxManager db, + File tombstone, byte[] tombstoneBytes, DropBoxManager db, DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException { - // Read the proto tombstone file as bytes. - final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); - final File tombstoneProtoWithHeaders = File.createTempFile( tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); Files.setPosixFilePermissions( @@ -412,6 +416,8 @@ public class BootReceiver extends BroadcastReceiver { } } + private static native String getTombstoneText(byte[] tombstoneBytes); + private static void addLastkToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String footers, String filename, int maxSize, @@ -429,6 +435,31 @@ public class BootReceiver extends BroadcastReceiver { addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag); } + /** Removes memory information from the Tombstone proto. */ + @VisibleForTesting + public static Tombstone removeMemoryFromTombstone(Tombstone tombstoneProto) { + Tombstone.Builder tombstoneBuilder = tombstoneProto.toBuilder() + .clearMemoryMappings() + .clearThreads() + .putAllThreads(tombstoneProto.getThreadsMap().entrySet() + .stream() + .map(BootReceiver::clearMemoryDump) + .collect(Collectors.toMap(e->e.getKey(), e->e.getValue()))); + + if (tombstoneProto.hasSignalInfo()) { + tombstoneBuilder.setSignalInfo( + tombstoneProto.getSignalInfo().toBuilder().clearFaultAdjacentMetadata()); + } + + return tombstoneBuilder.build(); + } + + private static AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread> clearMemoryDump( + Map.Entry<Integer, TombstoneProtos.Thread> e) { + return new AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread>( + e.getKey(), e.getValue().toBuilder().clearMemoryDump().build()); + } + private static void addFileToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String filename, int maxSize, String tag) throws IOException { diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index a2d7a81b3289..5335cc310af1 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -43,3 +43,6 @@ per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timez per-file TelephonyRegistry.java = file:/telephony/OWNERS per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS per-file VcnManagementService.java = file:/services/core/java/com/android/server/vcn/OWNERS + +# SystemConfig +per-file SystemConfig.java = file:/PACKAGE_MANAGER_OWNERS diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 490aa1f3144c..f952c99d0100 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -1341,8 +1341,8 @@ class StorageManagerService extends IStorageManager.Stub final int flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; for (UserInfo user : users) { - prepareUserStorageInternal(fromVolumeUuid, user.id, user.serialNumber, flags); - prepareUserStorageInternal(toVolumeUuid, user.id, user.serialNumber, flags); + prepareUserStorageInternal(fromVolumeUuid, user.id, flags); + prepareUserStorageInternal(toVolumeUuid, user.id, flags); } } @@ -3210,7 +3210,7 @@ class StorageManagerService extends IStorageManager.Stub @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) { + public void createUserStorageKeys(int userId, boolean ephemeral) { super.createUserStorageKeys_enforcePermission(); @@ -3255,8 +3255,7 @@ class StorageManagerService extends IStorageManager.Stub /* Only for use by LockSettingsService */ @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void unlockCeStorage(@UserIdInt int userId, int serialNumber, byte[] secret) - throws RemoteException { + public void unlockCeStorage(@UserIdInt int userId, byte[] secret) throws RemoteException { super.unlockCeStorage_enforcePermission(); if (StorageManager.isFileEncrypted()) { @@ -3327,25 +3326,25 @@ class StorageManagerService extends IStorageManager.Stub continue; } - prepareUserStorageInternal(vol.fsUuid, user.id, user.serialNumber, flags); + prepareUserStorageInternal(vol.fsUuid, user.id, flags); } } @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { + public void prepareUserStorage(String volumeUuid, int userId, int flags) { super.prepareUserStorage_enforcePermission(); try { - prepareUserStorageInternal(volumeUuid, userId, serialNumber, flags); + prepareUserStorageInternal(volumeUuid, userId, flags); } catch (Exception e) { throw new RuntimeException(e); } } - private void prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber, - int flags) throws Exception { + private void prepareUserStorageInternal(String volumeUuid, int userId, int flags) + throws Exception { try { mVold.prepareUserStorage(volumeUuid, userId, flags); // After preparing user storage, we should check if we should mount data mirror again, diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index bca2d60761d1..b04c7c52efbd 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -316,6 +316,11 @@ public class SystemConfig { private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>(); private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>(); + // These packages will be set as 'prevent disable', where they are no longer possible + // for the end user to disable via settings. This flag should only be used for packages + // which meet the 'force or keep enabled apps' policy. + private final ArrayList<String> mPreventUserDisablePackages = new ArrayList<>(); + // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService(). private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>(); private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>(); @@ -501,6 +506,10 @@ public class SystemConfig { return mAppDataIsolationWhitelistedApps; } + public @NonNull ArrayList<String> getPreventUserDisablePackages() { + return mPreventUserDisablePackages; + } + /** * Gets map of packagesNames to userTypes, dictating on which user types each package should be * initially installed, and then removes this map from SystemConfig. @@ -1303,6 +1312,16 @@ public class SystemConfig { } XmlUtils.skipCurrentTag(parser); } break; + case "prevent-disable": { + String pkgname = parser.getAttributeValue(null, "package"); + if (pkgname == null) { + Slog.w(TAG, "<" + name + "> without package in " + permFile + + " at " + parser.getPositionDescription()); + } else { + mPreventUserDisablePackages.add(pkgname); + } + XmlUtils.skipCurrentTag(parser); + } break; case "install-in-user-type": { // NB: We allow any directory permission to declare install-in-user-type. readInstallInUserType(parser, diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 0c2eee5aebbe..ad090829a2f6 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -2118,11 +2118,10 @@ public class LockSettingsService extends ILockSettings.Stub { Slogf.d(TAG, "CE storage for user %d is already unlocked", userId); return; } - final UserInfo userInfo = mUserManager.getUserInfo(userId); final String userType = isUserSecure(userId) ? "secured" : "unsecured"; final byte[] secret = sp.deriveFileBasedEncryptionKey(); try { - mStorageManager.unlockCeStorage(userId, userInfo.serialNumber, secret); + mStorageManager.unlockCeStorage(userId, secret); Slogf.i(TAG, "Unlocked CE storage for %s user %d", userType, userId); } catch (RemoteException e) { Slogf.wtf(TAG, e, "Failed to unlock CE storage for %s user %d", userType, userId); diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index ab0d0d2626db..b7e737448d2d 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -41,14 +41,13 @@ import android.system.Os; import android.system.StructStat; import android.util.Slog; import android.util.SparseArray; -import android.util.proto.ProtoInputStream; -import android.util.proto.ProtoParseException; import com.android.internal.annotations.GuardedBy; import com.android.server.BootReceiver; import com.android.server.ServiceThread; import com.android.server.os.TombstoneProtos.Cause; import com.android.server.os.TombstoneProtos.Tombstone; +import com.android.server.os.protobuf.CodedInputStream; import libcore.io.IoUtils; @@ -128,18 +127,21 @@ public final class NativeTombstoneManager { return; } - String processName = "UNKNOWN"; final boolean isProtoFile = filename.endsWith(".pb"); - File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb"); + if (!isProtoFile) { + return; + } - Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile); + Optional<ParsedTombstone> parsedTombstone = handleProtoTombstone(path, true); if (parsedTombstone.isPresent()) { - processName = parsedTombstone.get().getProcessName(); + BootReceiver.addTombstoneToDropBox( + mContext, path, parsedTombstone.get().getTombstone(), + parsedTombstone.get().getProcessName(), mTmpFileLock); } - BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock); } - private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) { + private Optional<ParsedTombstone> handleProtoTombstone( + File path, boolean addToList) { final String filename = path.getName(); if (!filename.endsWith(".pb")) { Slog.w(TAG, "unexpected tombstone name: " + path); @@ -169,7 +171,7 @@ public final class NativeTombstoneManager { return Optional.empty(); } - final Optional<TombstoneFile> parsedTombstone = TombstoneFile.parse(pfd); + final Optional<ParsedTombstone> parsedTombstone = TombstoneFile.parse(pfd); if (!parsedTombstone.isPresent()) { IoUtils.closeQuietly(pfd); return Optional.empty(); @@ -182,7 +184,7 @@ public final class NativeTombstoneManager { previous.dispose(); } - mTombstones.put(number, parsedTombstone.get()); + mTombstones.put(number, parsedTombstone.get().getTombstoneFile()); } } @@ -330,6 +332,27 @@ public final class NativeTombstoneManager { } } + static class ParsedTombstone { + TombstoneFile mTombstoneFile; + Tombstone mTombstone; + ParsedTombstone(TombstoneFile tombstoneFile, Tombstone tombstone) { + mTombstoneFile = tombstoneFile; + mTombstone = tombstone; + } + + public String getProcessName() { + return mTombstoneFile.getProcessName(); + } + + public TombstoneFile getTombstoneFile() { + return mTombstoneFile; + } + + public Tombstone getTombstone() { + return mTombstone; + } + } + static class TombstoneFile { final ParcelFileDescriptor mPfd; @@ -412,67 +435,21 @@ public final class NativeTombstoneManager { } } - static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) { - final FileInputStream is = new FileInputStream(pfd.getFileDescriptor()); - final ProtoInputStream stream = new ProtoInputStream(is); - - int pid = 0; - int uid = 0; - String processName = null; - String crashReason = ""; - String selinuxLabel = ""; - - try { - while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (stream.getFieldNumber()) { - case (int) Tombstone.PID: - pid = stream.readInt(Tombstone.PID); - break; - - case (int) Tombstone.UID: - uid = stream.readInt(Tombstone.UID); - break; - - case (int) Tombstone.COMMAND_LINE: - if (processName == null) { - processName = stream.readString(Tombstone.COMMAND_LINE); - } - break; + static Optional<ParsedTombstone> parse(ParcelFileDescriptor pfd) { + Tombstone tombstoneProto; + try (FileInputStream is = new FileInputStream(pfd.getFileDescriptor())) { + final byte[] tombstoneBytes = is.readAllBytes(); - case (int) Tombstone.CAUSES: - if (!crashReason.equals("")) { - // Causes appear in decreasing order of likelihood. For now we only - // want the most likely crash reason here, so ignore all others. - break; - } - long token = stream.start(Tombstone.CAUSES); - cause: - while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (stream.getFieldNumber()) { - case (int) Cause.HUMAN_READABLE: - crashReason = stream.readString(Cause.HUMAN_READABLE); - break cause; - - default: - break; - } - } - stream.end(token); - break; - - case (int) Tombstone.SELINUX_LABEL: - selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL); - break; - - default: - break; - } - } - } catch (IOException | ProtoParseException ex) { + tombstoneProto = Tombstone.parseFrom( + CodedInputStream.newInstance(tombstoneBytes)); + } catch (IOException ex) { Slog.e(TAG, "Failed to parse tombstone", ex); return Optional.empty(); } + int pid = tombstoneProto.getPid(); + int uid = tombstoneProto.getUid(); + if (!UserHandle.isApp(uid)) { Slog.e(TAG, "Tombstone's UID (" + uid + ") not an app, ignoring"); return Optional.empty(); @@ -489,6 +466,7 @@ public final class NativeTombstoneManager { final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); + String selinuxLabel = tombstoneProto.getSelinuxLabel(); if (!selinuxLabel.startsWith("u:r:untrusted_app")) { Slog.e(TAG, "Tombstone has invalid selinux label (" + selinuxLabel + "), ignoring"); return Optional.empty(); @@ -500,11 +478,30 @@ public final class NativeTombstoneManager { result.mAppId = appId; result.mPid = pid; result.mUid = uid; - result.mProcessName = processName == null ? "" : processName; + result.mProcessName = getCmdLineProcessName(tombstoneProto); result.mTimestampMs = timestampMs; - result.mCrashReason = crashReason; + result.mCrashReason = getCrashReason(tombstoneProto); - return Optional.of(result); + return Optional.of(new ParsedTombstone(result, tombstoneProto)); + } + + private static String getCmdLineProcessName(Tombstone tombstoneProto) { + for (String cmdline : tombstoneProto.getCommandLineList()) { + if (cmdline != null) { + return cmdline; + } + } + return ""; + } + + private static String getCrashReason(Tombstone tombstoneProto) { + for (Cause cause : tombstoneProto.getCausesList()) { + if (cause.getHumanReadable() != null + && !cause.getHumanReadable().equals("")) { + return cause.getHumanReadable(); + } + } + return ""; } public IParcelFileDescriptorRetriever getPfdRetriever() { diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index 89619232eb04..d9d708776442 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -193,7 +193,7 @@ public final class StorageEventHelper extends StorageEventListener { } try { - sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags); + sm.prepareUserStorage(volumeUuid, user.id, flags); synchronized (mPm.mInstallLock) { appDataHelper.reconcileAppsDataLI(volumeUuid, user.id, flags, true /* migrateAppData */); diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 8adb5661ad1d..4c42c2dd0850 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -92,7 +92,7 @@ class UserDataPreparer { volumeUuid, userId, flags, isNewUser); try { // Prepare CE and/or DE storage. - storage.prepareUserStorage(volumeUuid, userId, userSerial, flags); + storage.prepareUserStorage(volumeUuid, userId, flags); // Ensure that the data directories of a removed user with the same ID are not being // reused. New users must get fresh data directories, to avoid leaking data. diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 062d797937c0..8fcc921b3198 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4920,7 +4920,7 @@ public class UserManagerService extends IUserManager.Stub { t.traceBegin("createUserStorageKeys"); final StorageManager storage = mContext.getSystemService(StorageManager.class); - storage.createUserStorageKeys(userId, userInfo.serialNumber, userInfo.isEphemeral()); + storage.createUserStorageKeys(userId, userInfo.isEphemeral()); t.traceEnd(); // Only prepare DE storage here. CE storage will be prepared later, when the user is diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 720c773a032a..deff3d793854 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -1231,8 +1231,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba ipw.println(); } - PackageWatchdog.getInstance(mContext).dump(ipw); }); + PackageWatchdog.getInstance(mContext).dump(ipw); } @AnyThread diff --git a/services/core/java/com/android/server/trust/TEST_MAPPING b/services/core/java/com/android/server/trust/TEST_MAPPING index fa46acd9c39b..0de7c28c209b 100644 --- a/services/core/java/com/android/server/trust/TEST_MAPPING +++ b/services/core/java/com/android/server/trust/TEST_MAPPING @@ -12,6 +12,19 @@ ] } ], + "postsubmit": [ + { + "name": "FrameworksMockingServicesTests", + "options": [ + { + "include-filter": "com.android.server.trust" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] + } + ], "trust-tablet": [ { "name": "TrustTests", diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index d2d2a0cba085..ed9445c26740 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -1442,6 +1442,13 @@ public class TrustManagerService extends SystemService { if (biometricManager == null) { return new long[0]; } + if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2() + && mLockPatternUtils.isProfileWithUnifiedChallenge(userId)) { + // Profiles with unified challenge have their own set of biometrics, but the device + // unlock happens via the parent user. In this case Keystore needs to be given the list + // of biometric SIDs from the parent user, not the profile. + userId = resolveProfileParent(userId); + } return biometricManager.getAuthenticatorIds(userId); } @@ -1933,7 +1940,8 @@ public class TrustManagerService extends SystemService { }; } - private final PackageMonitor mPackageMonitor = new PackageMonitor() { + @VisibleForTesting + final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { refreshAgentList(UserHandle.USER_ALL); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index e51afbe20717..0bc60cd8efb5 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4708,6 +4708,7 @@ class Task extends TaskFragment { } if (top.isAttached()) { top.setWindowingMode(WINDOWING_MODE_UNDEFINED); + top.mWaitForEnteringPinnedMode = false; } } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 8cd55c7dd506..591a55972b81 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -37,6 +37,7 @@ cc_library_static { "com_android_server_adb_AdbDebuggingManager.cpp", "com_android_server_am_BatteryStatsService.cpp", "com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp", + "com_android_server_BootReceiver.cpp", "com_android_server_ConsumerIrService.cpp", "com_android_server_companion_virtual_InputController.cpp", "com_android_server_devicepolicy_CryptoTestHelper.cpp", @@ -91,6 +92,16 @@ cc_library_static { header_libs: [ "bionic_libc_platform_headers", ], + + static_libs: [ + "libunwindstack", + ], + + whole_static_libs: [ + "libdebuggerd_tombstone_proto_to_text", + ], + + runtime_libs: ["libdexfile"], } cc_defaults { diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index d4f6312d19d9..33d3686ee9ce 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -32,3 +32,7 @@ per-file com_android_server_companion_virtual_InputController.cpp = file:/servic # Bug component : 158088 = per-file *AnrTimer* per-file *AnrTimer* = file:/PERFORMANCE_OWNERS + +# Bug component : 158088 = per-file com_android_server_utils_AnrTimer*.java +per-file com_android_server_utils_AnrTimer*.java = file:/PERFORMANCE_OWNERS +per-file com_android_server_BootReceiver.cpp = file:/STABILITY_OWNERS diff --git a/services/core/jni/com_android_server_BootReceiver.cpp b/services/core/jni/com_android_server_BootReceiver.cpp new file mode 100644 index 000000000000..3892d284dafb --- /dev/null +++ b/services/core/jni/com_android_server_BootReceiver.cpp @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#include <libdebuggerd/tombstone.h> +#include <nativehelper/JNIHelp.h> + +#include <sstream> + +#include "jni.h" +#include "tombstone.pb.h" + +namespace android { + +static void writeToString(std::stringstream& ss, const std::string& line, bool should_log) { + ss << line << std::endl; +} + +static jstring com_android_server_BootReceiver_getTombstoneText(JNIEnv* env, jobject, + jbyteArray tombstoneBytes) { + Tombstone tombstone; + tombstone.ParseFromArray(env->GetByteArrayElements(tombstoneBytes, 0), + env->GetArrayLength(tombstoneBytes)); + + std::stringstream tombstoneString; + + tombstone_proto_to_text(tombstone, + std::bind(&writeToString, std::ref(tombstoneString), + std::placeholders::_1, std::placeholders::_2)); + + return env->NewStringUTF(tombstoneString.str().c_str()); +} + +static const JNINativeMethod sMethods[] = { + /* name, signature, funcPtr */ + {"getTombstoneText", "([B)Ljava/lang/String;", + (jstring*)com_android_server_BootReceiver_getTombstoneText}, +}; + +int register_com_android_server_BootReceiver(JNIEnv* env) { + return jniRegisterNativeMethods(env, "com/android/server/BootReceiver", sMethods, + NELEM(sMethods)); +} + +} // namespace android diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index a87902fe03c5..e7de081bd5f8 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -63,6 +63,7 @@ int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env); int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env); int register_android_server_companion_virtual_InputController(JNIEnv* env); int register_android_server_app_GameManagerService(JNIEnv* env); +int register_com_android_server_BootReceiver(JNIEnv* env); int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env); int register_com_android_server_display_DisplayControl(JNIEnv* env); int register_com_android_server_SystemClockTime(JNIEnv* env); @@ -122,6 +123,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_sensor_SensorService(vm, env); register_android_server_companion_virtual_InputController(env); register_android_server_app_GameManagerService(env); + register_com_android_server_BootReceiver(env); register_com_android_server_wm_TaskFpsCallbackController(env); register_com_android_server_display_DisplayControl(env); register_com_android_server_SystemClockTime(env); diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java index 6e82907d4361..fd21a326b640 100644 --- a/services/java/com/android/server/SystemConfigService.java +++ b/services/java/com/android/server/SystemConfigService.java @@ -21,6 +21,8 @@ import static java.util.stream.Collectors.toMap; import android.Manifest; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManagerInternal; +import android.os.Binder; import android.os.ISystemConfig; import android.util.ArrayMap; import android.util.ArraySet; @@ -108,6 +110,15 @@ public class SystemConfigService extends SystemService { "Caller must hold " + Manifest.permission.QUERY_ALL_PACKAGES); return new ArrayList<>(SystemConfig.getInstance().getDefaultVrComponents()); } + + @Override + public List<String> getPreventUserDisablePackages() { + PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); + return SystemConfig.getInstance().getPreventUserDisablePackages().stream() + .filter(preventUserDisablePackage -> + pmi.canQueryPackage(Binder.getCallingUid(), preventUserDisablePackage)) + .collect(toList()); + } }; public SystemConfigService(Context context) { diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp index 52eae21f9e66..a70802ad3337 100644 --- a/services/robotests/Android.bp +++ b/services/robotests/Android.bp @@ -57,9 +57,13 @@ android_robolectric_test { ], static_libs: [ "androidx.test.ext.truth", + "Settings-robo-testutils", + "SettingsLib-robo-testutils", ], instrumentation_for: "FrameworksServicesLib", + + upstream: true, } filegroup { diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp index 66ee696250c9..fba2cad90f00 100644 --- a/services/robotests/backup/Android.bp +++ b/services/robotests/backup/Android.bp @@ -56,6 +56,8 @@ android_robolectric_test { // Include the testing libraries libs: [ "mockito-robolectric-prebuilt", + "Settings-robo-testutils", + "SettingsLib-robo-testutils", "platform-test-annotations", "testng", "truth", @@ -63,4 +65,6 @@ android_robolectric_test { instrumentation_for: "BackupFrameworksServicesLib", + upstream: true, + } diff --git a/services/robotests/backup/config/robolectric.properties b/services/robotests/backup/config/robolectric.properties index 850557a9b693..1ebf6d423fe2 100644 --- a/services/robotests/backup/config/robolectric.properties +++ b/services/robotests/backup/config/robolectric.properties @@ -1 +1,3 @@ -sdk=NEWEST_SDK
\ No newline at end of file +sdk=NEWEST_SDK +looperMode=LEGACY +shadows=com.android.server.testing.shadows.FrameworkShadowLooper diff --git a/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java index ee5a534fe005..6839a06a0d9a 100644 --- a/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java +++ b/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java @@ -57,6 +57,7 @@ import java.nio.file.attribute.FileTime; ShadowBackupDataOutput.class, ShadowEnvironment.class, ShadowFullBackup.class, + ShadowSigningInfo.class, }) public class AppMetadataBackupWriterTest { private static final String TEST_PACKAGE = "com.test.package"; diff --git a/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java b/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java new file mode 100644 index 000000000000..53d807c2d3c9 --- /dev/null +++ b/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.fullbackup; + +import static android.os.Build.VERSION_CODES.P; + +import android.content.pm.SigningInfo; + +import org.robolectric.annotation.Implements; + +@Implements(value = SigningInfo.class, minSdk = P) +public class ShadowSigningInfo { +} diff --git a/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java b/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java index 4949091646dd..009276359209 100644 --- a/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java +++ b/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java @@ -35,6 +35,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.LooperMode; import org.robolectric.shadows.ShadowLooper; import java.util.concurrent.CountDownLatch; @@ -45,6 +46,7 @@ import java.util.concurrent.TimeUnit; */ @RunWith(RobolectricTestRunner.class) @Presubmit +@LooperMode(LooperMode.Mode.LEGACY) public class NtpNetworkTimeHelperTest { private static final long MOCK_NTP_TIME = 1519930775453L; diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java index 16d16cda42ed..3681bd4c6588 100644 --- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java +++ b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java @@ -21,12 +21,15 @@ import android.os.Looper; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.annotation.RealObject; +import org.robolectric.shadows.LooperShadowPicker; +import org.robolectric.shadows.ShadowLegacyLooper; import org.robolectric.shadows.ShadowLooper; +import org.robolectric.shadows.ShadowPausedLooper; import java.util.Optional; -@Implements(value = Looper.class) -public class FrameworkShadowLooper extends ShadowLooper { +@Implements(value = Looper.class, shadowPicker = FrameworkShadowLooper.Picker.class) +public class FrameworkShadowLooper extends ShadowLegacyLooper { @RealObject private Looper mLooper; private Optional<Boolean> mIsCurrentThread = Optional.empty(); @@ -45,4 +48,10 @@ public class FrameworkShadowLooper extends ShadowLooper { } return Thread.currentThread() == mLooper.getThread(); } + + public static class Picker extends LooperShadowPicker<ShadowLooper> { + public Picker() { + super(FrameworkShadowLooper.class, ShadowPausedLooper.class); + } + } } diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java index 4a9948668bc4..1da67597643f 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java +++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java @@ -95,7 +95,6 @@ public class ShadowApplicationPackageManager sPackageAppEnabledStates.put(packageName, Integer.valueOf(newState)); // flags unused here. } - @Override protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) throws NameNotFoundException { if (!sPackageInfos.containsKey(packageName)) { diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java index e5be4d9aa755..9e11fa2f0bdf 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java @@ -50,7 +50,7 @@ import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; -// atest PackageManagerServiceTest:com.android.server.pm.UserDataPreparerTest +// atest PackageManagerServiceServerTests:com.android.server.pm.UserDataPreparerTest @RunWith(AndroidJUnit4.class) @Presubmit @SmallTest @@ -99,7 +99,7 @@ public class UserDataPreparerTest { systemDeDir.mkdirs(); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_DE); verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), - eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE)); + eq(StorageManager.FLAG_STORAGE_DE)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE)); int serialNumber = UserDataPreparer.getSerialNumber(userDeDir); @@ -116,7 +116,7 @@ public class UserDataPreparerTest { systemCeDir.mkdirs(); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), - eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE)); + eq(StorageManager.FLAG_STORAGE_CE)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE)); int serialNumber = UserDataPreparer.getSerialNumber(userCeDir); @@ -129,7 +129,7 @@ public class UserDataPreparerTest { public void testPrepareUserData_forNewUser_destroysOnFailure() throws Exception { TEST_USER.lastLoggedInTime = 0; doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) - .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), + .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), @@ -140,7 +140,7 @@ public class UserDataPreparerTest { public void testPrepareUserData_forExistingUser_doesNotDestroyOnFailure() throws Exception { TEST_USER.lastLoggedInTime = System.currentTimeMillis(); doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) - .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), + .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); verify(mStorageManagerMock, never()).destroyUserStorage(isNull(String.class), diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java index c42c735e3c9d..37ca09d9fa27 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -32,6 +32,7 @@ import static com.google.common.truth.Truth.assertThat; import android.Manifest; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.IActivityManager; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustListener; import android.app.trust.ITrustManager; @@ -45,7 +46,8 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; -import android.net.Uri; +import android.hardware.biometrics.BiometricManager; +import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -53,7 +55,12 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; +import android.security.Authorization; +import android.security.authorization.IKeystoreAuthorization; import android.service.trust.TrustAgentService; import android.testing.TestableContext; import android.view.IWindowManager; @@ -83,23 +90,34 @@ public class TrustManagerServiceTest { @Rule public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) + .spyStatic(ActivityManager.class) + .spyStatic(Authorization.class) .mockStatic(ServiceManager.class) .mockStatic(WindowManagerGlobal.class) .build(); @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Rule public final MockContext mMockContext = new MockContext( ApplicationProvider.getApplicationContext()); private static final String URI_SCHEME_PACKAGE = "package"; private static final int TEST_USER_ID = 50; + private static final int PARENT_USER_ID = 60; + private static final int PROFILE_USER_ID = 70; + private static final long[] PARENT_BIOMETRIC_SIDS = new long[] { 600L, 601L }; + private static final long[] PROFILE_BIOMETRIC_SIDS = new long[] { 700L, 701L }; private final ArrayList<ResolveInfo> mTrustAgentResolveInfoList = new ArrayList<>(); private final ArrayList<ComponentName> mKnownTrustAgents = new ArrayList<>(); private final ArrayList<ComponentName> mEnabledTrustAgents = new ArrayList<>(); private @Mock ActivityManager mActivityManager; + private @Mock BiometricManager mBiometricManager; private @Mock DevicePolicyManager mDevicePolicyManager; + private @Mock IKeystoreAuthorization mKeystoreAuthorization; private @Mock LockPatternUtils mLockPatternUtils; private @Mock PackageManager mPackageManager; private @Mock UserManager mUserManager; @@ -113,6 +131,9 @@ public class TrustManagerServiceTest { @Before public void setUp() throws Exception { when(mActivityManager.isUserRunning(TEST_USER_ID)).thenReturn(true); + doReturn(mock(IActivityManager.class)).when(() -> ActivityManager.getService()); + + doReturn(mKeystoreAuthorization).when(() -> Authorization.getService()); when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager); when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true); @@ -146,6 +167,7 @@ public class TrustManagerServiceTest { when(mWindowManager.isKeyguardLocked()).thenReturn(true); mMockContext.addMockSystemService(ActivityManager.class, mActivityManager); + mMockContext.addMockSystemService(BiometricManager.class, mBiometricManager); mMockContext.setMockPackageManager(mPackageManager); mMockContext.addMockSystemService(UserManager.class, mUserManager); doReturn(mWindowManager).when(() -> WindowManagerGlobal.getWindowManagerService()); @@ -257,7 +279,7 @@ public class TrustManagerServiceTest { "com.android/.SystemTrustAgent"); addTrustAgent(newAgentComponentName, /* isSystemApp= */ true); - mMockContext.sendPackageChangedBroadcast(newAgentComponentName); + notifyPackageChanged(newAgentComponentName); assertThat(mEnabledTrustAgents).containsExactly(newAgentComponentName); assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName); @@ -276,7 +298,7 @@ public class TrustManagerServiceTest { "com.android/.SystemTrustAgent"); addTrustAgent(newAgentComponentName, /* isSystemApp= */ true); - mMockContext.sendPackageChangedBroadcast(newAgentComponentName); + notifyPackageChanged(newAgentComponentName); assertThat(mEnabledTrustAgents).containsExactly(defaultTrustAgent); assertThat(mKnownTrustAgents).containsExactly(defaultTrustAgent, newAgentComponentName); @@ -289,7 +311,7 @@ public class TrustManagerServiceTest { "com.user/.UserTrustAgent"); addTrustAgent(newAgentComponentName, /* isSystemApp= */ false); - mMockContext.sendPackageChangedBroadcast(newAgentComponentName); + notifyPackageChanged(newAgentComponentName); assertThat(mEnabledTrustAgents).isEmpty(); assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName); @@ -307,7 +329,7 @@ public class TrustManagerServiceTest { // Simulate user turning off systemTrustAgent2 mLockPatternUtils.setEnabledTrustAgents(List.of(systemTrustAgent1), TEST_USER_ID); - mMockContext.sendPackageChangedBroadcast(systemTrustAgent2); + notifyPackageChanged(systemTrustAgent2); assertThat(mEnabledTrustAgents).containsExactly(systemTrustAgent1); } @@ -322,6 +344,73 @@ public class TrustManagerServiceTest { verify(trustListener).onEnabledTrustAgentsChanged(TEST_USER_ID); } + // Tests that when the device is locked for a managed profile with a *unified* challenge, the + // device locked notification that is sent to Keystore contains the biometric SIDs of the parent + // user, not the profile. This matches the authentication that is needed to unlock the device + // for the profile again. + @Test + @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) + public void testLockDeviceForManagedProfileWithUnifiedChallenge_usesParentBiometricSids() + throws Exception { + setupMocksForProfile(/* unifiedChallenge= */ true); + + when(mWindowManager.isKeyguardLocked()).thenReturn(false); + mTrustManager.reportKeyguardShowingChanged(); + verify(mKeystoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null); + verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null); + + when(mWindowManager.isKeyguardLocked()).thenReturn(true); + mTrustManager.reportKeyguardShowingChanged(); + verify(mKeystoreAuthorization) + .onDeviceLocked(eq(PARENT_USER_ID), eq(PARENT_BIOMETRIC_SIDS)); + verify(mKeystoreAuthorization) + .onDeviceLocked(eq(PROFILE_USER_ID), eq(PARENT_BIOMETRIC_SIDS)); + } + + // Tests that when the device is locked for a managed profile with a *separate* challenge, the + // device locked notification that is sent to Keystore contains the biometric SIDs of the + // profile itself. This matches the authentication that is needed to unlock the device for the + // profile again. + @Test + public void testLockDeviceForManagedProfileWithSeparateChallenge_usesProfileBiometricSids() + throws Exception { + setupMocksForProfile(/* unifiedChallenge= */ false); + + mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, false); + verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null); + + mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, true); + verify(mKeystoreAuthorization) + .onDeviceLocked(eq(PROFILE_USER_ID), eq(PROFILE_BIOMETRIC_SIDS)); + } + + private void setupMocksForProfile(boolean unifiedChallenge) { + UserInfo parent = new UserInfo(PARENT_USER_ID, "parent", UserInfo.FLAG_FULL); + UserInfo profile = new UserInfo(PROFILE_USER_ID, "profile", UserInfo.FLAG_MANAGED_PROFILE); + when(mUserManager.getAliveUsers()).thenReturn(List.of(parent, profile)); + when(mUserManager.getUserInfo(PARENT_USER_ID)).thenReturn(parent); + when(mUserManager.getUserInfo(PROFILE_USER_ID)).thenReturn(profile); + when(mUserManager.getProfileParent(PROFILE_USER_ID)).thenReturn(parent); + when(mUserManager.getEnabledProfileIds(PARENT_USER_ID)) + .thenReturn(new int[] { PROFILE_USER_ID }); + + when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); + when(mLockPatternUtils.isProfileWithUnifiedChallenge(PROFILE_USER_ID)) + .thenReturn(unifiedChallenge); + when(mLockPatternUtils.isManagedProfileWithUnifiedChallenge(PROFILE_USER_ID)) + .thenReturn(unifiedChallenge); + when(mLockPatternUtils.isSeparateProfileChallengeEnabled(PROFILE_USER_ID)) + .thenReturn(!unifiedChallenge); + + when(mBiometricManager.getAuthenticatorIds(PARENT_USER_ID)) + .thenReturn(PARENT_BIOMETRIC_SIDS); + when(mBiometricManager.getAuthenticatorIds(PROFILE_USER_ID)) + .thenReturn(PROFILE_BIOMETRIC_SIDS); + + bootService(); + mService.onUserSwitching(null, new SystemService.TargetUser(parent)); + } + private void addTrustAgent(ComponentName agentComponentName, boolean isSystemApp) { ApplicationInfo applicationInfo = new ApplicationInfo(); if (isSystemApp) { @@ -350,11 +439,16 @@ public class TrustManagerServiceTest { permission, PackageManager.PERMISSION_GRANTED); } + private void notifyPackageChanged(ComponentName changedComponent) { + mService.mPackageMonitor.onPackageChanged( + changedComponent.getPackageName(), + UserHandle.of(TEST_USER_ID).getUid(1234), + new String[] { changedComponent.getClassName() }); + } + /** A mock Context that allows the test process to send protected broadcasts. */ private static final class MockContext extends TestableContext { - private final ArrayList<BroadcastReceiver> mPackageChangedBroadcastReceivers = - new ArrayList<>(); private final ArrayList<BroadcastReceiver> mUserStartedBroadcastReceivers = new ArrayList<>(); @@ -368,9 +462,6 @@ public class TrustManagerServiceTest { UserHandle user, IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler) { - if (filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)) { - mPackageChangedBroadcastReceivers.add(receiver); - } if (filter.hasAction(Intent.ACTION_USER_STARTED)) { mUserStartedBroadcastReceivers.add(receiver); } @@ -378,18 +469,9 @@ public class TrustManagerServiceTest { scheduler); } - void sendPackageChangedBroadcast(ComponentName changedComponent) { - Intent intent = new Intent( - Intent.ACTION_PACKAGE_CHANGED, - Uri.fromParts(URI_SCHEME_PACKAGE, - changedComponent.getPackageName(), /* fragment= */ null)) - .putExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, - new String[]{changedComponent.getClassName()}) - .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID) - .putExtra(Intent.EXTRA_UID, UserHandle.of(TEST_USER_ID).getUid(1234)); - for (BroadcastReceiver receiver : mPackageChangedBroadcastReceivers) { - receiver.onReceive(this, intent); - } + @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + @Nullable String receiverPermission, @Nullable Bundle options) { } void sendUserStartedBroadcast() { diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java new file mode 100644 index 000000000000..523c5c060cf5 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java @@ -0,0 +1,97 @@ +/* + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import android.test.AndroidTestCase; + +import com.android.server.os.TombstoneProtos; +import com.android.server.os.TombstoneProtos.Tombstone; + +public class BootReceiverTest extends AndroidTestCase { + private static final String TAG = "BootReceiverTest"; + + public void testRemoveMemoryFromTombstone() { + Tombstone tombstoneBase = Tombstone.newBuilder() + .setBuildFingerprint("build_fingerprint") + .setRevision("revision") + .setPid(123) + .setTid(23) + .setUid(34) + .setSelinuxLabel("selinux_label") + .addCommandLine("cmd1") + .addCommandLine("cmd2") + .addCommandLine("cmd3") + .setProcessUptime(300) + .setAbortMessage("abort") + .addCauses(TombstoneProtos.Cause.newBuilder() + .setHumanReadable("cause1") + .setMemoryError(TombstoneProtos.MemoryError.newBuilder() + .setTool(TombstoneProtos.MemoryError.Tool.SCUDO) + .setType(TombstoneProtos.MemoryError.Type.DOUBLE_FREE))) + .addLogBuffers(TombstoneProtos.LogBuffer.newBuilder().setName("name").addLogs( + TombstoneProtos.LogMessage.newBuilder() + .setTimestamp("123") + .setMessage("message"))) + .addOpenFds(TombstoneProtos.FD.newBuilder().setFd(1).setPath("path")) + .build(); + + Tombstone tombstoneWithoutMemory = tombstoneBase.toBuilder() + .putThreads(1, TombstoneProtos.Thread.newBuilder() + .setId(1) + .setName("thread1") + .addRegisters(TombstoneProtos.Register.newBuilder().setName("r1").setU64(1)) + .addRegisters(TombstoneProtos.Register.newBuilder().setName("r2").setU64(2)) + .addBacktraceNote("backtracenote1") + .addUnreadableElfFiles("files1") + .setTaggedAddrCtrl(1) + .setPacEnabledKeys(10) + .build()) + .build(); + + Tombstone tombstoneWithMemory = tombstoneBase.toBuilder() + .addMemoryMappings(TombstoneProtos.MemoryMapping.newBuilder() + .setBeginAddress(1) + .setEndAddress(100) + .setOffset(10) + .setRead(true) + .setWrite(true) + .setExecute(false) + .setMappingName("mapping") + .setBuildId("build") + .setLoadBias(70)) + .putThreads(1, TombstoneProtos.Thread.newBuilder() + .setId(1) + .setName("thread1") + .addRegisters(TombstoneProtos.Register.newBuilder().setName("r1").setU64(1)) + .addRegisters(TombstoneProtos.Register.newBuilder().setName("r2").setU64(2)) + .addBacktraceNote("backtracenote1") + .addUnreadableElfFiles("files1") + .addMemoryDump(TombstoneProtos.MemoryDump.newBuilder() + .setRegisterName("register1") + .setMappingName("mapping") + .setBeginAddress(10)) + .setTaggedAddrCtrl(1) + .setPacEnabledKeys(10) + .build()) + .build(); + + assertThat(BootReceiver.removeMemoryFromTombstone(tombstoneWithMemory)) + .isEqualTo(tombstoneWithoutMemory); + } +} diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index d26d67107001..f04a4e6a8b40 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -756,8 +756,7 @@ public class UserControllerTest { mUserController.startUser(TEST_USER_ID, USER_START_MODE_BACKGROUND); - verify(mInjector.mStorageManagerMock, never()) - .unlockCeStorage(eq(TEST_USER_ID), anyInt(), any()); + verify(mInjector.mStorageManagerMock, never()).unlockCeStorage(eq(TEST_USER_ID), any()); } @Test diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index f5d50d173466..6986cab72f56 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -305,9 +305,9 @@ public abstract class BaseLockSettingsServiceTests { doAnswer(invocation -> { Object[] args = invocation.getArguments(); mStorageManager.unlockCeStorage(/* userId= */ (int) args[0], - /* secret= */ (byte[]) args[2]); + /* secret= */ (byte[]) args[1]); return null; - }).when(sm).unlockCeStorage(anyInt(), anyInt(), any()); + }).when(sm).unlockCeStorage(anyInt(), any()); doAnswer(invocation -> { Object[] args = invocation.getArguments(); |