Merge "Update ukey2 references" into main
diff --git a/Android.bp b/Android.bp
index ebdb1a1..5f02a15 100644
--- a/Android.bp
+++ b/Android.bp
@@ -205,6 +205,7 @@
"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 @@
lint: {
baseline_filename: "lint-baseline.xml",
},
+ apex_available: ["com.android.wifi"],
}
filegroup {
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index e7adf20..d03bbd2 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -34,7 +34,6 @@
":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 0000000..a7ecb4d
--- /dev/null
+++ b/STABILITY_OWNERS
@@ -0,0 +1,2 @@
+gaillard@google.com
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
index eef3d27..8338c33 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 4f3bc27..4127f99 100644
--- a/WEAR_OWNERS
+++ b/WEAR_OWNERS
@@ -4,3 +4,9 @@
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 53988cd..0084126 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -458,3 +458,12 @@
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 ce5f995..0000000
--- 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 28b2d4b..ef1fa60 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -900,10 +900,19 @@
],
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 c600df1..48f58c0 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29120,6 +29120,8 @@
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 @@
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 4c2e4fc..8eca0fe 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10925,7 +10925,7 @@
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 f33d299..4823f44 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1311,8 +1311,9 @@
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 f6beec1..85879ac 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -86,4 +86,5 @@
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 191385a..f4b4604 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -43,4 +43,7 @@
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 8d75cac..f03fc0a 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -112,6 +112,9 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
}
}
+ /** 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 f407fb7..979855e 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -332,6 +332,19 @@
*/
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 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 @@
@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 @@
@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 @@
@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 @@
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1399,7 +1484,7 @@
@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 @@
@UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1529,7 +1614,7 @@
@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 void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1607,7 +1692,7 @@
* @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 void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1660,7 +1745,7 @@
* @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 @@
@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 @@
}
/**
+ * 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 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1770,7 +1929,7 @@
@Deprecated
@UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1800,7 +1959,7 @@
@Deprecated
@UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2080,7 +2239,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean isNdefPushEnabled() {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2194,7 +2353,7 @@
@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 @@
@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 58b6179..ad86d70 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -998,6 +998,87 @@
}
}
+ /**
+ * 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 0d073cc..11be905 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -55,3 +55,10 @@
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 a9b7257..5871717 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1315,9 +1315,7 @@
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 61b24aa..b7649ba 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -52,4 +52,9 @@
* @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 7f60a20..2145c1a 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -90,4 +90,8 @@
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 a3b836a..d002fe1 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -18,8 +18,6 @@
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.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.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 @@
} 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 77843d9..21ffbf1 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -161,4 +161,18 @@
}
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 1f11197..4fc5131 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.util.Slog;
import java.util.Map;
@@ -44,44 +43,8 @@
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 @@
*
* @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 3ecf74e..54ed73c 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -134,16 +134,16 @@
@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 4b9bd47..eb1db3e 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1602,14 +1602,13 @@
* 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 @@
}
/** {@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 1c2d19d..0000000
--- 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 1baea2a..b651711 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -46,6 +46,7 @@
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 @@
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 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 95bb42e..ef0750c 100644
--- a/core/jni/hwbinder/EphemeralStorage.cpp
+++ b/core/jni/hwbinder/EphemeralStorage.cpp
@@ -164,7 +164,7 @@
}
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 43266a5..cb3f99c 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 @@
}
@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 0000000..f15c153
--- /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 6ae8800..0000000
--- 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 d75b691..0000000
--- 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 0000000..2161a62
--- /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 0000000..2161a62
--- /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 344e56c..ae7c170 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 @@
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 3be14bc..10bf068 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 @@
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 03656f0..ada2196 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.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 @@
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 @@
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 @@
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 @@
}
@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 @@
@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 @@
}
}
};
+
+ /**
+ * 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 c35bc69..bcc9272 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 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 021e7df..ac90a45 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 @@
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 @@
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 76199e3..791165d 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 @@
}
@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 926d7a4..5cdfca7 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.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.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 @@
*
* @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 @@
// 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 @@
}
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 @@
}
}
+ 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 @@
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 a2d7a81..5335cc3 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -43,3 +43,6 @@
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 490aa1f..f952c99 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1341,8 +1341,8 @@
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 @@
@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 @@
/* 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 @@
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 bca2d60..b04c7c5 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -316,6 +316,11 @@
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 @@
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 @@
}
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 0c2eee5..ad09082 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 @@
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 ab0d0d2..b7e7374 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.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 @@
return;
}
- String processName = "UNKNOWN";
final boolean isProtoFile = filename.endsWith(".pb");
- File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb");
-
- Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile);
- if (parsedTombstone.isPresent()) {
- processName = parsedTombstone.get().getProcessName();
+ if (!isProtoFile) {
+ return;
}
- BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock);
+
+ Optional<ParsedTombstone> parsedTombstone = handleProtoTombstone(path, true);
+ if (parsedTombstone.isPresent()) {
+ BootReceiver.addTombstoneToDropBox(
+ mContext, path, parsedTombstone.get().getTombstone(),
+ parsedTombstone.get().getProcessName(), 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 @@
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 @@
previous.dispose();
}
- mTombstones.put(number, parsedTombstone.get());
+ mTombstones.put(number, parsedTombstone.get().getTombstoneFile());
}
}
@@ -330,6 +332,27 @@
}
}
+ 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 @@
}
}
- static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) {
- final FileInputStream is = new FileInputStream(pfd.getFileDescriptor());
- final ProtoInputStream stream = new ProtoInputStream(is);
+ static Optional<ParsedTombstone> parse(ParcelFileDescriptor pfd) {
+ Tombstone tombstoneProto;
+ try (FileInputStream is = new FileInputStream(pfd.getFileDescriptor())) {
+ final byte[] tombstoneBytes = is.readAllBytes();
- 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;
-
- 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 @@
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 @@
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 8961923..d9d7087 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 @@
}
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 8adb566..4c42c2d 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 @@
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 062d797..8fcc921 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 @@
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 720c773..deff3d7 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 @@
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 fa46acd..0de7c28 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 d2d2a0c..ed9445c 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 @@
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 @@
};
}
- 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 e51afbe..0bc60cd 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 @@
}
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 8cd55c7..591a559 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -37,6 +37,7 @@
"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 @@
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 d4f6312..33d3686 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -32,3 +32,7 @@
# 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 0000000..3892d28
--- /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 a87902f..e7de081 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -63,6 +63,7 @@
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 @@
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 6e82907..fd21a32 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -21,6 +21,8 @@
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 @@
"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 52eae21..a70802a 100644
--- a/services/robotests/Android.bp
+++ b/services/robotests/Android.bp
@@ -57,9 +57,13 @@
],
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 66ee696..fba2cad 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -56,6 +56,8 @@
// Include the testing libraries
libs: [
"mockito-robolectric-prebuilt",
+ "Settings-robo-testutils",
+ "SettingsLib-robo-testutils",
"platform-test-annotations",
"testng",
"truth",
@@ -63,4 +65,6 @@
instrumentation_for: "BackupFrameworksServicesLib",
+ upstream: true,
+
}
diff --git a/services/robotests/backup/config/robolectric.properties b/services/robotests/backup/config/robolectric.properties
index 850557a..1ebf6d4 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 ee5a534..6839a06 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 @@
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 0000000..53d807c
--- /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 4949091..0092763 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.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 @@
*/
@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 16d16cd..3681bd4 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 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 @@
}
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 4a99486..1da6759 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 @@
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 e5be4d9..9e11fa2 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.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 @@
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 @@
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 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 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 c42c735..37ca09d 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 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.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.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 @@
@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 @@
@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 @@
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 @@
"com.android/.SystemTrustAgent");
addTrustAgent(newAgentComponentName, /* isSystemApp= */ true);
- mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
+ notifyPackageChanged(newAgentComponentName);
assertThat(mEnabledTrustAgents).containsExactly(newAgentComponentName);
assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
@@ -276,7 +298,7 @@
"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 @@
"com.user/.UserTrustAgent");
addTrustAgent(newAgentComponentName, /* isSystemApp= */ false);
- mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
+ notifyPackageChanged(newAgentComponentName);
assertThat(mEnabledTrustAgents).isEmpty();
assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
@@ -307,7 +329,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 0000000..523c5c0
--- /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 d26d671..f04a4e6 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 @@
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 f5d50d1..6986cab 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 @@
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();