summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt1
-rw-r--r--core/java/android/net/NetworkAgent.java44
-rw-r--r--core/java/android/net/NetworkCapabilities.java5
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java425
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreProvider.java3
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java190
-rw-r--r--services/core/java/com/android/server/OWNERS3
-rw-r--r--services/core/java/com/android/server/UserspaceRebootLogger.java10
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java16
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java14
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorService.java2
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java66
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java17
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java97
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java101
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java9
17 files changed, 703 insertions, 302 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index f6b1d0627312..d047a99a834f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6175,6 +6175,7 @@ package android.net {
method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
method public final void sendSocketKeepaliveEvent(int, int);
+ method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 44ebff99f3e9..0676ad4e2322 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -40,6 +40,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -174,6 +175,14 @@ public abstract class NetworkAgent {
public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
/**
+ * Sent by the NetworkAgent to ConnectivityService to pass the current
+ * list of underlying networks.
+ * obj = array of Network objects
+ * @hide
+ */
+ public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5;
+
+ /**
* Sent by ConnectivityService to the NetworkAgent to inform the agent of the
* networks status - whether we could use the network or could not, due to
* either a bad network configuration (no internet link) or captive portal.
@@ -217,7 +226,13 @@ public abstract class NetworkAgent {
* The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}.
* @hide
*/
- public static String REDIRECT_URL_KEY = "redirect URL";
+ public static final String REDIRECT_URL_KEY = "redirect URL";
+
+ /**
+ * Bundle key for the underlying networks in {@code EVENT_UNDERLYING_NETWORKS_CHANGED}.
+ * @hide
+ */
+ public static final String UNDERLYING_NETWORKS_KEY = "underlyingNetworks";
/**
* Sent by the NetworkAgent to ConnectivityService to indicate this network was
@@ -650,6 +665,33 @@ public abstract class NetworkAgent {
}
/**
+ * Must be called by the agent when the network's underlying networks change.
+ *
+ * <p>{@code networks} is one of the following:
+ * <ul>
+ * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in
+ * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular)
+ * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear
+ * first in the array.</li>
+ * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no
+ * underlying network connection, and thus, app traffic will not be sent or received.</li>
+ * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's
+ * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket}
+ * APIs mentioned above to send traffic over specific channels.</li>
+ * </ul>
+ *
+ * @param underlyingNetworks the new list of underlying networks.
+ * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])}
+ */
+ public final void setUnderlyingNetworks(@Nullable List<Network> underlyingNetworks) {
+ final ArrayList<Network> underlyingArray = (underlyingNetworks != null)
+ ? new ArrayList<>(underlyingNetworks) : null;
+ final Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(UNDERLYING_NETWORKS_KEY, underlyingArray);
+ queueOrSendMessage(EVENT_UNDERLYING_NETWORKS_CHANGED, bundle);
+ }
+
+ /**
* Inform ConnectivityService that this agent has now connected.
* Call {@link #unregister} to disconnect.
*/
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 40bb8bf11d0b..8dad11ffa731 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -712,6 +712,7 @@ public final class NetworkCapabilities implements Parcelable {
if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) {
setAdministratorUids(new int[] {creatorUid});
}
+ // There is no need to clear the UIDs, they have already been cleared by clearAll() above.
}
/**
@@ -805,7 +806,9 @@ public final class NetworkCapabilities implements Parcelable {
*/
private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST
// Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces
- | 1 << TRANSPORT_ETHERNET;
+ | 1 << TRANSPORT_ETHERNET
+ // Test VPN networks can be created but their UID ranges must be empty.
+ | 1 << TRANSPORT_VPN;
/**
* Adds the given transport type to this {@code NetworkCapability} instance.
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 18921639f55d..6ef9e7e3d9b8 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -16,6 +16,19 @@
package android.security.keymaster;
+import android.hardware.keymint.Algorithm;
+import android.hardware.keymint.BlockMode;
+import android.hardware.keymint.Digest;
+import android.hardware.keymint.ErrorCode;
+import android.hardware.keymint.HardwareAuthenticatorType;
+import android.hardware.keymint.KeyFormat;
+import android.hardware.keymint.KeyOrigin;
+import android.hardware.keymint.KeyPurpose;
+import android.hardware.keymint.PaddingMode;
+import android.hardware.keymint.SecurityLevel;
+import android.hardware.keymint.Tag;
+import android.hardware.keymint.TagType;
+
import java.util.HashMap;
import java.util.Map;
@@ -30,206 +43,284 @@ public final class KeymasterDefs {
private KeymasterDefs() {}
// Tag types.
- public static final int KM_INVALID = 0 << 28;
- public static final int KM_ENUM = 1 << 28;
- public static final int KM_ENUM_REP = 2 << 28;
- public static final int KM_UINT = 3 << 28;
- public static final int KM_UINT_REP = 4 << 28;
- public static final int KM_ULONG = 5 << 28;
- public static final int KM_DATE = 6 << 28;
- public static final int KM_BOOL = 7 << 28;
- public static final int KM_BIGNUM = 8 << 28;
- public static final int KM_BYTES = 9 << 28;
- public static final int KM_ULONG_REP = 10 << 28;
+ public static final int KM_INVALID = TagType.INVALID;
+ public static final int KM_ENUM = TagType.ENUM;
+ public static final int KM_ENUM_REP = TagType.ENUM_REP;
+ public static final int KM_UINT = TagType.UINT;
+ public static final int KM_UINT_REP = TagType.UINT_REP;
+ public static final int KM_ULONG = TagType.ULONG;
+ public static final int KM_DATE = TagType.DATE;
+ public static final int KM_BOOL = TagType.BOOL;
+ public static final int KM_BIGNUM = TagType.BIGNUM;
+ public static final int KM_BYTES = TagType.BYTES;
+ public static final int KM_ULONG_REP = TagType.ULONG_REP;
// Tag values.
- public static final int KM_TAG_INVALID = KM_INVALID | 0;
- public static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
- public static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
- public static final int KM_TAG_KEY_SIZE = KM_UINT | 3;
- public static final int KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4;
- public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
- public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
- public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
- public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8;
+ public static final int KM_TAG_INVALID = Tag.INVALID; // KM_INVALID | 0;
+ public static final int KM_TAG_PURPOSE = Tag.PURPOSE; // KM_ENUM_REP | 1;
+ public static final int KM_TAG_ALGORITHM = Tag.ALGORITHM; // KM_ENUM | 2;
+ public static final int KM_TAG_KEY_SIZE = Tag.KEY_SIZE; // KM_UINT | 3;
+ public static final int KM_TAG_BLOCK_MODE = Tag.BLOCK_MODE; // KM_ENUM_REP | 4;
+ public static final int KM_TAG_DIGEST = Tag.DIGEST; // KM_ENUM_REP | 5;
+ public static final int KM_TAG_PADDING = Tag.PADDING; // KM_ENUM_REP | 6;
+ public static final int KM_TAG_CALLER_NONCE = Tag.CALLER_NONCE; // KM_BOOL | 7;
+ public static final int KM_TAG_MIN_MAC_LENGTH = Tag.MIN_MAC_LENGTH; // KM_UINT | 8;
- public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
- public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
- public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 705;
+ public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS =
+ Tag.BLOB_USAGE_REQUIREMENTS; // KM_ENUM | 705;
- public static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200;
- public static final int KM_TAG_INCLUDE_UNIQUE_ID = KM_BOOL | 202;
+ public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
+ public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
- public static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
- public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
- public static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
- public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_UINT | 403;
- public static final int KM_TAG_MAX_USES_PER_BOOT = KM_UINT | 404;
+ public static final int KM_TAG_ACTIVE_DATETIME = Tag.ACTIVE_DATETIME; // KM_DATE | 400;
+ public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME =
+ Tag.ORIGINATION_EXPIRE_DATETIME; // KM_DATE | 401;
+ public static final int KM_TAG_USAGE_EXPIRE_DATETIME =
+ Tag.USAGE_EXPIRE_DATETIME; // KM_DATE | 402;
+ public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS =
+ Tag.MIN_SECONDS_BETWEEN_OPS; // KM_UINT | 403;
+ public static final int KM_TAG_MAX_USES_PER_BOOT = Tag.MAX_USES_PER_BOOT; // KM_UINT | 404;
- public static final int KM_TAG_ALL_USERS = KM_BOOL | 500;
- public static final int KM_TAG_USER_ID = KM_UINT | 501;
- public static final int KM_TAG_USER_SECURE_ID = KM_ULONG_REP | 502;
- public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
- public static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
- public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
- public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
- public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
- public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
- public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
+ public static final int KM_TAG_USER_ID = Tag.USER_ID; // KM_UINT | 501;
+ public static final int KM_TAG_USER_SECURE_ID = Tag.USER_SECURE_ID; // KM_ULONG_REP | 502;
+ public static final int KM_TAG_NO_AUTH_REQUIRED = Tag.NO_AUTH_REQUIRED; // KM_BOOL | 503;
+ public static final int KM_TAG_USER_AUTH_TYPE = Tag.USER_AUTH_TYPE; // KM_ENUM | 504;
+ public static final int KM_TAG_AUTH_TIMEOUT = Tag.AUTH_TIMEOUT; // KM_UINT | 505;
+ public static final int KM_TAG_ALLOW_WHILE_ON_BODY = Tag.ALLOW_WHILE_ON_BODY; // KM_BOOL | 506;
+ public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED =
+ Tag.TRUSTED_USER_PRESENCE_REQUIRED; // KM_BOOL | 507;
+ public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED =
+ Tag.TRUSTED_CONFIRMATION_REQUIRED; // KM_BOOL | 508;
+ public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED =
+ Tag.UNLOCKED_DEVICE_REQUIRED; // KM_BOOL | 509;
- public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
- public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
+ public static final int KM_TAG_APPLICATION_ID = Tag.APPLICATION_ID; // KM_BYTES | 601;
- public static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701;
- public static final int KM_TAG_ORIGIN = KM_ENUM | 702;
- public static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703;
- public static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704;
- public static final int KM_TAG_UNIQUE_ID = KM_BYTES | 707;
- public static final int KM_TAG_ATTESTATION_CHALLENGE = KM_BYTES | 708;
- public static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710;
- public static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711;
- public static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712;
- public static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713;
- public static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714;
- public static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715;
- public static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716;
- public static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717;
- public static final int KM_TAG_VENDOR_PATCHLEVEL = KM_UINT | 718;
- public static final int KM_TAG_BOOT_PATCHLEVEL = KM_UINT | 719;
- public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION = KM_BOOL | 720;
+ public static final int KM_TAG_CREATION_DATETIME = Tag.CREATION_DATETIME; // KM_DATE | 701;
+ public static final int KM_TAG_ORIGIN = Tag.ORIGIN; // KM_ENUM | 702;
+ public static final int KM_TAG_ROLLBACK_RESISTANT = Tag.ROLLBACK_RESISTANCE; // KM_BOOL | 703;
+ public static final int KM_TAG_ROOT_OF_TRUST = Tag.ROOT_OF_TRUST; // KM_BYTES | 704;
+ public static final int KM_TAG_UNIQUE_ID = Tag.UNIQUE_ID; // KM_BYTES | 707;
+ public static final int KM_TAG_ATTESTATION_CHALLENGE =
+ Tag.ATTESTATION_CHALLENGE; // KM_BYTES | 708;
+ public static final int KM_TAG_ATTESTATION_ID_BRAND =
+ Tag.ATTESTATION_ID_BRAND; // KM_BYTES | 710;
+ public static final int KM_TAG_ATTESTATION_ID_DEVICE =
+ Tag.ATTESTATION_ID_DEVICE; // KM_BYTES | 711;
+ public static final int KM_TAG_ATTESTATION_ID_PRODUCT =
+ Tag.ATTESTATION_ID_PRODUCT; // KM_BYTES | 712;
+ public static final int KM_TAG_ATTESTATION_ID_SERIAL =
+ Tag.ATTESTATION_ID_SERIAL; // KM_BYTES | 713;
+ public static final int KM_TAG_ATTESTATION_ID_IMEI =
+ Tag.ATTESTATION_ID_IMEI; // KM_BYTES | 714;
+ public static final int KM_TAG_ATTESTATION_ID_MEID =
+ Tag.ATTESTATION_ID_MEID; // KM_BYTES | 715;
+ public static final int KM_TAG_ATTESTATION_ID_MANUFACTURER =
+ Tag.ATTESTATION_ID_MANUFACTURER; // KM_BYTES | 716;
+ public static final int KM_TAG_ATTESTATION_ID_MODEL =
+ Tag.ATTESTATION_ID_MODEL; // KM_BYTES | 717;
+ public static final int KM_TAG_VENDOR_PATCHLEVEL =
+ Tag.VENDOR_PATCHLEVEL; // KM_UINT | 718;
+ public static final int KM_TAG_BOOT_PATCHLEVEL =
+ Tag.BOOT_PATCHLEVEL; // KM_UINT | 719;
+ public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION =
+ Tag.DEVICE_UNIQUE_ATTESTATION; // KM_BOOL | 720;
- public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
- public static final int KM_TAG_NONCE = KM_BYTES | 1001;
- public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002;
- public static final int KM_TAG_MAC_LENGTH = KM_UINT | 1003;
+ public static final int KM_TAG_ASSOCIATED_DATA = Tag.ASSOCIATED_DATA; // KM_BYTES | 1000;
+ public static final int KM_TAG_NONCE = Tag.NONCE; // KM_BYTES | 1001;
+ public static final int KM_TAG_MAC_LENGTH = Tag.MAC_LENGTH; // KM_UINT | 1003;
// Algorithm values.
- public static final int KM_ALGORITHM_RSA = 1;
- public static final int KM_ALGORITHM_EC = 3;
- public static final int KM_ALGORITHM_AES = 32;
- public static final int KM_ALGORITHM_3DES = 33;
- public static final int KM_ALGORITHM_HMAC = 128;
+ public static final int KM_ALGORITHM_RSA = Algorithm.RSA;
+ public static final int KM_ALGORITHM_EC = Algorithm.EC;
+ public static final int KM_ALGORITHM_AES = Algorithm.AES;
+ public static final int KM_ALGORITHM_3DES = Algorithm.TRIPLE_DES;
+ public static final int KM_ALGORITHM_HMAC = Algorithm.HMAC;
// Block modes.
- public static final int KM_MODE_ECB = 1;
- public static final int KM_MODE_CBC = 2;
- public static final int KM_MODE_CTR = 3;
- public static final int KM_MODE_GCM = 32;
+ public static final int KM_MODE_ECB = BlockMode.ECB;
+ public static final int KM_MODE_CBC = BlockMode.CBC;
+ public static final int KM_MODE_CTR = BlockMode.CTR;
+ public static final int KM_MODE_GCM = BlockMode.GCM;
// Padding modes.
- public static final int KM_PAD_NONE = 1;
- public static final int KM_PAD_RSA_OAEP = 2;
- public static final int KM_PAD_RSA_PSS = 3;
- public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4;
- public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5;
- public static final int KM_PAD_PKCS7 = 64;
+ public static final int KM_PAD_NONE = PaddingMode.NONE;
+ public static final int KM_PAD_RSA_OAEP = PaddingMode.RSA_OAEP;
+ public static final int KM_PAD_RSA_PSS = PaddingMode.RSA_PSS;
+ public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = PaddingMode.RSA_PKCS1_1_5_ENCRYPT;
+ public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = PaddingMode.RSA_PKCS1_1_5_SIGN;
+ public static final int KM_PAD_PKCS7 = PaddingMode.PKCS7;
// Digest modes.
- public static final int KM_DIGEST_NONE = 0;
- public static final int KM_DIGEST_MD5 = 1;
- public static final int KM_DIGEST_SHA1 = 2;
- public static final int KM_DIGEST_SHA_2_224 = 3;
- public static final int KM_DIGEST_SHA_2_256 = 4;
- public static final int KM_DIGEST_SHA_2_384 = 5;
- public static final int KM_DIGEST_SHA_2_512 = 6;
+ public static final int KM_DIGEST_NONE = Digest.NONE;
+ public static final int KM_DIGEST_MD5 = Digest.MD5;
+ public static final int KM_DIGEST_SHA1 = Digest.SHA1;
+ public static final int KM_DIGEST_SHA_2_224 = Digest.SHA_2_224;
+ public static final int KM_DIGEST_SHA_2_256 = Digest.SHA_2_256;
+ public static final int KM_DIGEST_SHA_2_384 = Digest.SHA_2_384;
+ public static final int KM_DIGEST_SHA_2_512 = Digest.SHA_2_512;
// Key origins.
- public static final int KM_ORIGIN_GENERATED = 0;
- public static final int KM_ORIGIN_IMPORTED = 2;
- public static final int KM_ORIGIN_UNKNOWN = 3;
- public static final int KM_ORIGIN_SECURELY_IMPORTED = 4;
+ public static final int KM_ORIGIN_GENERATED = KeyOrigin.GENERATED;
+ public static final int KM_ORIGIN_DERIVED = KeyOrigin.DERIVED;
+ public static final int KM_ORIGIN_IMPORTED = KeyOrigin.IMPORTED;
+ public static final int KM_ORIGIN_UNKNOWN = KeyOrigin.RESERVED;
+ public static final int KM_ORIGIN_SECURELY_IMPORTED = KeyOrigin.SECURELY_IMPORTED;
// Key usability requirements.
public static final int KM_BLOB_STANDALONE = 0;
public static final int KM_BLOB_REQUIRES_FILE_SYSTEM = 1;
// Operation Purposes.
- public static final int KM_PURPOSE_ENCRYPT = 0;
- public static final int KM_PURPOSE_DECRYPT = 1;
- public static final int KM_PURPOSE_SIGN = 2;
- public static final int KM_PURPOSE_VERIFY = 3;
- public static final int KM_PURPOSE_WRAP = 5;
+ public static final int KM_PURPOSE_ENCRYPT = KeyPurpose.ENCRYPT;
+ public static final int KM_PURPOSE_DECRYPT = KeyPurpose.DECRYPT;
+ public static final int KM_PURPOSE_SIGN = KeyPurpose.SIGN;
+ public static final int KM_PURPOSE_VERIFY = KeyPurpose.VERIFY;
+ public static final int KM_PURPOSE_WRAP = KeyPurpose.WRAP_KEY;
// Key formats.
- public static final int KM_KEY_FORMAT_X509 = 0;
- public static final int KM_KEY_FORMAT_PKCS8 = 1;
- public static final int KM_KEY_FORMAT_RAW = 3;
+ public static final int KM_KEY_FORMAT_X509 = KeyFormat.X509;
+ public static final int KM_KEY_FORMAT_PKCS8 = KeyFormat.PKCS8;
+ public static final int KM_KEY_FORMAT_RAW = KeyFormat.RAW;
// User authenticators.
- public static final int HW_AUTH_PASSWORD = 1 << 0;
- public static final int HW_AUTH_BIOMETRIC = 1 << 1;
+ public static final int HW_AUTH_PASSWORD = HardwareAuthenticatorType.PASSWORD;
+ public static final int HW_AUTH_BIOMETRIC = HardwareAuthenticatorType.FINGERPRINT;
// Security Levels.
- public static final int KM_SECURITY_LEVEL_SOFTWARE = 0;
- public static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1;
- public static final int KM_SECURITY_LEVEL_STRONGBOX = 2;
+ public static final int KM_SECURITY_LEVEL_SOFTWARE = SecurityLevel.SOFTWARE;
+ public static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT =
+ SecurityLevel.TRUSTED_ENVIRONMENT;
+ public static final int KM_SECURITY_LEVEL_STRONGBOX = SecurityLevel.STRONGBOX;
// Error codes.
- public static final int KM_ERROR_OK = 0;
- public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1;
- public static final int KM_ERROR_UNSUPPORTED_PURPOSE = -2;
- public static final int KM_ERROR_INCOMPATIBLE_PURPOSE = -3;
- public static final int KM_ERROR_UNSUPPORTED_ALGORITHM = -4;
- public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM = -5;
- public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6;
- public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7;
- public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8;
- public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9;
- public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10;
- public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11;
- public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12;
- public static final int KM_ERROR_INCOMPATIBLE_DIGEST = -13;
- public static final int KM_ERROR_INVALID_EXPIRATION_TIME = -14;
- public static final int KM_ERROR_INVALID_USER_ID = -15;
- public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16;
- public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17;
- public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18;
- public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19;
- public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20;
- public static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
- public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22;
- public static final int KM_ERROR_DELEGATION_NOT_ALLOWED = -23;
- public static final int KM_ERROR_KEY_NOT_YET_VALID = -24;
- public static final int KM_ERROR_KEY_EXPIRED = -25;
- public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26;
- public static final int KM_ERROR_OUTPUT_PARAMETER_NULL = -27;
- public static final int KM_ERROR_INVALID_OPERATION_HANDLE = -28;
- public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29;
- public static final int KM_ERROR_VERIFICATION_FAILED = -30;
- public static final int KM_ERROR_TOO_MANY_OPERATIONS = -31;
- public static final int KM_ERROR_UNEXPECTED_NULL_POINTER = -32;
- public static final int KM_ERROR_INVALID_KEY_BLOB = -33;
- public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34;
- public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35;
- public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36;
- public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37;
- public static final int KM_ERROR_INVALID_ARGUMENT = -38;
- public static final int KM_ERROR_UNSUPPORTED_TAG = -39;
- public static final int KM_ERROR_INVALID_TAG = -40;
- public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED = -41;
- public static final int KM_ERROR_INVALID_RESCOPING = -42;
- public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44;
- public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED = -45;
- public static final int KM_ERROR_OPERATION_CANCELLED = -46;
- public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47;
- public static final int KM_ERROR_SECURE_HW_BUSY = -48;
- public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49;
- public static final int KM_ERROR_UNSUPPORTED_EC_FIELD = -50;
- public static final int KM_ERROR_MISSING_NONCE = -51;
- public static final int KM_ERROR_INVALID_NONCE = -52;
- public static final int KM_ERROR_MISSING_MAC_LENGTH = -53;
- public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
- public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
- public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
- public static final int KM_ERROR_INVALID_MAC_LENGTH = -57;
- public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
- public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
- public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
- public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = -68;
- public static final int KM_ERROR_DEVICE_LOCKED = -72;
- public static final int KM_ERROR_UNIMPLEMENTED = -100;
- public static final int KM_ERROR_VERSION_MISMATCH = -101;
- public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
+ public static final int KM_ERROR_OK = ErrorCode.OK;
+ public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET =
+ ErrorCode.ROOT_OF_TRUST_ALREADY_SET; // -1;
+ public static final int KM_ERROR_UNSUPPORTED_PURPOSE =
+ ErrorCode.UNSUPPORTED_PURPOSE; // -2;
+ public static final int KM_ERROR_INCOMPATIBLE_PURPOSE =
+ ErrorCode.INCOMPATIBLE_PURPOSE; // -3;
+ public static final int KM_ERROR_UNSUPPORTED_ALGORITHM =
+ ErrorCode.UNSUPPORTED_ALGORITHM; // -4;
+ public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM =
+ ErrorCode.INCOMPATIBLE_ALGORITHM; // -5;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE =
+ ErrorCode.UNSUPPORTED_KEY_SIZE; // -6;
+ public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE =
+ ErrorCode.UNSUPPORTED_BLOCK_MODE; // -7;
+ public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE =
+ ErrorCode.INCOMPATIBLE_BLOCK_MODE; // -8;
+ public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH =
+ ErrorCode.UNSUPPORTED_MAC_LENGTH; // -9;
+ public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE =
+ ErrorCode.UNSUPPORTED_PADDING_MODE; // -10;
+ public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE =
+ ErrorCode.INCOMPATIBLE_PADDING_MODE; // -11;
+ public static final int KM_ERROR_UNSUPPORTED_DIGEST =
+ ErrorCode.UNSUPPORTED_DIGEST; // -12;
+ public static final int KM_ERROR_INCOMPATIBLE_DIGEST =
+ ErrorCode.INCOMPATIBLE_DIGEST; // -13;
+ public static final int KM_ERROR_INVALID_EXPIRATION_TIME =
+ ErrorCode.INVALID_EXPIRATION_TIME; // -14;
+ public static final int KM_ERROR_INVALID_USER_ID =
+ ErrorCode.INVALID_USER_ID; // -15;
+ public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT =
+ ErrorCode.INVALID_AUTHORIZATION_TIMEOUT; // -16;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT =
+ ErrorCode.UNSUPPORTED_KEY_FORMAT; // -17;
+ public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT =
+ ErrorCode.INCOMPATIBLE_KEY_FORMAT; // -18;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM =
+ ErrorCode.UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM; // -19;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM =
+ ErrorCode.UNSUPPORTED_KEY_VERIFICATION_ALGORITHM; // -20;
+ public static final int KM_ERROR_INVALID_INPUT_LENGTH =
+ ErrorCode.INVALID_INPUT_LENGTH; // -21;
+ public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID =
+ ErrorCode.KEY_EXPORT_OPTIONS_INVALID; // -22;
+ public static final int KM_ERROR_DELEGATION_NOT_ALLOWED =
+ ErrorCode.DELEGATION_NOT_ALLOWED; // -23;
+ public static final int KM_ERROR_KEY_NOT_YET_VALID =
+ ErrorCode.KEY_NOT_YET_VALID; // -24;
+ public static final int KM_ERROR_KEY_EXPIRED =
+ ErrorCode.KEY_EXPIRED; // -25;
+ public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED =
+ ErrorCode.KEY_USER_NOT_AUTHENTICATED; // -26;
+ public static final int KM_ERROR_OUTPUT_PARAMETER_NULL =
+ ErrorCode.OUTPUT_PARAMETER_NULL; // -27;
+ public static final int KM_ERROR_INVALID_OPERATION_HANDLE =
+ ErrorCode.INVALID_OPERATION_HANDLE; // -28;
+ public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE =
+ ErrorCode.INSUFFICIENT_BUFFER_SPACE; // -29;
+ public static final int KM_ERROR_VERIFICATION_FAILED =
+ ErrorCode.VERIFICATION_FAILED; // -30;
+ public static final int KM_ERROR_TOO_MANY_OPERATIONS =
+ ErrorCode.TOO_MANY_OPERATIONS; // -31;
+ public static final int KM_ERROR_UNEXPECTED_NULL_POINTER =
+ ErrorCode.UNEXPECTED_NULL_POINTER; // -32;
+ public static final int KM_ERROR_INVALID_KEY_BLOB =
+ ErrorCode.INVALID_KEY_BLOB; // -33;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED =
+ ErrorCode.IMPORTED_KEY_NOT_ENCRYPTED; // -34;
+ public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED =
+ ErrorCode.IMPORTED_KEY_DECRYPTION_FAILED; // -35;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED =
+ ErrorCode.IMPORTED_KEY_NOT_SIGNED; // -36;
+ public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED =
+ ErrorCode.IMPORTED_KEY_VERIFICATION_FAILED; // -37;
+ public static final int KM_ERROR_INVALID_ARGUMENT =
+ ErrorCode.INVALID_ARGUMENT; // -38;
+ public static final int KM_ERROR_UNSUPPORTED_TAG =
+ ErrorCode.UNSUPPORTED_TAG; // -39;
+ public static final int KM_ERROR_INVALID_TAG =
+ ErrorCode.INVALID_TAG; // -40;
+ public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED =
+ ErrorCode.MEMORY_ALLOCATION_FAILED; // -41;
+ public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH =
+ ErrorCode.IMPORT_PARAMETER_MISMATCH; // -44;
+ public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED =
+ ErrorCode.SECURE_HW_ACCESS_DENIED; // -45;
+ public static final int KM_ERROR_OPERATION_CANCELLED =
+ ErrorCode.OPERATION_CANCELLED; // -46;
+ public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT =
+ ErrorCode.CONCURRENT_ACCESS_CONFLICT; // -47;
+ public static final int KM_ERROR_SECURE_HW_BUSY =
+ ErrorCode.SECURE_HW_BUSY; // -48;
+ public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED =
+ ErrorCode.SECURE_HW_COMMUNICATION_FAILED; // -49;
+ public static final int KM_ERROR_UNSUPPORTED_EC_FIELD =
+ ErrorCode.UNSUPPORTED_EC_FIELD; // -50;
+ public static final int KM_ERROR_MISSING_NONCE =
+ ErrorCode.MISSING_NONCE; // -51;
+ public static final int KM_ERROR_INVALID_NONCE =
+ ErrorCode.INVALID_NONCE; // -52;
+ public static final int KM_ERROR_MISSING_MAC_LENGTH =
+ ErrorCode.MISSING_MAC_LENGTH; // -53;
+ public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED =
+ ErrorCode.KEY_RATE_LIMIT_EXCEEDED; // -54;
+ public static final int KM_ERROR_CALLER_NONCE_PROHIBITED =
+ ErrorCode.CALLER_NONCE_PROHIBITED; // -55;
+ public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED =
+ ErrorCode.KEY_MAX_OPS_EXCEEDED; // -56;
+ public static final int KM_ERROR_INVALID_MAC_LENGTH =
+ ErrorCode.INVALID_MAC_LENGTH; // -57;
+ public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH =
+ ErrorCode.MISSING_MIN_MAC_LENGTH; // -58;
+ public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH =
+ ErrorCode.UNSUPPORTED_MIN_MAC_LENGTH; // -59;
+ public static final int KM_ERROR_CANNOT_ATTEST_IDS =
+ ErrorCode.CANNOT_ATTEST_IDS; // -66;
+ public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE =
+ ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68;
+ public static final int KM_ERROR_DEVICE_LOCKED =
+ ErrorCode.DEVICE_LOCKED; // -72;
+ public static final int KM_ERROR_UNIMPLEMENTED =
+ ErrorCode.UNIMPLEMENTED; // -100;
+ public static final int KM_ERROR_VERSION_MISMATCH =
+ ErrorCode.VERSION_MISMATCH; // -101;
+ public static final int KM_ERROR_UNKNOWN_ERROR =
+ ErrorCode.UNKNOWN_ERROR; // -1000;
public static final Map<Integer, String> sErrorCodeToString = new HashMap<Integer, String>();
static {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 5867ef6eaea5..b1b6306e0cf6 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -83,8 +83,7 @@ public class AndroidKeyStoreProvider extends Provider {
boolean supports3DES = "true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY));
// java.security.KeyStore
- put("KeyStore.AndroidKeyStore", PACKAGE_NAME + ".AndroidKeyStoreSpi");
- put("Alg.Alias.KeyStore.AndroidKeyStoreLegacy", "AndroidKeyStore");
+ put("KeyStore." + providerName, PACKAGE_NAME + ".AndroidKeyStoreSpi");
// java.security.KeyPairGenerator
put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC");
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f7de5c023b4f..5420ee2f11af 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2771,6 +2771,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkCapabilities = new NetworkCapabilities(networkCapabilities);
networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid);
}
+ processCapabilitiesFromAgent(nai, networkCapabilities);
updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
break;
}
@@ -2809,6 +2810,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
break;
}
+ case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
+ if (!nai.supportsUnderlyingNetworks()) {
+ Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
+ break;
+ }
+ final ArrayList<Network> underlying;
+ try {
+ underlying = ((Bundle) msg.obj).getParcelableArrayList(
+ NetworkAgent.UNDERLYING_NETWORKS_KEY);
+ } catch (NullPointerException | ClassCastException e) {
+ break;
+ }
+ final Network[] oldUnderlying = nai.declaredUnderlyingNetworks;
+ nai.declaredUnderlyingNetworks = (underlying != null)
+ ? underlying.toArray(new Network[0]) : null;
+
+ if (!Arrays.equals(oldUnderlying, nai.declaredUnderlyingNetworks)) {
+ if (DBG) {
+ log(nai.toShortString() + " changed underlying networks to "
+ + Arrays.toString(nai.declaredUnderlyingNetworks));
+ }
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ notifyIfacesChangedForNetworkStats();
+ }
+ }
}
}
@@ -3394,7 +3420,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mLegacyTypeTracker.remove(nai, wasDefault);
if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
@@ -4704,10 +4730,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mLockdownEnabled) {
return new VpnInfo[0];
}
-
List<VpnInfo> infoList = new ArrayList<>();
- for (int i = 0; i < mVpns.size(); i++) {
- VpnInfo info = createVpnInfo(mVpns.valueAt(i));
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ VpnInfo info = createVpnInfo(nai);
if (info != null) {
infoList.add(info);
}
@@ -4720,13 +4745,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @return VPN information for accounting, or null if we can't retrieve all required
* information, e.g underlying ifaces.
*/
- @Nullable
- private VpnInfo createVpnInfo(Vpn vpn) {
- VpnInfo info = vpn.getVpnInfo();
- if (info == null) {
- return null;
- }
- Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
+ private VpnInfo createVpnInfo(NetworkAgentInfo nai) {
+ if (!nai.isVPN()) return null;
+
+ Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
if (underlyingNetworks == null) {
@@ -4735,23 +4757,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
underlyingNetworks = new Network[] { defaultNai.network };
}
}
- if (underlyingNetworks != null && underlyingNetworks.length > 0) {
- List<String> interfaces = new ArrayList<>();
- for (Network network : underlyingNetworks) {
- LinkProperties lp = getLinkProperties(network);
- if (lp != null) {
- for (String iface : lp.getAllInterfaceNames()) {
- if (!TextUtils.isEmpty(iface)) {
- interfaces.add(iface);
- }
- }
+
+ if (ArrayUtils.isEmpty(underlyingNetworks)) return null;
+
+ List<String> interfaces = new ArrayList<>();
+ for (Network network : underlyingNetworks) {
+ NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network);
+ if (underlyingNai == null) continue;
+ LinkProperties lp = underlyingNai.linkProperties;
+ for (String iface : lp.getAllInterfaceNames()) {
+ if (!TextUtils.isEmpty(iface)) {
+ interfaces.add(iface);
}
}
- if (!interfaces.isEmpty()) {
- info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
- }
}
- return info.underlyingIfaces == null ? null : info;
+
+ if (interfaces.isEmpty()) return null;
+
+ VpnInfo info = new VpnInfo();
+ info.ownerUid = nai.networkCapabilities.getOwnerUid();
+ info.vpnIface = nai.linkProperties.getInterfaceName();
+ // Must be non-null or NetworkStatsService will crash.
+ // Cannot happen in production code because Vpn only registers the NetworkAgent after the
+ // tun or ipsec interface is created.
+ if (info.vpnIface == null) return null;
+ info.underlyingIfaces = interfaces.toArray(new String[0]);
+
+ return info;
}
/**
@@ -4774,22 +4806,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
- * Ask all VPN objects to recompute and update their capabilities.
+ * Ask all networks with underlying networks to recompute and update their capabilities.
*
- * When underlying networks change, VPNs may have to update capabilities to reflect things
- * like the metered bit, their transports, and so on. This asks the VPN objects to update
- * their capabilities, and as this will cause them to send messages to the ConnectivityService
- * handler thread through their agent, this is asynchronous. When the capabilities objects
- * are computed they will be up-to-date as they are computed synchronously from here and
- * this is running on the ConnectivityService thread.
+ * When underlying networks change, such networks may have to update capabilities to reflect
+ * things like the metered bit, their transports, and so on. The capabilities are calculated
+ * immediately. This method runs on the ConnectivityService thread.
*/
- private void updateAllVpnsCapabilities() {
- Network defaultNetwork = getNetwork(getDefaultNetwork());
- synchronized (mVpns) {
- for (int i = 0; i < mVpns.size(); i++) {
- final Vpn vpn = mVpns.valueAt(i);
- NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
- updateVpnCapabilities(vpn, nc);
+ private void propagateUnderlyingNetworkCapabilities() {
+ ensureRunningOnConnectivityServiceThread();
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ if (nai.supportsUnderlyingNetworks()) {
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
}
}
}
@@ -5959,13 +5986,29 @@ public class ConnectivityService extends IConnectivityManager.Stub
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
+ } else {
+ enforceNetworkFactoryPermission();
+ }
+
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
+ networkCapabilities, currentScore, networkAgentConfig, providerId, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private Network registerNetworkAgentInternal(Messenger messenger, NetworkInfo networkInfo,
+ LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
+ int currentScore, NetworkAgentConfig networkAgentConfig, int providerId, int uid) {
+ if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
// Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in
// the call to mixInCapabilities below anyway, but sanitizing here means the NAI never
// sees capabilities that may be malicious, which might prevent mistakes in the future.
networkCapabilities = new NetworkCapabilities(networkCapabilities);
- networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid());
- } else {
- enforceNetworkFactoryPermission();
+ networkCapabilities.restrictCapabilitesForTestNetwork(uid);
}
LinkProperties lp = new LinkProperties(linkProperties);
@@ -5976,9 +6019,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
- this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid());
+ this, mNetd, mDnsResolver, mNMS, providerId, uid);
// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
+ processCapabilitiesFromAgent(nai, nc);
nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
processLinkPropertiesFromAgent(nai, nai.linkProperties);
@@ -5986,13 +6030,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSsid() : extraInfo;
if (DBG) log("registerNetworkAgent " + nai);
- final long token = Binder.clearCallingIdentity();
- try {
- mDeps.getNetworkStack().makeNetworkMonitor(
- nai.network, name, new NetworkMonitorCallbacks(nai));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mDeps.getNetworkStack().makeNetworkMonitor(
+ nai.network, name, new NetworkMonitorCallbacks(nai));
// NetworkAgentInfo registration will finish when the NetworkMonitor is created.
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
@@ -6019,6 +6058,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateUids(nai, null, nai.networkCapabilities);
}
+ /**
+ * Called when receiving LinkProperties directly from a NetworkAgent.
+ * Stores into |nai| any data coming from the agent that might also be written to the network's
+ * LinkProperties by ConnectivityService itself. This ensures that the data provided by the
+ * agent is not lost when updateLinkProperties is called.
+ */
private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
lp.ensureDirectlyConnectedRoutes();
nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix());
@@ -6315,6 +6360,30 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
+ * Called when receiving NetworkCapabilities directly from a NetworkAgent.
+ * Stores into |nai| any data coming from the agent that might also be written to the network's
+ * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the
+ * agent is not lost when updateCapabilities is called.
+ */
+ private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
+ nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
+ }
+
+ /** Propagates to |nc| the capabilities declared by the underlying networks of |nai|. */
+ private void mixInUnderlyingCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
+ Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
+ Network defaultNetwork = getNetwork(getDefaultNetwork());
+ if (underlyingNetworks == null && defaultNetwork != null) {
+ // null underlying networks means to track the default.
+ underlyingNetworks = new Network[] { defaultNetwork };
+ }
+
+ // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ Vpn.applyUnderlyingCapabilities(cm, underlyingNetworks, nc, nai.declaredMetered);
+ }
+
+ /**
* Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
* maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
* and foreground status).
@@ -6367,6 +6436,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
}
+ if (nai.supportsUnderlyingNetworks()) {
+ mixInUnderlyingCapabilities(nai, newNc);
+ }
+
return newNc;
}
@@ -6446,7 +6519,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!newNc.hasTransport(TRANSPORT_VPN)) {
// Tell VPNs about updated capabilities, since they may need to
// bubble those changes through.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
if (!newNc.equalsTransportTypes(prevNc)) {
@@ -6766,7 +6839,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
? newNetwork.linkProperties.getTcpBufferSizes() : null);
notifyIfacesChangedForNetworkStats();
// Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
@@ -7228,7 +7301,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
// the VPN would switch from its default, blank capabilities to those
// that reflect the capabilities of its underlying networks.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
networkAgent.created = true;
}
@@ -7270,8 +7343,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
- if (networkAgent.isVPN()) {
- updateAllVpnsCapabilities();
+ if (networkAgent.supportsUnderlyingNetworks()) {
+ propagateUnderlyingNetworkCapabilities();
}
// Consider network even though it is not yet validated.
@@ -7528,13 +7601,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
throwIfLockdownEnabled();
success = mVpns.get(user).setUnderlyingNetworks(networks);
}
- if (success) {
- mHandler.post(() -> {
- // Update VPN's capabilities based on updated underlying network set.
- updateAllVpnsCapabilities();
- notifyIfacesChangedForNetworkStats();
- });
- }
return success;
}
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 8099f8f37bc7..3d1e709ab3bd 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -7,3 +7,6 @@ per-file VibratorService.java, DisplayThread.java = ogunwale@google.com
# Zram writeback
per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@google.com
+
+# Userspace reboot
+per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com
diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java
index 2403b637581f..89327b50883c 100644
--- a/services/core/java/com/android/server/UserspaceRebootLogger.java
+++ b/services/core/java/com/android/server/UserspaceRebootLogger.java
@@ -59,7 +59,7 @@ public final class UserspaceRebootLogger {
*/
public static void noteUserspaceRebootWasRequested() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "noteUserspaceRebootWasRequested: Userspace reboot is not supported.");
return;
}
@@ -77,7 +77,7 @@ public final class UserspaceRebootLogger {
*/
public static void noteUserspaceRebootSuccess() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "noteUserspaceRebootSuccess: Userspace reboot is not supported.");
return;
}
@@ -88,11 +88,11 @@ public final class UserspaceRebootLogger {
/**
* Returns {@code true} if {@code UserspaceRebootReported} atom should be logged.
*
- * <p>This call should only be made on devices supporting userspace reboot.
+ * <p>On devices that do not support userspace reboot this method will always return {@code
+ * false}.
*/
public static boolean shouldLogUserspaceRebootEvent() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
return false;
}
@@ -110,7 +110,7 @@ public final class UserspaceRebootLogger {
*/
public static void logEventAsync(boolean userUnlocked, Executor executor) {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "logEventAsync: Userspace reboot is not supported.");
return;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index a9f62d91592d..3270dd55218c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -132,6 +132,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// TODO: make this private with a getter.
public NetworkCapabilities networkCapabilities;
public final NetworkAgentConfig networkAgentConfig;
+
+ // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true.
+ // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are
+ // not guaranteed to be current or correct, or even to exist.
+ public @Nullable Network[] declaredUnderlyingNetworks;
+
+ // Whether this network is always metered even if its underlying networks are unmetered.
+ // Only relevant if #supportsUnderlyingNetworks is true.
+ public boolean declaredMetered;
+
// Indicates if netd has been told to create this Network. From this point on the appropriate
// routing rules are setup and routes are added so packets can begin flowing over the Network.
// This is a sticky bit; once set it is never cleared.
@@ -474,10 +484,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
networkCapabilities);
}
+ /** Whether this network is a VPN. */
public boolean isVPN() {
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
+ /** Whether this network might have underlying networks. Currently only true for VPNs. */
+ public boolean supportsUnderlyingNetworks() {
+ return isVPN();
+ }
+
private int getCurrentScore(boolean pretendValidated) {
// TODO: We may want to refactor this into a NetworkScore class that takes a base score from
// the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ff1a9c0ab35f..4f5c13db1231 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -112,7 +112,6 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
-import com.android.server.ConnectivityService;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.net.BaseNetworkObserver;
@@ -1262,6 +1261,15 @@ public class Vpn {
mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID});
mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
+
+ // Only apps targeting Q and above can explicitly declare themselves as metered.
+ // These VPNs are assumed metered unless they state otherwise.
+ if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) {
+ mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_METERED);
+ } else {
+ mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
+ }
+
final long token = Binder.clearCallingIdentity();
try {
mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
@@ -1276,6 +1284,8 @@ public class Vpn {
} finally {
Binder.restoreCallingIdentity(token);
}
+ mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
+ ? Arrays.asList(mConfig.underlyingNetworks) : null);
mNetworkInfo.setIsAvailable(true);
updateState(DetailedState.CONNECTED, "agentConnect");
}
@@ -1857,6 +1867,8 @@ public class Vpn {
}
}
}
+ mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
+ ? Arrays.asList(mConfig.underlyingNetworks) : null);
return true;
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index c63f306ec84f..6dac6b1773c4 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -125,7 +125,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
/** Internal method for handling the auto time setting being changed. */
@VisibleForTesting
public void handleAutoTimeDetectionChanged() {
- mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged);
+ mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged);
}
@Override
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 13f0ab605b3a..abd4c8c63a07 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -16,6 +16,7 @@
package com.android.server.timedetector;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
@@ -24,6 +25,8 @@ import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* The interface for the class that implements the time detection algorithm used by the
@@ -37,22 +40,41 @@ import java.io.PrintWriter;
*/
public interface TimeDetectorStrategy {
- /** Process the suggested time from telephony sources. */
+ @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Origin {}
+
+ /** Used when a time value originated from a telephony signal. */
+ @Origin
+ int ORIGIN_TELEPHONY = 1;
+
+ /** Used when a time value originated from a user / manual settings. */
+ @Origin
+ int ORIGIN_MANUAL = 2;
+
+ /** Used when a time value originated from a network signal. */
+ @Origin
+ int ORIGIN_NETWORK = 3;
+
+ /** Processes the suggested time from telephony sources. */
void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
/**
- * Process the suggested manually entered time. Returns {@code false} if the suggestion was
+ * Processes the suggested manually entered time. Returns {@code false} if the suggestion was
* invalid, or the device configuration prevented the suggestion being used, {@code true} if the
* suggestion was accepted. A suggestion that is valid but does not change the time because it
* matches the current device time is considered accepted.
*/
boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
- /** Process the suggested time from network sources. */
+ /** Processes the suggested time from network sources. */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
- /** Handle the auto-time setting being toggled on or off. */
- void handleAutoTimeDetectionChanged();
+ /**
+ * Handles the auto-time configuration changing For example, when the auto-time setting is
+ * toggled on or off.
+ */
+ void handleAutoTimeConfigChanged();
/** Dump debug information. */
void dump(@NonNull PrintWriter pw, @Nullable String[] args);
@@ -67,4 +89,38 @@ public interface TimeDetectorStrategy {
return (referenceClockMillisNow - timeValue.getReferenceTimeMillis())
+ timeValue.getValue();
}
+
+ /**
+ * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config
+ * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized.
+ */
+ static String originToString(@Origin int origin) {
+ switch (origin) {
+ case ORIGIN_MANUAL:
+ return "manual";
+ case ORIGIN_NETWORK:
+ return "network";
+ case ORIGIN_TELEPHONY:
+ return "telephony";
+ default:
+ throw new IllegalArgumentException("origin=" + origin);
+ }
+ }
+
+ /**
+ * Converts a human readable config string to one of the {@code ORIGIN_} constants.
+ * Throws an {@link IllegalArgumentException} if the value is unrecognized.
+ */
+ static @Origin int stringToOrigin(String originString) {
+ switch (originString) {
+ case "manual":
+ return ORIGIN_MANUAL;
+ case "network":
+ return ORIGIN_NETWORK;
+ case "telephony":
+ return ORIGIN_TELEPHONY;
+ default:
+ throw new IllegalArgumentException("originString=" + originString);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
index 6bd107fffeaa..5b6de0518999 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
@@ -16,6 +16,8 @@
package com.android.server.timedetector;
+import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
+
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.content.ContentResolver;
@@ -58,6 +60,7 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
@NonNull private final ContentResolver mContentResolver;
@NonNull private final PowerManager.WakeLock mWakeLock;
@NonNull private final AlarmManager mAlarmManager;
+ @NonNull private final int[] mOriginPriorities;
public TimeDetectorStrategyCallbackImpl(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
@@ -72,6 +75,15 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
mSystemClockUpdateThresholdMillis =
SystemProperties.getInt("ro.sys.time_detector_update_diff",
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
+
+ // TODO(b/172230856): Obtain these values from configuration.
+ String[] originStrings = { "telephony", "network" };
+ int[] origins = new int[originStrings.length];
+ for (int i = 0; i < originStrings.length; i++) {
+ int origin = stringToOrigin(originStrings[i]);
+ origins[i] = origin;
+ }
+ mOriginPriorities = origins;
}
@Override
@@ -94,6 +106,11 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
}
@Override
+ public int[] getAutoOriginPriorities() {
+ return mOriginPriorities;
+ }
+
+ @Override
public void acquireWakeLock() {
if (mWakeLock.isHeld()) {
Slog.wtf(TAG, "WakeLock " + mWakeLock + " already held");
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index a889bdfe17b6..36a3ddd73d89 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -16,7 +16,8 @@
package com.android.server.timedetector;
-import android.annotation.IntDef;
+import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
@@ -34,9 +35,8 @@ import com.android.server.timezonedetector.ArrayMapWithHistory;
import com.android.server.timezonedetector.ReferenceWithHistory;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
+import java.util.Arrays;
/**
* An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
@@ -64,22 +64,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
static final long MAX_UTC_TIME_AGE_MILLIS =
TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS;
- @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Origin {}
-
- /** Used when a time value originated from a telephony signal. */
- @Origin
- private static final int ORIGIN_TELEPHONY = 1;
-
- /** Used when a time value originated from a user / manual settings. */
- @Origin
- private static final int ORIGIN_MANUAL = 2;
-
- /** Used when a time value originated from a network signal. */
- @Origin
- private static final int ORIGIN_NETWORK = 3;
-
/**
* CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
* actual system clock time before a warning is logged. Used to help identify situations where
@@ -153,6 +137,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@NonNull
Instant autoTimeLowerBound();
+ /**
+ * Returns the order to look at time suggestions when automatically detecting time.
+ * See {@code #ORIGIN_} constants
+ */
+ @Origin int[] getAutoOriginPriorities();
+
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
void acquireWakeLock();
@@ -237,12 +227,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@Override
- public synchronized void handleAutoTimeDetectionChanged() {
+ public synchronized void handleAutoTimeConfigChanged() {
boolean enabled = mCallback.isAutoTimeDetectionEnabled();
// When automatic time detection is enabled we update the system clock instantly if we can.
// Conversely, when automatic time detection is disabled we leave the clock as it is.
if (enabled) {
- String reason = "Auto time zone detection setting enabled.";
+ String reason = "Auto time zone detection config changed.";
doAutoTimeDetection(reason);
} else {
// CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
@@ -365,33 +355,44 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return;
}
- // Android devices currently prioritize any telephony over network signals. There are
- // carrier compliance tests that would need to be changed before we could ignore NITZ or
- // prefer NTP generally. This check is cheap on devices without telephony hardware.
- TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
- if (bestTelephonySuggestion != null) {
- final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime();
- String cause = "Found good telephony suggestion."
- + ", bestTelephonySuggestion=" + bestTelephonySuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause);
- return;
- }
+ // Try the different origins one at a time.
+ int[] originPriorities = mCallback.getAutoOriginPriorities();
+ for (int origin : originPriorities) {
+ TimestampedValue<Long> newUtcTime = null;
+ String cause = null;
+ if (origin == ORIGIN_TELEPHONY) {
+ TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
+ if (bestTelephonySuggestion != null) {
+ newUtcTime = bestTelephonySuggestion.getUtcTime();
+ cause = "Found good telephony suggestion."
+ + ", bestTelephonySuggestion=" + bestTelephonySuggestion
+ + ", detectionReason=" + detectionReason;
+ }
+ } else if (origin == ORIGIN_NETWORK) {
+ NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
+ if (networkSuggestion != null) {
+ newUtcTime = networkSuggestion.getUtcTime();
+ cause = "Found good network suggestion."
+ + ", networkSuggestion=" + networkSuggestion
+ + ", detectionReason=" + detectionReason;
+ }
+ } else {
+ Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin
+ + " in " + Arrays.toString(originPriorities)
+ + ": Skipping");
+ }
- // There is no good telephony suggestion, try network.
- NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
- if (networkSuggestion != null) {
- final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
- String cause = "Found good network suggestion."
- + ", networkSuggestion=" + networkSuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause);
- return;
+ // Update the system clock if a good suggestion has been found.
+ if (newUtcTime != null) {
+ setSystemClockIfRequired(origin, newUtcTime, cause);
+ return;
+ }
}
if (DBG) {
- Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion."
- + " detectionReason=" + detectionReason);
+ Slog.d(LOG_TAG, "Could not determine time: No suggestion found in"
+ + " originPriorities=" + Arrays.toString(originPriorities)
+ + ", detectionReason=" + detectionReason);
}
}
@@ -476,7 +477,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
// Validate first.
TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) {
- Slog.w(LOG_TAG, "Existing suggestion found to be invalid "
+ Slog.w(LOG_TAG, "Existing suggestion found to be invalid"
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
return TELEPHONY_INVALID_SCORE;
@@ -525,7 +526,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
if (!mCallback.isAutoTimeDetectionEnabled()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is not enabled."
- + " origin=" + origin
+ + " origin=" + originToString(origin)
+ ", time=" + time
+ ", cause=" + cause);
}
@@ -535,7 +536,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
if (mCallback.isAutoTimeDetectionEnabled()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is enabled."
- + " origin=" + origin
+ + " origin=" + originToString(origin)
+ ", time=" + time
+ ", cause=" + cause);
}
@@ -557,7 +558,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@GuardedBy("this")
private boolean setSystemClockUnderWakeLock(
- int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) {
+ @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) {
long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
boolean isOriginAutomatic = isOriginAutomatic(origin);
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 02031bc4f210..22addf948a53 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -242,7 +242,7 @@ public class TimeDetectorServiceTest {
}
@Override
- public void handleAutoTimeDetectionChanged() {
+ public void handleAutoTimeConfigChanged() {
mHandleAutoTimeDetectionChangedCalled = true;
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 217de55fb400..c23fb8028224 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -16,6 +16,9 @@
package com.android.server.timedetector;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -29,6 +32,8 @@ import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.timedetector.TimeDetectorStrategy.Origin;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,6 +53,9 @@ public class TimeDetectorStrategyImplTest {
123456789L /* realtimeClockMillis */,
createUtcTime(2010, 5, 23, 12, 0, 0));
+ // This is the traditional ordering for time detection on Android.
+ private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
+
/**
* An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO}
* time. Can be used as the basis for time suggestions.
@@ -488,11 +496,8 @@ public class TimeDetectorStrategyImplTest {
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
}
- /**
- * Manual suggestions should be ignored if auto time is enabled.
- */
@Test
- public void testSuggestManualTime_autoTimeEnabled() {
+ public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
@@ -505,7 +510,7 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void suggestManualTime_ignoresTimeLowerBound() {
+ public void manualTimeSuggestion_ignoresTimeLowerBound() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(false);
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
@@ -658,6 +663,73 @@ public class TimeDetectorStrategyImplTest {
.assertLatestNetworkSuggestion(null);
}
+ @Test
+ public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant networkTime = ARBITRARY_TEST_TIME;
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+
+ NetworkTimeSuggestion networkTimeSuggestion =
+ mScript.generateNetworkTimeSuggestion(networkTime);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+
+ mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
+ }
+
+ @Test
+ public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant networkTime = ARBITRARY_TEST_TIME;
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+
+ NetworkTimeSuggestion networkTimeSuggestion =
+ mScript.generateNetworkTimeSuggestion(networkTime);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+
+ mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
+ }
+
+ @Test
+ public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
+
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
+ }
+
+ @Test
+ public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(new int[]{ORIGIN_TELEPHONY});
+
+ NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion(
+ ARBITRARY_TEST_TIME);
+
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
/**
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
* like the real thing should, it also asserts preconditions.
@@ -668,6 +740,7 @@ public class TimeDetectorStrategyImplTest {
private long mElapsedRealtimeMillis;
private long mSystemClockMillis;
private int mSystemClockUpdateThresholdMillis = 2000;
+ private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
// Tracking operations.
private boolean mSystemClockWasSet;
@@ -688,6 +761,11 @@ public class TimeDetectorStrategyImplTest {
}
@Override
+ public int[] getAutoOriginPriorities() {
+ return mAutoOriginPriorities;
+ }
+
+ @Override
public void acquireWakeLock() {
if (mWakeLockAcquired) {
fail("Wake lock already acquired");
@@ -736,6 +814,10 @@ public class TimeDetectorStrategyImplTest {
mAutoTimeDetectionEnabled = enabled;
}
+ void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) {
+ mAutoOriginPriorities = autoOriginPriorities;
+ }
+
long peekElapsedRealtimeMillis() {
return mElapsedRealtimeMillis;
}
@@ -804,6 +886,11 @@ public class TimeDetectorStrategyImplTest {
return this;
}
+ Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) {
+ mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeCallback.peekElapsedRealtimeMillis();
}
@@ -836,7 +923,7 @@ public class TimeDetectorStrategyImplTest {
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
- mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
+ mTimeDetectorStrategy.handleAutoTimeConfigChanged();
return this;
}
@@ -870,7 +957,7 @@ public class TimeDetectorStrategyImplTest {
Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) {
assertEquals(
"Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got "
- + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex),
+ + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex),
expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex));
return this;
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 99f1985ff691..561c6bab9c6d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1084,7 +1084,7 @@ public class ConnectivityServiceTest {
throws Exception {
if (mAgentRegistered) throw new IllegalStateException("already registered");
setUids(uids);
- mConfig.isMetered = isAlwaysMetered;
+ if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities);
@@ -5053,6 +5053,13 @@ public class ConnectivityServiceTest {
waitForIdle();
expectForceUpdateIfaces(wifiAndVpn, null);
reset(mStatsService);
+
+ // Passing in null again means follow the default network again.
+ mService.setUnderlyingNetworksForVpn(null);
+ waitForIdle();
+ expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{WIFI_IFNAME});
+ reset(mStatsService);
}
@Test