summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/api/system-current.txt11
-rwxr-xr-xcore/java/android/os/Build.java11
-rw-r--r--core/java/android/os/OWNERS3
-rw-r--r--core/java/com/android/server/SystemConfig.java183
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java111
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java18
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java72
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java70
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java7
-rw-r--r--services/core/java/com/android/server/OWNERS3
-rw-r--r--services/core/java/com/android/server/infra/OWNERS3
-rw-r--r--services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java67
-rw-r--r--services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java281
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt4
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java317
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java82
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthLte.java35
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java3
-rw-r--r--tests/TrustTests/OWNERS1
22 files changed, 1113 insertions, 199 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index e0eccf4fc1f3..d02c7abfe802 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29495,6 +29495,7 @@ package android.os {
field public static final int PREVIEW_SDK_INT;
field public static final String RELEASE;
field @NonNull public static final String RELEASE_OR_CODENAME;
+ field @NonNull public static final String RELEASE_OR_PREVIEW_DISPLAY;
field @Deprecated public static final String SDK;
field public static final int SDK_INT;
field public static final String SECURITY_PATCH;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index af7fc7728a5b..456a4f46ebbf 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -7039,14 +7039,21 @@ package android.net {
}
public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
- ctor public EthernetNetworkUpdateRequest(@NonNull android.net.StaticIpConfiguration, @NonNull android.net.NetworkCapabilities);
method public int describeContents();
- method @NonNull public android.net.StaticIpConfiguration getIpConfig();
+ method @NonNull public android.net.IpConfiguration getIpConfiguration();
method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR;
}
+ public static final class EthernetNetworkUpdateRequest.Builder {
+ ctor public EthernetNetworkUpdateRequest.Builder();
+ ctor public EthernetNetworkUpdateRequest.Builder(@NonNull android.net.EthernetNetworkUpdateRequest);
+ method @NonNull public android.net.EthernetNetworkUpdateRequest build();
+ method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@NonNull android.net.IpConfiguration);
+ method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+ }
+
public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public MatchAllNetworkSpecifier();
method public int describeContents();
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 545ae38c38c0..03492aa56631 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -285,13 +285,20 @@ public class Build {
public static final String RELEASE = getString("ro.build.version.release");
/**
- * The version string we show to the user; may be {@link #RELEASE} or
- * {@link #CODENAME} if not a final release build.
+ * The version string. May be {@link #RELEASE} or {@link #CODENAME} if
+ * not a final release build.
*/
@NonNull public static final String RELEASE_OR_CODENAME = getString(
"ro.build.version.release_or_codename");
/**
+ * The version string we show to the user; may be {@link #RELEASE} or
+ * a descriptive string if not a final release build.
+ */
+ @NonNull public static final String RELEASE_OR_PREVIEW_DISPLAY = getString(
+ "ro.build.version.release_or_preview_display");
+
+ /**
* The base OS build the product is based on.
*/
public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", "");
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 5d9f2189df1b..8e5ed8f6e578 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -52,6 +52,9 @@ per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS
per-file *Telephony* = file:/telephony/OWNERS
per-file *Zygote* = file:/ZYGOTE_OWNERS
+# Time
+per-file *Clock* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+
# RecoverySystem
per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ae9d71610aaa..fb0b7fdd6ce3 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -112,17 +112,74 @@ public class SystemConfig {
public final String name;
public final String filename;
public final String[] dependencies;
+
+ /**
+ * SDK version this library was added to the BOOTCLASSPATH.
+ *
+ * <p>At the SDK level specified in this field and higher, the apps' uses-library tags for
+ * this library will be ignored, since the library is always available on BOOTCLASSPATH.
+ *
+ * <p>0 means not specified.
+ */
+ public final int onBootclasspathSince;
+
+ /**
+ * SDK version this library was removed from the BOOTCLASSPATH.
+ *
+ * <p>At the SDK level specified in this field and higher, this library needs to be
+ * explicitly added by apps. For compatibility reasons, when an app
+ * targets an SDK less than the value of this attribute, this library is automatically
+ * added.
+ *
+ * <p>0 means not specified.
+ */
+ public final int onBootclasspathBefore;
+
+ /**
+ * Declares whether this library can be safely ignored from <uses-library> tags.
+ *
+ * <p> This can happen if the library initially had to be explicitly depended-on using that
+ * tag but has since been moved to the BOOTCLASSPATH which means now is always available
+ * and the tag is no longer required.
+ */
+ public final boolean canBeSafelyIgnored;
+
public final boolean isNative;
- SharedLibraryEntry(String name, String filename, String[] dependencies) {
- this(name, filename, dependencies, false /* isNative */);
+
+ @VisibleForTesting
+ public SharedLibraryEntry(String name, String filename, String[] dependencies,
+ boolean isNative) {
+ this(name, filename, dependencies, 0 /* onBootclasspathSince */,
+ 0 /* onBootclasspathBefore */, isNative);
}
- SharedLibraryEntry(String name, String filename, String[] dependencies, boolean isNative) {
+ @VisibleForTesting
+ public SharedLibraryEntry(String name, String filename, String[] dependencies,
+ int onBootclasspathSince, int onBootclassPathBefore) {
+ this(name, filename, dependencies, onBootclasspathSince, onBootclassPathBefore,
+ false /* isNative */);
+ }
+
+ SharedLibraryEntry(String name, String filename, String[] dependencies,
+ int onBootclasspathSince, int onBootclasspathBefore, boolean isNative) {
this.name = name;
this.filename = filename;
this.dependencies = dependencies;
+ this.onBootclasspathSince = onBootclasspathSince;
+ this.onBootclasspathBefore = onBootclasspathBefore;
this.isNative = isNative;
+
+ canBeSafelyIgnored = this.onBootclasspathSince != 0
+ && isSdkAtLeast(this.onBootclasspathSince);
+ }
+
+ private static boolean isSdkAtLeast(int level) {
+ if ("REL".equals(Build.VERSION.CODENAME)) {
+ return Build.VERSION.SDK_INT >= level;
+ }
+ return level == Build.VERSION_CODES.CUR_DEVELOPMENT
+ || Build.VERSION.SDK_INT >= level;
}
}
@@ -509,12 +566,14 @@ public class SystemConfig {
}
private void readAllPermissions() {
+ final XmlPullParser parser = Xml.newPullParser();
+
// Read configuration from system
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Vendors are only allowed to customize these
@@ -524,18 +583,18 @@ public class SystemConfig {
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
}
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");
if (!vendorSkuProperty.isEmpty()) {
String vendorSkuDir = "sku_" + vendorSkuProperty;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
vendorPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
vendorPermissionFlag);
}
@@ -543,18 +602,18 @@ public class SystemConfig {
// Allow ODM to customize system configs as much as Vendor, because /odm is another
// vendor partition other than /vendor.
int odmPermissionFlag = vendorPermissionFlag;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
if (!skuProperty.isEmpty()) {
String skuDir = "sku_" + skuProperty;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions", skuDir),
odmPermissionFlag);
}
@@ -562,9 +621,9 @@ public class SystemConfig {
// Allow OEM to customize these
int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS
| ALLOW_VENDOR_APEX;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
// Allow Product to customize these configs
@@ -579,15 +638,15 @@ public class SystemConfig {
// DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement.
productPermissionFlag = ALLOW_ALL;
}
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
// Allow /system_ext to customize all system configs
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
// Skip loading configuration from apex if it is not a system process.
@@ -601,12 +660,14 @@ public class SystemConfig {
if (f.isFile() || f.getPath().contains("@")) {
continue;
}
- readPermissions(Environment.buildPath(f, "etc", "permissions"), apexPermissionFlag);
+ readPermissions(parser, Environment.buildPath(f, "etc", "permissions"),
+ apexPermissionFlag);
}
+ pruneVendorApexPrivappAllowlists();
}
@VisibleForTesting
- public void readPermissions(File libraryDir, int permissionFlag) {
+ public void readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag) {
// Read permissions from given directory.
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
if (permissionFlag == ALLOW_ALL) {
@@ -641,12 +702,12 @@ public class SystemConfig {
continue;
}
- readPermissionsFromXml(f, permissionFlag);
+ readPermissionsFromXml(parser, f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
- readPermissionsFromXml(platformFile, permissionFlag);
+ readPermissionsFromXml(parser, platformFile, permissionFlag);
}
}
@@ -655,8 +716,9 @@ public class SystemConfig {
+ permFile + " at " + parser.getPositionDescription());
}
- private void readPermissionsFromXml(File permFile, int permissionFlag) {
- FileReader permReader = null;
+ private void readPermissionsFromXml(final XmlPullParser parser, File permFile,
+ int permissionFlag) {
+ final FileReader permReader;
try {
permReader = new FileReader(permFile);
} catch (FileNotFoundException e) {
@@ -668,7 +730,6 @@ public class SystemConfig {
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
try {
- XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
int type;
@@ -789,11 +850,17 @@ public class SystemConfig {
XmlUtils.skipCurrentTag(parser);
}
} break;
+ case "apex-library":
+ // "apex-library" is meant to behave exactly like "library"
case "library": {
if (allowLibs) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");
String ldependency = parser.getAttributeValue(null, "dependency");
+ int minDeviceSdk = XmlUtils.readIntAttribute(parser, "min-device-sdk",
+ 0);
+ int maxDeviceSdk = XmlUtils.readIntAttribute(parser, "max-device-sdk",
+ 0);
if (lname == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
+ parser.getPositionDescription());
@@ -801,10 +868,34 @@ public class SystemConfig {
Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
+ parser.getPositionDescription());
} else {
- //Log.i(TAG, "Got library " + lname + " in " + lfile);
- SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
- ldependency == null ? new String[0] : ldependency.split(":"));
- mSharedLibraries.put(lname, entry);
+ boolean allowedMinSdk = minDeviceSdk <= Build.VERSION.SDK_INT;
+ boolean allowedMaxSdk =
+ maxDeviceSdk == 0 || maxDeviceSdk >= Build.VERSION.SDK_INT;
+ final boolean exists = new File(lfile).exists();
+ if (allowedMinSdk && allowedMaxSdk && exists) {
+ int bcpSince = XmlUtils.readIntAttribute(parser,
+ "on-bootclasspath-since", 0);
+ int bcpBefore = XmlUtils.readIntAttribute(parser,
+ "on-bootclasspath-before", 0);
+ SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
+ ldependency == null
+ ? new String[0] : ldependency.split(":"),
+ bcpSince, bcpBefore);
+ mSharedLibraries.put(lname, entry);
+ } else {
+ final StringBuilder msg = new StringBuilder(
+ "Ignore shared library ").append(lname).append(":");
+ if (!allowedMinSdk) {
+ msg.append(" min-device-sdk=").append(minDeviceSdk);
+ }
+ if (!allowedMaxSdk) {
+ msg.append(" max-device-sdk=").append(maxDeviceSdk);
+ }
+ if (!exists) {
+ msg.append(" ").append(lfile).append(" does not exist");
+ }
+ Slog.i(TAG, msg.toString());
+ }
}
} else {
logNotAllowedInPartition(name, permFile, parser);
@@ -1085,7 +1176,8 @@ public class SystemConfig {
readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
mSystemExtPrivAppDenyPermissions);
} else if (apex) {
- readApexPrivAppPermissions(parser, permFile);
+ readApexPrivAppPermissions(parser, permFile,
+ Environment.getApexDirectory().toPath());
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
@@ -1435,6 +1527,21 @@ public class SystemConfig {
}
}
+ /**
+ * Prunes out any privileged permission allowlists bundled in vendor apexes.
+ */
+ @VisibleForTesting
+ public void pruneVendorApexPrivappAllowlists() {
+ for (String moduleName: mAllowedVendorApexes.keySet()) {
+ if (mApexPrivAppPermissions.containsKey(moduleName)
+ || mApexPrivAppDenyPermissions.containsKey(moduleName)) {
+ Slog.w(TAG, moduleName + " is a vendor apex, ignore its priv-app allowlist");
+ mApexPrivAppPermissions.remove(moduleName);
+ mApexPrivAppDenyPermissions.remove(moduleName);
+ }
+ }
+ }
+
private void readInstallInUserType(XmlPullParser parser,
Map<String, Set<String>> doInstallMap,
Map<String, Set<String>> nonInstallMap)
@@ -1645,8 +1752,7 @@ public class SystemConfig {
/**
* Returns the module name for a file in the apex module's partition.
*/
- private String getApexModuleNameFromFilePath(Path path) {
- final Path apexDirectoryPath = Environment.getApexDirectory().toPath();
+ private String getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath) {
if (!path.startsWith(apexDirectoryPath)) {
throw new IllegalArgumentException("File " + path + " is not part of an APEX.");
}
@@ -1658,9 +1764,14 @@ public class SystemConfig {
return path.getName(apexDirectoryPath.getNameCount()).toString();
}
- private void readApexPrivAppPermissions(XmlPullParser parser, File permFile)
- throws IOException, XmlPullParserException {
- final String moduleName = getApexModuleNameFromFilePath(permFile.toPath());
+ /**
+ * Reads the contents of the privileged permission allowlist stored inside an APEX.
+ */
+ @VisibleForTesting
+ public void readApexPrivAppPermissions(XmlPullParser parser, File permFile,
+ Path apexDirectoryPath) throws IOException, XmlPullParserException {
+ final String moduleName =
+ getApexModuleNameFromFilePath(permFile.toPath(), apexDirectoryPath);
final ArrayMap<String, ArraySet<String>> privAppPermissions;
if (mApexPrivAppPermissions.containsKey(moduleName)) {
privAppPermissions = mApexPrivAppPermissions.get(moduleName);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 2e85b304ec47..31dd10a8ed53 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -66,6 +66,7 @@ import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
+import java.security.spec.NamedParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
@@ -119,36 +120,42 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
private static final int RSA_MIN_KEY_SIZE = 512;
private static final int RSA_MAX_KEY_SIZE = 8192;
- private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
+ private static final Map<String, Integer> SUPPORTED_EC_CURVE_NAME_TO_SIZE =
new HashMap<String, Integer>();
- private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
- private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
+ private static final List<String> SUPPORTED_EC_CURVE_NAMES = new ArrayList<String>();
+ private static final List<Integer> SUPPORTED_EC_CURVE_SIZES = new ArrayList<Integer>();
+ private static final String CURVE_X_25519 = NamedParameterSpec.X25519.getName();
+ private static final String CURVE_ED_25519 = NamedParameterSpec.ED25519.getName();
+
static {
// Aliases for NIST P-224
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-224", 224);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
// Aliases for NIST P-256
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-256", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
+ // Aliases for Curve 25519
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_X_25519.toLowerCase(Locale.US), 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_ED_25519.toLowerCase(Locale.US), 256);
// Aliases for NIST P-384
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-384", 384);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
// Aliases for NIST P-521
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-521", 521);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
- SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
- Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
+ SUPPORTED_EC_CURVE_NAMES.addAll(SUPPORTED_EC_CURVE_NAME_TO_SIZE.keySet());
+ Collections.sort(SUPPORTED_EC_CURVE_NAMES);
- SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
- new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
- Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
+ SUPPORTED_EC_CURVE_SIZES.addAll(
+ new HashSet<Integer>(SUPPORTED_EC_CURVE_NAME_TO_SIZE.values()));
+ Collections.sort(SUPPORTED_EC_CURVE_SIZES);
}
private final int mOriginalKeymasterAlgorithm;
@@ -164,6 +171,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
private int mKeySizeBits;
private SecureRandom mRng;
private KeyDescriptor mAttestKeyDescriptor;
+ private String mEcCurveName;
private int[] mKeymasterPurposes;
private int[] mKeymasterBlockModes;
@@ -177,12 +185,15 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
mOriginalKeymasterAlgorithm = keymasterAlgorithm;
}
- private @EcCurve int keySize2EcCurve(int keySizeBits)
+ private static @EcCurve int keySizeAndNameToEcCurve(int keySizeBits, String ecCurveName)
throws InvalidAlgorithmParameterException {
switch (keySizeBits) {
case 224:
return EcCurve.P_224;
case 256:
+ if (isCurve25519(ecCurveName)) {
+ return EcCurve.CURVE_25519;
+ }
return EcCurve.P_256;
case 384:
return EcCurve.P_384;
@@ -247,7 +258,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
if (mKeySizeBits == -1) {
mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
}
- checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked());
+ checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked(),
+ mEcCurveName);
if (spec.getKeystoreAlias() == null) {
throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
@@ -299,6 +311,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
mAttestKeyDescriptor = buildAndCheckAttestKeyDescriptor(spec);
checkAttestKeyPurpose(spec);
+ checkCorrectKeyPurposeForCurve(spec);
success = true;
} finally {
@@ -317,6 +330,42 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
}
}
+ private void checkCorrectKeyPurposeForCurve(KeyGenParameterSpec spec)
+ throws InvalidAlgorithmParameterException {
+ // Validate the key usage purposes against the curve. x25519 should be
+ // key exchange only, ed25519 signing and attesting.
+
+ if (!isCurve25519(mEcCurveName)) {
+ return;
+ }
+
+ if (mEcCurveName.equalsIgnoreCase(CURVE_X_25519)
+ && spec.getPurposes() != KeyProperties.PURPOSE_AGREE_KEY) {
+ throw new InvalidAlgorithmParameterException(
+ "x25519 may only be used for key agreement.");
+ } else if (mEcCurveName.equalsIgnoreCase(CURVE_ED_25519)
+ && !hasOnlyAllowedPurposeForEd25519(spec.getPurposes())) {
+ throw new InvalidAlgorithmParameterException(
+ "ed25519 may not be used for key agreement.");
+ }
+ }
+
+ private static boolean isCurve25519(String ecCurveName) {
+ if (ecCurveName == null) {
+ return false;
+ }
+ return ecCurveName.equalsIgnoreCase(CURVE_X_25519)
+ || ecCurveName.equalsIgnoreCase(CURVE_ED_25519);
+ }
+
+ private static boolean hasOnlyAllowedPurposeForEd25519(@KeyProperties.PurposeEnum int purpose) {
+ final int allowedPurposes = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY
+ | KeyProperties.PURPOSE_ATTEST_KEY;
+ boolean hasAllowedPurpose = (purpose & allowedPurposes) != 0;
+ boolean hasDisallowedPurpose = (purpose & ~allowedPurposes) != 0;
+ return hasAllowedPurpose && !hasDisallowedPurpose;
+ }
+
private KeyDescriptor buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec)
throws InvalidAlgorithmParameterException {
if (spec.getAttestKeyAlias() != null) {
@@ -473,6 +522,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
mRSAPublicExponent = null;
mRng = null;
mKeyStore = null;
+ mEcCurveName = null;
}
private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
@@ -514,13 +564,13 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
case KeymasterDefs.KM_ALGORITHM_EC:
if (algSpecificSpec instanceof ECGenParameterSpec) {
ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
- String curveName = ecSpec.getName();
- Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
- curveName.toLowerCase(Locale.US));
+ mEcCurveName = ecSpec.getName();
+ final Integer ecSpecKeySizeBits = SUPPORTED_EC_CURVE_NAME_TO_SIZE.get(
+ mEcCurveName.toLowerCase(Locale.US));
if (ecSpecKeySizeBits == null) {
throw new InvalidAlgorithmParameterException(
- "Unsupported EC curve name: " + curveName
- + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
+ "Unsupported EC curve name: " + mEcCurveName
+ + ". Supported: " + SUPPORTED_EC_CURVE_NAMES);
}
if (mKeySizeBits == -1) {
mKeySizeBits = ecSpecKeySizeBits;
@@ -744,7 +794,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
params.add(KeyStore2ParameterUtils.makeEnum(
- Tag.EC_CURVE, keySize2EcCurve(mKeySizeBits)
+ Tag.EC_CURVE, keySizeAndNameToEcCurve(mKeySizeBits, mEcCurveName)
));
}
@@ -864,7 +914,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
private static void checkValidKeySize(
int keymasterAlgorithm,
int keySize,
- boolean isStrongBoxBacked)
+ boolean isStrongBoxBacked,
+ String mEcCurveName)
throws InvalidAlgorithmParameterException {
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
@@ -873,9 +924,13 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
"Unsupported StrongBox EC key size: "
+ keySize + " bits. Supported: 256");
}
- if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
+ if (isStrongBoxBacked && isCurve25519(mEcCurveName)) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported StrongBox EC: " + mEcCurveName);
+ }
+ if (!SUPPORTED_EC_CURVE_SIZES.contains(keySize)) {
throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
- + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
+ + keySize + " bits. Supported: " + SUPPORTED_EC_CURVE_SIZES);
}
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index 72a145fa6a05..358104fffbf6 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -66,6 +66,11 @@ public class AndroidKeyStoreProvider extends Provider {
private static final String DESEDE_SYSTEM_PROPERTY =
"ro.hardware.keystore_desede";
+ // Conscrypt returns the Ed25519 OID as the JCA key algorithm.
+ private static final String ED25519_OID = "1.3.101.112";
+ // Conscrypt returns "XDH" as the X25519 JCA key algorithm.
+ private static final String X25519_ALIAS = "XDH";
+
/** @hide **/
public AndroidKeyStoreProvider() {
super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
@@ -78,10 +83,16 @@ public class AndroidKeyStoreProvider extends Provider {
// java.security.KeyPairGenerator
put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC");
put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
+ put("KeyPairGenerator." + X25519_ALIAS,
+ PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
+ put("KeyPairGenerator." + ED25519_OID,
+ PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
// java.security.KeyFactory
putKeyFactoryImpl("EC");
putKeyFactoryImpl("RSA");
+ putKeyFactoryImpl(X25519_ALIAS);
+ putKeyFactoryImpl(ED25519_OID);
// javax.crypto.KeyGenerator
put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
@@ -219,12 +230,17 @@ public class AndroidKeyStoreProvider extends Provider {
KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
-
return new AndroidKeyStoreECPublicKey(descriptor, metadata,
iSecurityLevel, (ECPublicKey) publicKey);
} else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(jcaKeyAlgorithm)) {
return new AndroidKeyStoreRSAPublicKey(descriptor, metadata,
iSecurityLevel, (RSAPublicKey) publicKey);
+ } else if (ED25519_OID.equalsIgnoreCase(jcaKeyAlgorithm)) {
+ //TODO(b/214203951) missing classes in conscrypt
+ throw new ProviderException("Curve " + ED25519_OID + " not supported yet");
+ } else if (X25519_ALIAS.equalsIgnoreCase(jcaKeyAlgorithm)) {
+ //TODO(b/214203951) missing classes in conscrypt
+ throw new ProviderException("Curve " + X25519_ALIAS + " not supported yet");
} else {
throw new ProviderException("Unsupported Android Keystore public key algorithm: "
+ jcaKeyAlgorithm);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
deleted file mode 100644
index f23794b50543..000000000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediaframeworktest.unit;
-
-import static org.junit.Assert.assertEquals;
-
-import android.bluetooth.BluetoothProfile;
-import android.media.BluetoothProfileConnectionInfo;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class BluetoothProfileConnectionInfoTest {
-
- @Test
- public void testCoverageA2dp() {
- final boolean supprNoisy = false;
- final int volume = 42;
- final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
- .createA2dpInfo(supprNoisy, volume);
- assertEquals(info.getProfile(), BluetoothProfile.A2DP);
- assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
- assertEquals(info.getVolume(), volume);
- }
-
- @Test
- public void testCoverageA2dpSink() {
- final int volume = 42;
- final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
- .createA2dpSinkInfo(volume);
- assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK);
- assertEquals(info.getVolume(), volume);
- }
-
- @Test
- public void testCoveragehearingAid() {
- final boolean supprNoisy = true;
- final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
- .createHearingAidInfo(supprNoisy);
- assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID);
- assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
- }
-
- @Test
- public void testCoverageLeAudio() {
- final boolean supprNoisy = false;
- final boolean isLeOutput = true;
- final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
- .createLeAudioInfo(supprNoisy, isLeOutput);
- assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO);
- assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
- assertEquals(info.isLeOutput(), isLeOutput);
- }
-}
-
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
index e879e40247cf..a6269711055a 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,13 +28,13 @@ import java.util.Objects;
@SystemApi
public final class EthernetNetworkUpdateRequest implements Parcelable {
@NonNull
- private final StaticIpConfiguration mIpConfig;
+ private final IpConfiguration mIpConfig;
@NonNull
private final NetworkCapabilities mNetworkCapabilities;
@NonNull
- public StaticIpConfiguration getIpConfig() {
- return new StaticIpConfiguration(mIpConfig);
+ public IpConfiguration getIpConfiguration() {
+ return new IpConfiguration(mIpConfig);
}
@NonNull
@@ -41,20 +42,75 @@ public final class EthernetNetworkUpdateRequest implements Parcelable {
return new NetworkCapabilities(mNetworkCapabilities);
}
- public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+ private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig,
@NonNull final NetworkCapabilities networkCapabilities) {
Objects.requireNonNull(ipConfig);
Objects.requireNonNull(networkCapabilities);
- mIpConfig = new StaticIpConfiguration(ipConfig);
+ mIpConfig = new IpConfiguration(ipConfig);
mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
}
private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
Objects.requireNonNull(source);
- mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
+ mIpConfig = IpConfiguration.CREATOR.createFromParcel(source);
mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
}
+ /**
+ * Builder used to create {@link EthernetNetworkUpdateRequest} objects.
+ */
+ public static final class Builder {
+ @Nullable
+ private IpConfiguration mBuilderIpConfig;
+ @Nullable
+ private NetworkCapabilities mBuilderNetworkCapabilities;
+
+ public Builder(){}
+
+ /**
+ * Constructor to populate the builder's values with an already built
+ * {@link EthernetNetworkUpdateRequest}.
+ * @param request the {@link EthernetNetworkUpdateRequest} to populate with.
+ */
+ public Builder(@NonNull final EthernetNetworkUpdateRequest request) {
+ Objects.requireNonNull(request);
+ mBuilderIpConfig = new IpConfiguration(request.mIpConfig);
+ mBuilderNetworkCapabilities = new NetworkCapabilities(request.mNetworkCapabilities);
+ }
+
+ /**
+ * Set the {@link IpConfiguration} to be used with the {@code Builder}.
+ * @param ipConfig the {@link IpConfiguration} to set.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) {
+ Objects.requireNonNull(ipConfig);
+ mBuilderIpConfig = new IpConfiguration(ipConfig);
+ return this;
+ }
+
+ /**
+ * Set the {@link NetworkCapabilities} to be used with the {@code Builder}.
+ * @param nc the {@link NetworkCapabilities} to set.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public Builder setNetworkCapabilities(@NonNull final NetworkCapabilities nc) {
+ Objects.requireNonNull(nc);
+ mBuilderNetworkCapabilities = new NetworkCapabilities(nc);
+ return this;
+ }
+
+ /**
+ * Build {@link EthernetNetworkUpdateRequest} return the current update request.
+ */
+ @NonNull
+ public EthernetNetworkUpdateRequest build() {
+ return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities);
+ }
+ }
+
@Override
public String toString() {
return "EthernetNetworkUpdateRequest{"
@@ -68,7 +124,7 @@ public final class EthernetNetworkUpdateRequest implements Parcelable {
if (o == null || getClass() != o.getClass()) return false;
EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
- return Objects.equals(that.getIpConfig(), mIpConfig)
+ return Objects.equals(that.getIpConfiguration(), mIpConfig)
&& Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index a0f239d43927..fcde533fe05c 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -171,7 +171,9 @@ public class NetworkTimeUpdateService extends Binder {
>= mPollingIntervalMs) {
if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
boolean isSuccessful = mTime.forceRefresh();
- if (!isSuccessful) {
+ if (isSuccessful) {
+ mTryAgainCounter = 0;
+ } else {
String logMsg = "forceRefresh() returned false: cachedNtpResult=" + cachedNtpResult
+ ", currentElapsedRealtimeMillis=" + currentElapsedRealtimeMillis;
@@ -188,7 +190,8 @@ public class NetworkTimeUpdateService extends Binder {
&& cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
< mPollingIntervalMs) {
// Obtained fresh fix; schedule next normal update
- resetAlarm(mPollingIntervalMs);
+ resetAlarm(mPollingIntervalMs
+ - cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis));
// Suggest the time to the time detector. It may choose use it to set the system clock.
TimestampedValue<Long> timeSignal = new TimestampedValue<>(
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 71b463a4db8c..f4b8f5ddda66 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -23,14 +23,13 @@ per-file *Alarm* = file:/apex/jobscheduler/OWNERS
per-file *AppOp* = file:/core/java/android/permission/OWNERS
per-file *Battery* = file:/BATTERY_STATS_OWNERS
per-file *Binder* = file:/core/java/com/android/internal/os/BINDER_OWNERS
-per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS
per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
per-file *Storage* = file:/core/java/android/os/storage/OWNERS
-per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS
+per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS
per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
per-file MmsServiceBroker.java = file:/telephony/OWNERS
diff --git a/services/core/java/com/android/server/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS
new file mode 100644
index 000000000000..0466d8a88053
--- /dev/null
+++ b/services/core/java/com/android/server/infra/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 655446
+
+include /core/java/android/service/cloudsearch/OWNERS
diff --git a/services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java b/services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java
new file mode 100644
index 000000000000..0418afbf29ee
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing.library;
+
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+/**
+ * Updates packages to add or remove dependencies on shared libraries as per attributes
+ * in the library declaration
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class ApexSharedLibraryUpdater extends PackageSharedLibraryUpdater {
+
+ /**
+ * ArrayMap like the one you find in {@link SystemConfig}. The keys are the library names.
+ */
+ private final ArrayMap<String, SystemConfig.SharedLibraryEntry> mSharedLibraries;
+
+ public ApexSharedLibraryUpdater(
+ ArrayMap<String, SystemConfig.SharedLibraryEntry> sharedLibraries) {
+ mSharedLibraries = sharedLibraries;
+ }
+
+ @Override
+ public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
+ final int builtInLibCount = mSharedLibraries.size();
+ for (int i = 0; i < builtInLibCount; i++) {
+ updateSharedLibraryForPackage(mSharedLibraries.valueAt(i), parsedPackage);
+ }
+ }
+
+ private void updateSharedLibraryForPackage(SystemConfig.SharedLibraryEntry entry,
+ ParsedPackage parsedPackage) {
+ if (entry.onBootclasspathBefore != 0
+ && parsedPackage.getTargetSdkVersion() < entry.onBootclasspathBefore) {
+ // this package targets an API where this library was in the BCP, so add
+ // the library transparently in case the package is using it
+ prefixRequiredLibrary(parsedPackage, entry.name);
+ }
+
+ if (entry.canBeSafelyIgnored) {
+ // the library is now present in the BCP and always available; we don't need to add
+ // it a second time
+ removeLibrary(parsedPackage, entry.name);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
index 8a8a302734b1..d81e7d05fd73 100644
--- a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
+++ b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
@@ -25,6 +25,7 @@ import android.content.pm.PackageParser;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemConfig;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import java.util.ArrayList;
@@ -63,6 +64,11 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
boolean bootClassPathContainsATB = !addUpdaterForAndroidTestBase(packageUpdaters);
+ // ApexSharedLibraryUpdater should be the last one, to allow modifications introduced by
+ // mainline after dessert release.
+ packageUpdaters.add(new ApexSharedLibraryUpdater(
+ SystemConfig.getInstance().getSharedLibraries()));
+
PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
.toArray(new PackageSharedLibraryUpdater[0]);
INSTANCE = new PackageBackwardCompatibility(
@@ -106,6 +112,11 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
private final PackageSharedLibraryUpdater[] mPackageUpdaters;
+ @VisibleForTesting
+ PackageSharedLibraryUpdater[] getPackageUpdaters() {
+ return mPackageUpdaters;
+ }
+
private PackageBackwardCompatibility(
boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
this.mBootClassPathContainsATB = bootClassPathContainsATB;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
new file mode 100644
index 000000000000..1d9ea4b6028c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing.library;
+
+import android.os.Build;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
+/**
+ * Test for {@link ApexSharedLibraryUpdater}
+ */
+@Presubmit
+@SmallTest
+@RunWith(JUnit4.class)
+public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ private final ArrayMap<String, SystemConfig.SharedLibraryEntry> mSharedLibraries =
+ new ArrayMap<>(8);
+
+ @Before
+ public void setUp() throws Exception {
+ installSharedLibraries();
+ }
+
+ private void installSharedLibraries() throws Exception {
+ mSharedLibraries.clear();
+ insertLibrary("foo", 0, 0);
+ insertLibrary("fooBcpSince30", 30, 0);
+ insertLibrary("fooBcpBefore30", 0, 30);
+ insertLibrary("fooFromFuture", Build.VERSION.SDK_INT + 2, 0);
+ }
+
+ private void insertLibrary(String libraryName, int onBootclasspathSince,
+ int onBootclasspathBefore) {
+ mSharedLibraries.put(libraryName, new SystemConfig.SharedLibraryEntry(
+ libraryName,
+ "foo.jar",
+ new String[0] /* dependencies */,
+ onBootclasspathSince,
+ onBootclasspathBefore
+ )
+ );
+ }
+
+ @Test
+ public void testRegularAppOnRPlus() {
+ // platform Q should have changes (tested below)
+
+ // these should have no changes
+ checkNoChanges(Build.VERSION_CODES.R);
+ checkNoChanges(Build.VERSION_CODES.S);
+ checkNoChanges(Build.VERSION_CODES.TIRAMISU);
+ checkNoChanges(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ private void checkNoChanges(int targetSdkVersion) {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(targetSdkVersion)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(targetSdkVersion)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince30Applied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpSince30")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // should be removed because on 30+ (R+) it is implicit
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince11kNotAppliedWithoutLibrary() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // nothing should change because the implicit from is only from a future platform release
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince11kNotAppliedWithLibrary() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooFromFuture")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooFromFuture")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // nothing should change because the implicit from is only from a future platform release
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpBefore30NotApplied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // should not be affected because it is still in the BCP in 30 / R
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpBefore30Applied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // should be present because this was in BCP in 29 / Q
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. All of this happening before the current
+ * SDK.
+ */
+ @Test
+ public void testBcpRemovedThenAddedPast() {
+ insertLibrary("fooBcpRemovedThenAdded", 30, 28);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.N)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.N)
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // the library is now in the BOOTCLASSPATH (for the second time) so it doesn't need to be
+ // listed
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetQ() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app targets Q / 29 (when this library was in the BCP) then we need to add it
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetR() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app targets R/30 (when this library was removed from the BCP) then we don't
+ //need to add it
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetR_usingLib() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app wants to use the library, it needs to be present
+ checkBackwardsCompatibility(before, after);
+ }
+
+ private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
+ checkBackwardsCompatibility(before, after,
+ () -> new ApexSharedLibraryUpdater(mSharedLibraries));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index 9768f176ea85..5bcd0f6bb029 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -21,6 +21,8 @@ import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_T
import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.google.common.truth.Truth.assertThat;
+
import android.content.pm.parsing.ParsingPackage;
import android.os.Build;
import android.platform.test.annotations.Presubmit;
@@ -182,6 +184,22 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate
checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
}
+ /**
+ * Ensures that ApexSharedLibraryUpdater is the last updater in the list of package updaters
+ * used by PackageBackwardCompatibility.
+ *
+ * This is required so mainline can add and remove libraries installed by the platform updaters.
+ */
+ @Test
+ public void testApexPackageUpdaterOrdering() {
+ PackageBackwardCompatibility instance =
+ (PackageBackwardCompatibility) PackageBackwardCompatibility.getInstance();
+ PackageSharedLibraryUpdater[] updaterArray = instance.getPackageUpdaters();
+
+ PackageSharedLibraryUpdater lastUpdater = updaterArray[updaterArray.length - 1];
+ assertThat(lastUpdater).isInstanceOf(ApexSharedLibraryUpdater.class);
+ }
+
private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance);
}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
index b7199d4a2443..150822bdff6b 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
@@ -17,6 +17,7 @@
package com.android.server.systemconfig
import android.content.Context
+import android.util.Xml
import androidx.test.InstrumentationRegistry
import com.android.server.SystemConfig
import com.google.common.truth.Truth.assertThat
@@ -227,6 +228,7 @@ class SystemConfigNamedActorTest {
.writeText(this.trimIndent())
private fun assertPermissions() = SystemConfig(false).apply {
- readPermissions(tempFolder.root, 0)
+ val parser = Xml.newPullParser()
+ readPermissions(parser, tempFolder.root, 0)
}. let { assertThat(it.namedActors) }
}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 5eb21a58c38e..bfdffc0e6567 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -21,10 +21,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.testng.Assert.expectThrows;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Xml;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -36,9 +38,12 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
@@ -59,12 +64,15 @@ public class SystemConfigTest {
private static final String LOG_TAG = "SystemConfigTest";
private SystemConfig mSysConfig;
+ private File mFooJar;
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@Before
public void setUp() throws Exception {
mSysConfig = new SystemConfigTestClass();
+ mFooJar = createTempFile(
+ mTemporaryFolder.getRoot().getCanonicalFile(), "foo.jar", "JAR");
}
/**
@@ -76,6 +84,11 @@ public class SystemConfigTest {
}
}
+ private void readPermissions(File libraryDir, int permissionFlag) {
+ final XmlPullParser parser = Xml.newPullParser();
+ mSysConfig.readPermissions(parser, libraryDir, permissionFlag);
+ }
+
/**
* Tests that readPermissions works correctly for the tag: install-in-user-type
*/
@@ -126,16 +139,17 @@ public class SystemConfigTest {
new ArraySet<>(Arrays.asList("GUEST", "PROFILE")));
final File folder1 = createTempSubfolder("folder1");
- createTempFile(folder1, "permFile1.xml", contents1);
+ createTempFile(folder1, "permissionFile1.xml", contents1);
final File folder2 = createTempSubfolder("folder2");
- createTempFile(folder2, "permFile2.xml", contents2);
+ createTempFile(folder2, "permissionFile2.xml", contents2);
- // Also, make a third file, but with the name folder1/permFile2.xml, to prove no conflicts.
- createTempFile(folder1, "permFile2.xml", contents3);
+ // Also, make a third file, but with the name folder1/permissionFile2.xml, to prove no
+ // conflicts.
+ createTempFile(folder1, "permissionFile2.xml", contents3);
- mSysConfig.readPermissions(folder1, /* No permission needed anyway */ 0);
- mSysConfig.readPermissions(folder2, /* No permission needed anyway */ 0);
+ readPermissions(folder1, /* No permission needed anyway */ 0);
+ readPermissions(folder2, /* No permission needed anyway */ 0);
Map<String, Set<String>> actualWhite = mSysConfig.getAndClearPackageToUserTypeWhitelist();
Map<String, Set<String>> actualBlack = mSysConfig.getAndClearPackageToUserTypeBlacklist();
@@ -165,7 +179,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "component-override.xml", contents);
- mSysConfig.readPermissions(folder, /* No permission needed anyway */ 0);
+ readPermissions(folder, /* No permission needed anyway */ 0);
final ArrayMap<String, Boolean> packageOneExpected = new ArrayMap<>();
packageOneExpected.put("com.android.package1.Full", true);
@@ -197,7 +211,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
@@ -215,7 +229,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
@@ -238,7 +252,7 @@ public class SystemConfigTest {
IllegalStateException e = expectThrows(
IllegalStateException.class,
- () -> mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0));
+ () -> readPermissions(folder, /* Grant all permission flags */ ~0));
assertThat(e).hasMessageThat().contains("Multiple modules installers");
}
@@ -257,7 +271,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
+ readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
assertThat(mSysConfig.getWhitelistedStagedInstallers()).isEmpty();
}
@@ -277,7 +291,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getAllowedVendorApexes())
.containsExactly("com.android.apex1", "com.installer");
@@ -297,7 +311,7 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
}
@@ -317,11 +331,273 @@ public class SystemConfigTest {
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all but ALLOW_VENDOR_APEX flag */ ~0x400);
+ readPermissions(folder, /* Grant all but ALLOW_VENDOR_APEX flag */ ~0x400);
assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
}
+ @Test
+ public void readApexPrivAppPermissions_addAllPermissions()
+ throws Exception {
+ final String contents =
+ "<privapp-permissions package=\"com.android.apk_in_apex\">"
+ + "<permission name=\"android.permission.FOO\"/>"
+ + "<deny-permission name=\"android.permission.BAR\"/>"
+ + "</privapp-permissions>";
+ File apexDir = createTempSubfolder("apex");
+ File permissionFile = createTempFile(
+ createTempSubfolder("apex/com.android.my_module/etc/permissions"),
+ "permissions.xml", contents);
+ XmlPullParser parser = readXmlUntilStartTag(permissionFile);
+
+ mSysConfig.readApexPrivAppPermissions(parser, permissionFile, apexDir.toPath());
+
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.my_module",
+ "com.android.apk_in_apex"))
+ .containsExactly("android.permission.FOO");
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.my_module",
+ "com.android.apk_in_apex"))
+ .containsExactly("android.permission.BAR");
+ }
+
+ @Test
+ public void pruneVendorApexPrivappAllowlists_removeVendor()
+ throws Exception {
+ File apexDir = createTempSubfolder("apex");
+
+ // Read non-vendor apex permission allowlists
+ final String allowlistNonVendorContents =
+ "<privapp-permissions package=\"com.android.apk_in_non_vendor_apex\">"
+ + "<permission name=\"android.permission.FOO\"/>"
+ + "<deny-permission name=\"android.permission.BAR\"/>"
+ + "</privapp-permissions>";
+ File nonVendorPermDir =
+ createTempSubfolder("apex/com.android.non_vendor/etc/permissions");
+ File nonVendorPermissionFile =
+ createTempFile(nonVendorPermDir, "permissions.xml", allowlistNonVendorContents);
+ XmlPullParser nonVendorParser = readXmlUntilStartTag(nonVendorPermissionFile);
+ mSysConfig.readApexPrivAppPermissions(nonVendorParser, nonVendorPermissionFile,
+ apexDir.toPath());
+
+ // Read vendor apex permission allowlists
+ final String allowlistVendorContents =
+ "<privapp-permissions package=\"com.android.apk_in_vendor_apex\">"
+ + "<permission name=\"android.permission.BAZ\"/>"
+ + "<deny-permission name=\"android.permission.BAT\"/>"
+ + "</privapp-permissions>";
+ File vendorPermissionFile =
+ createTempFile(createTempSubfolder("apex/com.android.vendor/etc/permissions"),
+ "permissions.xml", allowlistNonVendorContents);
+ XmlPullParser vendorParser = readXmlUntilStartTag(vendorPermissionFile);
+ mSysConfig.readApexPrivAppPermissions(vendorParser, vendorPermissionFile,
+ apexDir.toPath());
+
+ // Read allowed vendor apex list
+ final String allowedVendorContents =
+ "<config>\n"
+ + " <allowed-vendor-apex package=\"com.android.vendor\" "
+ + "installerPackage=\"com.installer\" />\n"
+ + "</config>";
+ final File allowedVendorFolder = createTempSubfolder("folder");
+ createTempFile(allowedVendorFolder, "vendor-apex-allowlist.xml", allowedVendorContents);
+ readPermissions(allowedVendorFolder, /* Grant all permission flags */ ~0);
+
+ // Finally, prune non-vendor allowlists.
+ // There is no guarantee in which order the above reads will be done, however pruning
+ // will always happen last.
+ mSysConfig.pruneVendorApexPrivappAllowlists();
+
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.non_vendor",
+ "com.android.apk_in_non_vendor_apex"))
+ .containsExactly("android.permission.FOO");
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.non_vendor",
+ "com.android.apk_in_non_vendor_apex"))
+ .containsExactly("android.permission.BAR");
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.vendor",
+ "com.android.apk_in_vendor_apex"))
+ .isNull();
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.vendor",
+ "com.android.apk_in_vendor_apex"))
+ .isNull();
+ }
+
+ /**
+ * Tests that readPermissions works correctly for a library with on-bootclasspath-before
+ * and on-bootclasspath-since.
+ */
+ @Test
+ public void readPermissions_allowLibs_parsesSimpleLibrary() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " on-bootclasspath-before=\"10\"\n"
+ + " on-bootclasspath-since=\"20\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.onBootclasspathBefore).isEqualTo(10);
+ assertThat(entry.onBootclasspathSince).isEqualTo(20);
+ }
+
+ /**
+ * Tests that readPermissions works correctly for a library using the new
+ * {@code apex-library} tag.
+ */
+ @Test
+ public void readPermissions_allowLibs_parsesUpdatableLibrary() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <apex-library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " on-bootclasspath-before=\"10\"\n"
+ + " on-bootclasspath-since=\"20\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.onBootclasspathBefore).isEqualTo(10);
+ assertThat(entry.onBootclasspathSince).isEqualTo(20);
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} lower than the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsOldMinSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"30\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} equal to the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsCurrentMinSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"" + Build.VERSION.SDK_INT + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} greater than the current
+ * SDK results in the library being ignored.
+ */
+ @Test
+ public void readPermissions_allowLibs_ignoresMinSdkInFuture() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"" + (Build.VERSION.SDK_INT + 1) + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertThat(mSysConfig.getSharedLibraries()).isEmpty();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} less than the current
+ * SDK results in the library being ignored.
+ */
+ @Test
+ public void readPermissions_allowLibs_ignoredOldMaxSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"30\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertThat(mSysConfig.getSharedLibraries()).isEmpty();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} equal to the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsCurrentMaxSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"" + Build.VERSION.SDK_INT + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} greater than the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsMaxSdkInFuture() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"" + (Build.VERSION.SDK_INT + 1) + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ private void parseSharedLibraries(String contents) throws IOException {
+ File folder = createTempSubfolder("permissions_folder");
+ createTempFile(folder, "permissions.xml", contents);
+ readPermissions(folder, /* permissionFlag = ALLOW_LIBS */ 0x02);
+ }
+
+ /**
+ * Create an {@link XmlPullParser} for {@param permissionFile} and begin parsing it until
+ * reaching the root tag.
+ */
+ private XmlPullParser readXmlUntilStartTag(File permissionFile)
+ throws IOException, XmlPullParserException {
+ FileReader permReader = new FileReader(permissionFile);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(permReader);
+ int type;
+ do {
+ type = parser.next();
+ } while (type != parser.START_TAG && type != parser.END_DOCUMENT);
+ if (type != parser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+ return parser;
+ }
+
/**
* Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
*
@@ -331,7 +607,7 @@ public class SystemConfigTest {
private File createTempSubfolder(String folderName)
throws IOException {
File folder = new File(mTemporaryFolder.getRoot(), folderName);
- folder.mkdir();
+ folder.mkdirs();
return folder;
}
@@ -341,7 +617,7 @@ public class SystemConfigTest {
* @param folder pre-existing subdirectory of mTemporaryFolder to put the file
* @param fileName name of the file (e.g. filename.xml) to create
* @param contents contents to write to the file
- * @return the folder containing the newly created file (not the file itself!)
+ * @return the newly created file
*/
private File createTempFile(File folder, String fileName, String contents)
throws IOException {
@@ -357,6 +633,13 @@ public class SystemConfigTest {
Log.d(LOG_TAG, input.nextLine());
}
- return folder;
+ return file;
+ }
+
+ private void assertFooIsOnlySharedLibrary() {
+ assertThat(mSysConfig.getSharedLibraries().size()).isEqualTo(1);
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.name).isEqualTo("foo");
+ assertThat(entry.filename).isEqualTo(mFooJar.toString());
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f8014c88a037..4f94a6213234 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -28,6 +28,7 @@ import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.net.NetworkCapabilities;
import android.net.ipsec.ike.SaProposal;
import android.os.Build;
import android.os.PersistableBundle;
@@ -3777,30 +3778,42 @@ public class CarrierConfigManager {
public static final String KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL =
"opportunistic_esim_download_via_wifi_only_bool";
- /**
- * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
+/**
+ * Controls RSRP threshold, in dBm, at which OpportunisticNetworkService will decide whether
* the opportunistic network is good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRsrp()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT =
"opportunistic_network_entry_threshold_rsrp_int";
/**
- * Controls RSSNR threshold at which OpportunisticNetworkService will decide whether
- * the opportunistic network is good enough for internet data.
+ * Controls RSSNR threshold, in dB, at which OpportunisticNetworkService will
+ * decide whether the opportunistic network is good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRssnr()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT =
"opportunistic_network_entry_threshold_rssnr_int";
/**
- * Controls RSRP threshold below which OpportunisticNetworkService will decide whether
+ * Controls RSRP threshold, in dBm, below which OpportunisticNetworkService will decide whether
* the opportunistic network available is not good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRsrp()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT =
"opportunistic_network_exit_threshold_rsrp_int";
/**
- * Controls RSSNR threshold below which OpportunisticNetworkService will decide whether
- * the opportunistic network available is not good enough for internet data.
+ * Controls RSSNR threshold, in dB, below which OpportunisticNetworkService will
+ * decide whether the opportunistic network available is not good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRssnr()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT =
"opportunistic_network_exit_threshold_rssnr_int";
@@ -3898,7 +3911,7 @@ public class CarrierConfigManager {
* good enough for internet data. Note other factors may be considered for the final
* decision.
*
- * <p>The value of {@link CellSignalStrengthNr#getSsRsrp} will be compared with this
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrp()} will be compared with this
* threshold.
*
* @hide
@@ -3925,7 +3938,7 @@ public class CarrierConfigManager {
* good enough for internet data. Note other factors may be considered for the final
* decision.
*
- * <p>The value of {@link CellSignalStrengthNr#getSsRsrq} will be compared with this
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrq()} will be compared with this
* threshold.
*
* @hide
@@ -3952,6 +3965,9 @@ public class CarrierConfigManager {
* be considered good enough for internet data. Note other factors may be considered
* for the final decision.
*
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrp()} will be compared with this
+ * threshold.
+ *
* @hide
*/
public static final String KEY_EXIT_THRESHOLD_SS_RSRP_INT =
@@ -3975,6 +3991,9 @@ public class CarrierConfigManager {
* be considered good enough for internet data. Note other factors may be considered
* for the final decision.
*
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrq()} will be compared with this
+ * threshold.
+ *
* @hide
*/
public static final String KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE =
@@ -5457,6 +5476,38 @@ public class CarrierConfigManager {
*/
public static final String KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY =
"telephony_network_capability_priorities_string_array";
+
+ /**
+ * Defines the rules for data retry.
+ *
+ * The syntax of the retry rule:
+ * 1. Retry based on {@link NetworkCapabilities}
+ * "capabilities=[netCaps1|netCaps2|...], [retry_interval=x], [backoff=[true|false]],
+ * [maximum_retries=y]"
+ *
+ * 2. Retry based on {@link DataFailCause}
+ * "fail_causes=[cause1|cause2|cause3|...], [retry_interval=x], [backoff=[true|false]],
+ * [maximum_retries=y]"
+ *
+ * 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}
+ * "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...],
+ * [retry_interval=x], [backoff=[true|false]], [maximum_retries=y]"
+ *
+ * For example,
+ * "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached
+ * network request is emergency, then retry data network setup every 1 second for up to 20
+ * times.
+ *
+ * "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|2254
+ * , maximum_retries=0" means for those fail causes, never retry with timers. Note that
+ * when environment changes, retry can still happens.
+ *
+ * // TODO: remove KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS
+ * @hide
+ */
+ public static final String KEY_TELEPHONY_DATA_RETRY_RULES_STRING_ARRAY =
+ "telephony_data_retry_rules_string_array";
+
/**
* The patterns of missed incoming call sms. This is the regular expression used for
* matching the missed incoming call's date, time, and caller id. The pattern should match
@@ -6147,9 +6198,9 @@ public class CarrierConfigManager {
/* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT, -118);
/* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_GOOD */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 45);
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 5);
/* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_MODERATE */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 10);
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 1);
/* Default value is 1024 kbps */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024);
/* Default value is 10 seconds */
@@ -6230,6 +6281,15 @@ public class CarrierConfigManager {
"eims:90", "supl:80", "mms:70", "xcap:70", "cbs:50", "mcx:50", "fota:50",
"ims:40", "dun:30", "enterprise:20", "internet:20"
});
+ sDefaults.putStringArray(
+ KEY_TELEPHONY_DATA_RETRY_RULES_STRING_ARRAY, new String[] {
+ "capabilities=eims, retry_interval=1000, maximum_retries=20",
+ "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|"
+ + "2254, maximum_retries=0", // No retry for those causes
+ "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2000, "
+ + "backoff=true, maximum_retries=13",
+ "capabilities=mms|supl|cbs, retry_interval=2000"
+ });
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 947dc0107dba..5e902613a654 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -125,13 +125,13 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
/**
* Construct a cell signal strength
*
- * @param rssi in dBm [-113,-51], UNKNOWN
- * @param rsrp in dBm [-140,-43], UNKNOWN
- * @param rsrq in dB [-34, 3], UNKNOWN
- * @param rssnr in dB [-20, +30], UNKNOWN
- * @param cqiTableIndex [1, 6], UNKNOWN
- * @param cqi [0, 15], UNKNOWN
- * @param timingAdvance [0, 1282], UNKNOWN
+ * @param rssi in dBm [-113,-51], {@link CellInfo#UNAVAILABLE}
+ * @param rsrp in dBm [-140,-43], {@link CellInfo#UNAVAILABLE}
+ * @param rsrq in dB [-34, 3], {@link CellInfo#UNAVAILABLE}
+ * @param rssnr in dB [-20, +30], {@link CellInfo#UNAVAILABLE}
+ * @param cqiTableIndex [1, 6], {@link CellInfo#UNAVAILABLE}
+ * @param cqi [0, 15], {@link CellInfo#UNAVAILABLE}
+ * @param timingAdvance [0, 1282], {@link CellInfo#UNAVAILABLE}
*
*/
/** @hide */
@@ -151,12 +151,12 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
/**
* Construct a cell signal strength
*
- * @param rssi in dBm [-113,-51], UNKNOWN
- * @param rsrp in dBm [-140,-43], UNKNOWN
- * @param rsrq in dB [-34, 3], UNKNOWN
- * @param rssnr in dB [-20, +30], UNKNOWN
- * @param cqi [0, 15], UNKNOWN
- * @param timingAdvance [0, 1282], UNKNOWN
+ * @param rssi in dBm [-113,-51], {@link CellInfo#UNAVAILABLE}
+ * @param rsrp in dBm [-140,-43], {@link CellInfo#UNAVAILABLE}
+ * @param rsrq in dB [-34, 3], {@link CellInfo#UNAVAILABLE}
+ * @param rssnr in dB [-20, +30], {@link CellInfo#UNAVAILABLE}
+ * @param cqi [0, 15], {@link CellInfo#UNAVAILABLE}
+ * @param timingAdvance [0, 1282], {@link CellInfo#UNAVAILABLE}
*
*/
/** @hide */
@@ -403,10 +403,11 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
}
/**
- * Get reference signal signal-to-noise ratio
+ * Get reference signal signal-to-noise ratio in dB
+ * Range: -20 dB to +30 dB.
*
* @return the RSSNR if available or
- * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
+ * {@link android.telephony.CellInfo#UNAVAILABLE} if unavailable.
*/
public int getRssnr() {
return mRssnr;
@@ -414,8 +415,10 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
/**
* Get reference signal received power in dBm
+ * Range: -140 dBm to -43 dBm.
*
- * @return the RSRP of the measured cell.
+ * @return the RSRP of the measured cell or {@link CellInfo#UNAVAILABLE} if
+ * unavailable.
*/
public int getRsrp() {
return mRsrp;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index d6dce25d931f..8c02ffe12363 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -2158,8 +2158,7 @@ public class ApnSetting implements Parcelable {
| TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
| TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE)) == 0
|| TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
- throw new IllegalArgumentException("mApName=" + mApnName + ", mEntryName="
- + mEntryName + ", mApnTypeBitmask=" + mApnTypeBitmask);
+ return null;
}
return new ApnSetting(this);
}
diff --git a/tests/TrustTests/OWNERS b/tests/TrustTests/OWNERS
new file mode 100644
index 000000000000..e2c6ce15b51e
--- /dev/null
+++ b/tests/TrustTests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/trust/OWNERS