summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java425
-rw-r--r--core/java/com/android/internal/compat/ChangeReporter.java4
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreProvider.java3
-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/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.java32
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java145
-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.java286
11 files changed, 675 insertions, 303 deletions
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/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index 5e886a611913..60a30a0faf61 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -221,7 +221,7 @@ public final class ChangeReporter {
FrameworkStatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER;
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "STATE_" }, value = {
+ @IntDef(prefix = { "STATE_" }, value = {
STATE_UNKNOWN_STATE,
STATE_ENABLED,
STATE_DISABLED,
@@ -231,7 +231,7 @@ public final class ChangeReporter {
}
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "SOURCE_" }, value = {
+ @IntDef(prefix = { "SOURCE_" }, value = {
SOURCE_UNKNOWN_SOURCE,
SOURCE_APP_PROCESS,
SOURCE_SYSTEM_SERVER
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/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/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 e06fe9276323..5b6de0518999 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
@@ -16,16 +16,21 @@
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;
import android.content.Context;
+import android.os.Build;
+import android.os.Environment;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Slog;
+import java.time.Instant;
import java.util.Objects;
/**
@@ -38,6 +43,13 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
/**
+ * Time in the past. If automatic time suggestion is before this point, it's
+ * incorrect for sure.
+ */
+ private static final Instant TIME_LOWER_BOUND = Instant.ofEpochMilli(
+ Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
+
+ /**
* If a newly calculated system clock time and the current system clock time differs by this or
* more the system clock will actually be updated. Used to prevent the system clock being set
* for only minor differences.
@@ -48,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);
@@ -62,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
@@ -79,6 +101,16 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
}
@Override
+ public Instant autoTimeLowerBound() {
+ return TIME_LOWER_BOUND;
+ }
+
+ @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 d447a785f3bb..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,8 +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
@@ -63,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
@@ -143,6 +128,21 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
/** Returns true if automatic time detection is enabled. */
boolean isAutoTimeDetectionEnabled();
+ /**
+ * Returns a lower bound for valid automatic times. It is guaranteed to be in the past,
+ * i.e. it is unrelated to the current system clock time.
+ * It holds no other meaning; it could be related to when the device system image was built,
+ * or could be updated by a mainline module.
+ */
+ @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();
@@ -177,7 +177,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@Override
public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) {
- if (!validateSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
return;
}
@@ -211,9 +211,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return;
}
- // Perform validation / input filtering and record the validated suggestion against the
- // slotIndex.
- if (!validateAndStoreTelephonySuggestion(timeSuggestion)) {
+ if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ return;
+ }
+
+ // Perform input filtering and record the validated suggestion against the slotIndex.
+ if (!storeTelephonySuggestion(timeSuggestion)) {
return;
}
@@ -224,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
@@ -272,14 +275,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@GuardedBy("this")
- private boolean validateAndStoreTelephonySuggestion(
+ private boolean storeTelephonySuggestion(
@NonNull TelephonyTimeSuggestion suggestion) {
TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
- if (!validateSuggestionTime(newUtcTime, suggestion)) {
- // There's probably nothing useful we can do: elsewhere we assume that reference
- // times are in the past so just stop here.
- return false;
- }
int slotIndex = suggestion.getSlotIndex();
TelephonyTimeSuggestion previousSuggestion = mSuggestionBySlotIndex.get(slotIndex);
@@ -330,6 +328,26 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return true;
}
+ private boolean validateAutoSuggestionTime(
+ @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
+ return validateSuggestionTime(newUtcTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUtcTime, suggestion);
+ }
+
+ private boolean validateSuggestionAgainstLowerBound(
+ @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
+ Instant lowerBound = mCallback.autoTimeLowerBound();
+
+ // Suggestion is definitely wrong if it comes before lower time bound.
+ if (lowerBound.isAfter(Instant.ofEpochMilli(newUtcTime.getValue()))) {
+ Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. "
+ + "suggestion=" + suggestion + ", lower bound=" + lowerBound);
+ return false;
+ }
+
+ return true;
+ }
+
@GuardedBy("this")
private void doAutoTimeDetection(@NonNull String detectionReason) {
if (!mCallback.isAutoTimeDetectionEnabled()) {
@@ -337,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);
}
}
@@ -448,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;
@@ -497,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);
}
@@ -507,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);
}
@@ -529,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 1be074dfa5a3..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;
@@ -25,32 +28,39 @@ import static org.junit.Assert.fail;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
-import android.icu.util.Calendar;
-import android.icu.util.GregorianCalendar;
-import android.icu.util.TimeZone;
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;
import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
@RunWith(AndroidJUnit4.class)
public class TimeDetectorStrategyImplTest {
- private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO =
+ private static final Instant TIME_LOWER_BOUND = createUtcTime(2009, 1, 1, 12, 0, 0);
+
+ private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
123456789L /* realtimeClockMillis */,
- createUtcTime(2008, 5, 23, 12, 0, 0));
+ 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.
*/
- private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0);
+ private static final Instant ARBITRARY_TEST_TIME = createUtcTime(2018, 1, 1, 12, 0, 0);
private static final int ARBITRARY_SLOT_INDEX = 123456;
@@ -67,10 +77,10 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(true);
int slotIndex = ARBITRARY_SLOT_INDEX;
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
mScript.simulateTimePassing()
.simulateTelephonyTimeSuggestion(timeSuggestion);
@@ -106,9 +116,9 @@ public class TimeDetectorStrategyImplTest {
// Send the first time signal. It should be used.
{
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
- // Increment the the device clocks to simulate the passage of time.
+ // Increment the device clocks to simulate the passage of time.
mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis1 =
@@ -157,13 +167,13 @@ public class TimeDetectorStrategyImplTest {
// uses the lowest slotIndex when multiple telephony suggestions are available.
int slotIndex1 = ARBITRARY_SLOT_INDEX;
int slotIndex2 = ARBITRARY_SLOT_INDEX + 1;
- long slotIndex1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- long slotIndex2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis();
+ Instant slotIndex1Time = ARBITRARY_TEST_TIME;
+ Instant slotIndex2Time = ARBITRARY_TEST_TIME.plus(Duration.ofDays(1));
// Make a suggestion with slotIndex2.
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
@@ -180,7 +190,7 @@ public class TimeDetectorStrategyImplTest {
// Now make a different suggestion with slotIndex1.
{
TelephonyTimeSuggestion slotIndex1TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1TimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
@@ -198,7 +208,7 @@ public class TimeDetectorStrategyImplTest {
// slotIndex1 suggestion will still "win".
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
mScript.simulateTimePassing();
mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
@@ -213,7 +223,7 @@ public class TimeDetectorStrategyImplTest {
// is in an older "bucket".
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
@@ -232,7 +242,7 @@ public class TimeDetectorStrategyImplTest {
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
mScript.simulateTimePassing()
.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
@@ -246,11 +256,11 @@ public class TimeDetectorStrategyImplTest {
.pokeThresholds(systemClockUpdateThreshold)
.pokeAutoTimeDetectionEnabled(true);
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ Instant testTime = ARBITRARY_TEST_TIME;
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
// Initialize the strategy / device with a time set from a telephony suggestion.
@@ -300,6 +310,23 @@ public class TimeDetectorStrategyImplTest {
}
@Test
+ public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+ Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(
+ slotIndex, suggestedTime);
+
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestTelephonySuggestion(slotIndex, null);
+ }
+
+ @Test
public void testSuggestTelephonyTime_timeDetectionToggled() {
final int clockIncrementMillis = 100;
final int systemClockUpdateThreshold = 2000;
@@ -308,9 +335,9 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(false);
int slotIndex = ARBITRARY_SLOT_INDEX;
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
// Simulate time passing.
@@ -366,9 +393,9 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(true);
int slotIndex = ARBITRARY_SLOT_INDEX;
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion telephonySuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
mScript.simulateTimePassing();
@@ -397,7 +424,7 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(false);
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
mScript.simulateTimePassing();
@@ -416,9 +443,9 @@ public class TimeDetectorStrategyImplTest {
int slotIndex = ARBITRARY_SLOT_INDEX;
// Simulate a telephony suggestion.
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
// Simulate the passage of time.
mScript.simulateTimePassing();
@@ -441,9 +468,9 @@ public class TimeDetectorStrategyImplTest {
mScript.simulateTimePassing();
// Simulate a manual suggestion 1 day different from the auto suggestion.
- long manualTimeMillis = testTimeMillis + Duration.ofDays(1).toMillis();
+ Instant manualTime = testTime.plus(Duration.ofDays(1));
ManualTimeSuggestion manualTimeSuggestion =
- mScript.generateManualTimeSuggestion(manualTimeMillis);
+ mScript.generateManualTimeSuggestion(manualTime);
mScript.simulateTimePassing();
long expectedManualClockMillis =
@@ -469,16 +496,13 @@ 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);
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
mScript.simulateTimePassing()
.simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */)
@@ -486,12 +510,25 @@ public class TimeDetectorStrategyImplTest {
}
@Test
+ public void manualTimeSuggestion_ignoresTimeLowerBound() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false);
+ Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+
+ ManualTimeSuggestion timeSuggestion =
+ mScript.generateManualTimeSuggestion(suggestedTime);
+
+ mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
+ .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli());
+ }
+
+ @Test
public void testSuggestNetworkTime_autoTimeEnabled() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
NetworkTimeSuggestion timeSuggestion =
- mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
mScript.simulateTimePassing();
@@ -507,7 +544,7 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(false);
NetworkTimeSuggestion timeSuggestion =
- mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
mScript.simulateTimePassing()
.simulateNetworkTimeSuggestion(timeSuggestion)
@@ -520,16 +557,16 @@ public class TimeDetectorStrategyImplTest {
.pokeAutoTimeDetectionEnabled(true);
// Three obviously different times that could not be mistaken for each other.
- long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS;
- long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis();
- long telephonyTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis();
+ Instant networkTime1 = ARBITRARY_TEST_TIME;
+ Instant networkTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
// A small increment used to simulate the passage of time, but not enough to interfere with
// macro-level time changes associated with suggestion age.
final long smallTimeIncrementMillis = 101;
// A network suggestion is made. It should be used because there is no telephony suggestion.
NetworkTimeSuggestion networkTimeSuggestion1 =
- mScript.generateNetworkTimeSuggestion(networkTimeMillis1);
+ mScript.generateNetworkTimeSuggestion(networkTime1);
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
@@ -548,7 +585,7 @@ public class TimeDetectorStrategyImplTest {
// Now a telephony suggestion is made. Telephony suggestions are prioritized over network
// suggestions so it should "win".
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeMillis);
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
@@ -568,7 +605,7 @@ public class TimeDetectorStrategyImplTest {
// Now another network suggestion is made. Telephony suggestions are prioritized over
// network suggestions so the latest telephony suggestion should still "win".
NetworkTimeSuggestion networkTimeSuggestion2 =
- mScript.generateNetworkTimeSuggestion(networkTimeMillis2);
+ mScript.generateNetworkTimeSuggestion(networkTime2);
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking();
@@ -612,6 +649,87 @@ public class TimeDetectorStrategyImplTest {
assertNull(mScript.peekBestTelephonySuggestion());
}
+ @Test
+ public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ NetworkTimeSuggestion timeSuggestion = mScript
+ .generateNetworkTimeSuggestion(suggestedTime);
+
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .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.
@@ -622,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;
@@ -637,6 +756,16 @@ public class TimeDetectorStrategyImplTest {
}
@Override
+ public Instant autoTimeLowerBound() {
+ return TIME_LOWER_BOUND;
+ }
+
+ @Override
+ public int[] getAutoOriginPriorities() {
+ return mAutoOriginPriorities;
+ }
+
+ @Override
public void acquireWakeLock() {
if (mWakeLockAcquired) {
fail("Wake lock already acquired");
@@ -685,6 +814,10 @@ public class TimeDetectorStrategyImplTest {
mAutoTimeDetectionEnabled = enabled;
}
+ void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) {
+ mAutoOriginPriorities = autoOriginPriorities;
+ }
+
long peekElapsedRealtimeMillis() {
return mElapsedRealtimeMillis;
}
@@ -703,7 +836,10 @@ public class TimeDetectorStrategyImplTest {
}
void verifySystemClockNotSet() {
- assertFalse(mSystemClockWasSet);
+ assertFalse(
+ String.format("System clock was manipulated and set to %s(=%s)",
+ Instant.ofEpochMilli(mSystemClockMillis), mSystemClockMillis),
+ mSystemClockWasSet);
}
void verifySystemClockWasSet(long expectedSystemClockMillis) {
@@ -739,9 +875,9 @@ public class TimeDetectorStrategyImplTest {
return this;
}
- Script pokeFakeClocks(TimestampedValue<Long> timeInfo) {
+ Script pokeFakeClocks(TimestampedValue<Instant> timeInfo) {
mFakeCallback.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
- mFakeCallback.pokeSystemClockMillis(timeInfo.getValue());
+ mFakeCallback.pokeSystemClockMillis(timeInfo.getValue().toEpochMilli());
return this;
}
@@ -750,6 +886,11 @@ public class TimeDetectorStrategyImplTest {
return this;
}
+ Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) {
+ mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeCallback.peekElapsedRealtimeMillis();
}
@@ -765,7 +906,13 @@ public class TimeDetectorStrategyImplTest {
Script simulateManualTimeSuggestion(
ManualTimeSuggestion timeSuggestion, boolean expectedResult) {
- assertEquals(expectedResult, mTimeDetectorStrategy.suggestManualTime(timeSuggestion));
+ String errorMessage = expectedResult
+ ? "Manual time suggestion was ignored, but expected to be accepted."
+ : "Manual time suggestion was accepted, but expected to be ignored.";
+ assertEquals(
+ errorMessage,
+ expectedResult,
+ mTimeDetectorStrategy.suggestManualTime(timeSuggestion));
return this;
}
@@ -776,7 +923,7 @@ public class TimeDetectorStrategyImplTest {
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
- mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
+ mTimeDetectorStrategy.handleAutoTimeConfigChanged();
return this;
}
@@ -808,7 +955,10 @@ public class TimeDetectorStrategyImplTest {
* White box test info: Asserts the latest suggestion for the slotIndex is as expected.
*/
Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) {
- assertEquals(expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex));
+ assertEquals(
+ "Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got "
+ + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex),
+ expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex));
return this;
}
@@ -840,9 +990,11 @@ public class TimeDetectorStrategyImplTest {
* Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
* reference time.
*/
- ManualTimeSuggestion generateManualTimeSuggestion(long timeMillis) {
+ ManualTimeSuggestion generateManualTimeSuggestion(Instant suggestedTime) {
TimestampedValue<Long> utcTime =
- new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+ new TimestampedValue<>(
+ mFakeCallback.peekElapsedRealtimeMillis(),
+ suggestedTime.toEpochMilli());
return new ManualTimeSuggestion(utcTime);
}
@@ -850,21 +1002,33 @@ public class TimeDetectorStrategyImplTest {
* Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for
* the reference time.
*/
- TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, Long timeMillis) {
- TimestampedValue<Long> time = null;
- if (timeMillis != null) {
- time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis);
- }
+ TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, long timeMillis) {
+ TimestampedValue<Long> time =
+ new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis);
return createTelephonyTimeSuggestion(slotIndex, time);
}
/**
+ * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for
+ * the reference time.
+ */
+ TelephonyTimeSuggestion generateTelephonyTimeSuggestion(
+ int slotIndex, Instant suggestedTime) {
+ if (suggestedTime == null) {
+ return createTelephonyTimeSuggestion(slotIndex, null);
+ }
+ return generateTelephonyTimeSuggestion(slotIndex, suggestedTime.toEpochMilli());
+ }
+
+ /**
* Generates a NetworkTimeSuggestion using the current elapsed realtime clock for the
* reference time.
*/
- NetworkTimeSuggestion generateNetworkTimeSuggestion(long timeMillis) {
+ NetworkTimeSuggestion generateNetworkTimeSuggestion(Instant suggestedTime) {
TimestampedValue<Long> utcTime =
- new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+ new TimestampedValue<>(
+ mFakeCallback.peekElapsedRealtimeMillis(),
+ suggestedTime.toEpochMilli());
return new NetworkTimeSuggestion(utcTime);
}
@@ -884,11 +1048,9 @@ public class TimeDetectorStrategyImplTest {
.build();
}
- private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
- int second) {
- Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
- cal.clear();
- cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
- return cal.getTimeInMillis();
+ private static Instant createUtcTime(int year, int monthInYear, int day, int hourOfDay,
+ int minute, int second) {
+ return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second)
+ .toInstant(ZoneOffset.UTC);
}
}