Merge "Prepare for keeping concrete overrides of abstract methods" into main
diff --git a/Android.mk b/Android.mk
index d9e202c..e2c1ed8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -69,9 +69,6 @@
.PHONY: framework-doc-stubs
framework-doc-stubs: $(SDK_METADATA)
-# Run this for checkbuild
-checkbuild: doc-comment-check-docs
-
# Include subdirectory makefiles
# ============================================================
diff --git a/OWNERS b/OWNERS
index 4e5c7d8..023bdef 100644
--- a/OWNERS
+++ b/OWNERS
@@ -34,3 +34,6 @@
per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS
per-file SQLITE_OWNERS = file:/SQLITE_OWNERS
+
+per-file *ravenwood* = file:ravenwood/OWNERS
+per-file *Ravenwood* = file:ravenwood/OWNERS
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index 6461c00..30b4423 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -20,41 +20,6 @@
// The API doc generation is done by the various droiddoc modules each of which
// is for different format.
-/////////////////////////////////////////////////////////////////////
-// stub source files are generated using metalava
-/////////////////////////////////////////////////////////////////////
-
-framework_docs_only_libs = [
- "voip-common",
- "android.test.mock",
- "android-support-annotations",
- "android-support-compat",
- "android-support-core-ui",
- "android-support-core-utils",
- "android-support-design",
- "android-support-dynamic-animation",
- "android-support-exifinterface",
- "android-support-fragment",
- "android-support-media-compat",
- "android-support-percent",
- "android-support-transition",
- "android-support-v7-cardview",
- "android-support-v7-gridlayout",
- "android-support-v7-mediarouter",
- "android-support-v7-palette",
- "android-support-v7-preference",
- "android-support-v13",
- "android-support-v14-preference",
- "android-support-v17-leanback",
- "android-support-vectordrawable",
- "android-support-animatedvectordrawable",
- "android-support-v7-appcompat",
- "android-support-v7-recyclerview",
- "android-support-v8-renderscript",
- "android-support-multidex",
- "android-support-multidex-instrumentation",
-]
-
// These defaults enable doc-stub generation, api lint database generation and sdk value generation.
stubs_defaults {
name: "android-non-updatable-doc-stubs-defaults",
@@ -65,7 +30,6 @@
":android-test-mock-sources",
":android-test-runner-sources",
],
- libs: framework_docs_only_libs,
create_doc_stubs: true,
write_sdk_values: true,
}
@@ -195,7 +159,9 @@
doc_defaults {
name: "framework-docs-default",
- libs: framework_docs_only_libs + [
+ sdk_version: "none",
+ system_modules: "none",
+ libs: [
"stub-annotations",
"unsupportedappusage",
],
@@ -234,20 +200,6 @@
},
}
-doc_defaults {
- name: "framework-dokka-docs-default",
-}
-
-droiddoc {
- name: "doc-comment-check-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- args: framework_docs_only_args + " -referenceonly -parsecomments",
- installable: false,
-}
-
droiddoc {
name: "offline-sdk-docs",
defaults: ["framework-docs-default"],
@@ -301,70 +253,6 @@
}
droiddoc {
- name: "online-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-docs-proofread.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "online-system-api-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-system-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-system-api-sdk-docs-proofread.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including system APIs.\" " +
- " -hide 101 " +
- " -hide 104 " +
- " -hide 108 " +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
- installable: false,
-}
-
-droiddoc {
name: "ds-docs-java",
defaults: ["framework-docs-default"],
srcs: [
@@ -395,7 +283,6 @@
droiddoc {
name: "ds-docs-kt",
- defaults: ["framework-dokka-docs-default"],
srcs: [
":framework-doc-stubs",
],
@@ -474,44 +361,3 @@
" -atLinksNavtree " +
" -navtreeonly ",
}
-
-droiddoc {
- name: "online-sdk-dev-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-dev-docs-proofread.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "hidden-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- proofread_file: "hidden-docs-proofread.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including hidden APIs.\"",
-}
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 1812c2b..fd4e3df 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6634,12 +6634,6 @@
android.security.attestationverification.AttestationVerificationManager
android.security.keymaster.ExportResult$1
android.security.keymaster.ExportResult
-android.security.keymaster.IKeyAttestationApplicationIdProvider$Stub
-android.security.keymaster.IKeyAttestationApplicationIdProvider
-android.security.keymaster.KeyAttestationApplicationId$1
-android.security.keymaster.KeyAttestationApplicationId
-android.security.keymaster.KeyAttestationPackageInfo$1
-android.security.keymaster.KeyAttestationPackageInfo
android.security.keymaster.KeyCharacteristics$1
android.security.keymaster.KeyCharacteristics
android.security.keymaster.KeymasterArgument$1
@@ -6664,7 +6658,13 @@
android.security.keystore.BackendBusyException
android.security.keystore.DelegatingX509Certificate
android.security.keystore.DeviceIdAttestationException
+android.security.keystore.IKeyAttestationApplicationIdProvider$Stub
+android.security.keystore.IKeyAttestationApplicationIdProvider
+android.security.keystore.KeyAttestationApplicationId$Stub
+android.security.keystore.KeyAttestationApplicationId
android.security.keystore.KeyAttestationException
+android.security.keystore.KeyAttestationPackageInfo$Stub
+android.security.keystore.KeyAttestationPackageInfo
android.security.keystore.KeyExpiredException
android.security.keystore.KeyGenParameterSpec$Builder
android.security.keystore.KeyGenParameterSpec
@@ -6687,6 +6687,8 @@
android.security.keystore.KeystoreResponse
android.security.keystore.ParcelableKeyGenParameterSpec$1
android.security.keystore.ParcelableKeyGenParameterSpec
+android.security.keystore.Signature$Stub
+android.security.keystore.Signature
android.security.keystore.SecureKeyImportUnavailableException
android.security.keystore.StrongBoxUnavailableException
android.security.keystore.UserAuthArgs
diff --git a/core/api/current.txt b/core/api/current.txt
index 365df4d..e8988dc 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29086,6 +29086,8 @@
method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
method public boolean isEnabled();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
@@ -32495,6 +32497,7 @@
field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2
field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5
+ field @FlaggedApi("android.os.state_of_health_public") public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa
field public static final int BATTERY_PROPERTY_STATUS = 6; // 0x6
field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 160a627..40eee4c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10218,6 +10218,7 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
@@ -10317,7 +10318,6 @@
field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9; // 0x9
field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8; // 0x8
field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7; // 0x7
- field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa
field public static final int CHARGING_POLICY_ADAPTIVE_AC = 3; // 0x3
field public static final int CHARGING_POLICY_ADAPTIVE_AON = 2; // 0x2
field public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE = 4; // 0x4
@@ -10385,8 +10385,8 @@
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanResults(@NonNull android.os.WorkSource, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStarted(@NonNull android.os.WorkSource, boolean);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStopped(@NonNull android.os.WorkSource, boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int, int, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int, int, @NonNull String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int, int, @NonNull String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int, int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 5091b52..70864d5 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -23,11 +23,6 @@
visibility: ["//frameworks/base"],
}
-filegroup {
- name: "IKeyAttestationApplicationIdProvider.aidl",
- srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
-}
-
aidl_library {
name: "IDropBoxManagerService_aidl",
srcs: [
diff --git a/core/java/android/content/pm/Signature.aidl b/core/java/android/content/pm/Signature.aidl
deleted file mode 100644
index 36c127a..0000000
--- a/core/java/android/content/pm/Signature.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-/* For the key attestation application id provider service we needed a native implementation
- * of the Signature parcelable because the service is used by the native keystore.
- * The native implementation is now located at
- * system/security/keystore/Signature.cpp
- * and
- * system/security/keystore/include/keystore/Signature.h.
- * and can be used by linking against libkeystore_binder.
- *
- * This is not the best arrangement. If you, dear reader, happen to implement native implementations
- * for the package manager's parcelables, consider moving Signature.cpp/.h to your library and
- * adjust keystore's dependencies accordingly. Thank you.
- */
-parcelable Signature cpp_header "keystore/Signature.h";
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 151f819..6ac1efb 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -114,8 +114,8 @@
}
/**
- * Get {@link PresentationSession} object.
- * @return {@link PresentationSession} object or null if this doesn't contain one.
+ * Get {@link KeyAgreement} object.
+ * @return {@link KeyAgreement} object or null if this doesn't contain one.
*/
@FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
public KeyAgreement getKeyAgreement() {
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index a6d8caf..0c95c2e 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -79,4 +79,9 @@
Map getTagIntentAppPreferenceForUser(int userId);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
int setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow);
+
+ boolean isReaderOptionEnabled();
+ boolean isReaderOptionSupported();
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ boolean enableReaderOption(boolean enable);
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 1307dfc..4658630 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -17,6 +17,7 @@
package android.nfc;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1826,6 +1827,97 @@
}
/**
+ * Sets NFC Reader option feature.
+ * <p>This API is for the Settings application.
+ * @return True if successful
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public boolean enableReaderOption(boolean enable) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.enableReaderOption(enable);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.enableReaderOption(enable);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the device supports NFC Reader option functionality.
+ *
+ * @return True if device supports NFC Reader option, false otherwise
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
+ public boolean isReaderOptionSupported() {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.isReaderOptionSupported();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.isReaderOptionSupported();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Checks NFC Reader option feature is enabled.
+ *
+ * @return True if NFC Reader option is enabled, false otherwise
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if device doesn't support
+ * NFC Reader option functionality. {@link #isReaderOptionSupported}
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
+ public boolean isReaderOptionEnabled() {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.isReaderOptionEnabled();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.isReaderOptionEnabled();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
+
+ /**
* Enable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index e3faf39..55b0b42 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -6,3 +6,10 @@
description: "Flag for NFC mainline changes"
bug: "292140387"
}
+
+flag {
+ name: "enable_nfc_reader_option"
+ namespace: "nfc"
+ description: "Flag for NFC reader option API changes"
+ bug: "291187960"
+}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 092923e..6a4ec9b 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,7 +16,10 @@
package android.os;
+import static android.os.Flags.FLAG_STATE_OF_HEALTH_PUBLIC;
+
import android.Manifest.permission;
+import android.annotation.FlaggedApi;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -354,17 +357,11 @@
public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9;
/**
- *
- * Percentage representing the measured battery state of health (remaining
- * estimated full charge capacity relative to the rated capacity in %).
- *
- * <p class="note">
- * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
- *
- * @hide
+ * Percentage representing the measured battery state of health.
+ * This is the remaining estimated full charge capacity relative
+ * to the rated capacity in %.
*/
- @RequiresPermission(permission.BATTERY_STATS)
- @SystemApi
+ @FlaggedApi(FLAG_STATE_OF_HEALTH_PUBLIC)
public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10;
private final Context mContext;
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 955fad3..3abe9a0 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -520,8 +520,9 @@
* @param uid calling package uid
* @param reason why Bluetooth has been turned on
* @param packageName package responsible for this change
- * @Deprecated Bluetooth self report its state and no longer call this
+ * @deprecated Bluetooth self report its state and no longer call this
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void reportBluetoothOn(int uid, int reason, @NonNull String packageName) {
}
@@ -532,8 +533,9 @@
* @param uid calling package uid
* @param reason why Bluetooth has been turned on
* @param packageName package responsible for this change
- * @Deprecated Bluetooth self report its state and no longer call this
+ * @deprecated Bluetooth self report its state and no longer call this
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void reportBluetoothOff(int uid, int reason, @NonNull String packageName) {
}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index 851aa6d..77229c4 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -1,6 +1,13 @@
package: "android.os"
flag {
+ name: "state_of_health_public"
+ namespace: "system_sw_battery"
+ description: "Feature flag for making state_of_health a public api."
+ bug: "288842045"
+}
+
+flag {
name: "disallow_cellular_null_ciphers_restriction"
namespace: "cellular_security"
description: "Guards a new UserManager user restriction that admins can use to require cellular encryption on their managed devices."
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index baeb1aa..9cdb9ce 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10442,20 +10442,6 @@
"assist_long_press_home_enabled";
/**
- * Control whether Trust Agents are in active unlock or extend unlock mode.
- * @hide
- */
- @Readable
- public static final String TRUST_AGENTS_EXTEND_UNLOCK = "trust_agents_extend_unlock";
-
- /**
- * Control whether the screen locks when trust is lost.
- * @hide
- */
- @Readable
- public static final String LOCK_SCREEN_WHEN_TRUST_LOST = "lock_screen_when_trust_lost";
-
- /**
* Control whether Night display is currently activated.
* @hide
*/
diff --git a/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl b/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl
deleted file mode 100644
index dbffd5f..0000000
--- a/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-import android.security.keymaster.KeyAttestationApplicationId;
-import android.security.keymaster.KeyAttestationPackageInfo;
-import android.content.pm.Signature;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-interface IKeyAttestationApplicationIdProvider {
- /* keep in sync with /system/security/keystore/keystore_attestation_id.cpp */
- KeyAttestationApplicationId getKeyAttestationApplicationId(int uid);
-}
diff --git a/core/java/android/security/keymaster/KeyAttestationApplicationId.aidl b/core/java/android/security/keymaster/KeyAttestationApplicationId.aidl
deleted file mode 100644
index 9f6ff58..0000000
--- a/core/java/android/security/keymaster/KeyAttestationApplicationId.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* The cpp_header is relative to system/security/keystore/include
- * Link against libkeystore_binder to make use of the native implementation of this Parcelable.
- */
-parcelable KeyAttestationApplicationId cpp_header "keystore/KeyAttestationApplicationId.h";
diff --git a/core/java/android/security/keymaster/KeyAttestationApplicationId.java b/core/java/android/security/keymaster/KeyAttestationApplicationId.java
deleted file mode 100644
index 670f30e1b..0000000
--- a/core/java/android/security/keymaster/KeyAttestationApplicationId.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- * The information aggregated by this class is used by keystore to identify a caller of the
- * keystore API toward a remote party. It aggregates multiple PackageInfos because keystore
- * can only determine a caller by uid granularity, and a uid can be shared by multiple packages.
- * The remote party must decide if it trusts all of the packages enough to consider the
- * confidentiality of the key material in question intact.
- */
-public class KeyAttestationApplicationId implements Parcelable {
- private final KeyAttestationPackageInfo[] mAttestationPackageInfos;
-
- /**
- * @param mAttestationPackageInfos
- */
- public KeyAttestationApplicationId(KeyAttestationPackageInfo[] mAttestationPackageInfos) {
- super();
- this.mAttestationPackageInfos = mAttestationPackageInfos;
- }
-
- /**
- * @return the mAttestationPackageInfos
- */
- public KeyAttestationPackageInfo[] getAttestationPackageInfos() {
- return mAttestationPackageInfos;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeTypedArray(mAttestationPackageInfos, flags);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<KeyAttestationApplicationId> CREATOR
- = new Parcelable.Creator<KeyAttestationApplicationId>() {
- @Override
- public KeyAttestationApplicationId createFromParcel(Parcel source) {
- return new KeyAttestationApplicationId(source);
- }
-
- @Override
- public KeyAttestationApplicationId[] newArray(int size) {
- return new KeyAttestationApplicationId[size];
- }
- };
-
- KeyAttestationApplicationId(Parcel source) {
- mAttestationPackageInfos = source.createTypedArray(KeyAttestationPackageInfo.CREATOR);
- }
-}
diff --git a/core/java/android/security/keymaster/KeyAttestationPackageInfo.aidl b/core/java/android/security/keymaster/KeyAttestationPackageInfo.aidl
deleted file mode 100644
index f8b843b..0000000
--- a/core/java/android/security/keymaster/KeyAttestationPackageInfo.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* The cpp_header is relative to system/security/keystore/include
- * Link against libkeystore_binder to make use of the native implementation of this Parcelable.
- */
-parcelable KeyAttestationPackageInfo cpp_header "keystore/KeyAttestationPackageInfo.h";
diff --git a/core/java/android/security/keymaster/KeyAttestationPackageInfo.java b/core/java/android/security/keymaster/KeyAttestationPackageInfo.java
deleted file mode 100644
index c0b8d8d..0000000
--- a/core/java/android/security/keymaster/KeyAttestationPackageInfo.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-import android.content.pm.Signature;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- * This class constitutes and excerpt from the PackageManager's PackageInfo for the purpose of
- * key attestation. It is part of the KeyAttestationApplicationId, which is used by
- * keystore to identify the caller of the keystore API towards a remote party.
- */
-public class KeyAttestationPackageInfo implements Parcelable {
- private final String mPackageName;
- private final long mPackageVersionCode;
- private final Signature[] mPackageSignatures;
-
- /**
- * @param mPackageName
- * @param mPackageVersionCode
- * @param mPackageSignatures
- */
- public KeyAttestationPackageInfo(
- String mPackageName, long mPackageVersionCode, Signature[] mPackageSignatures) {
- super();
- this.mPackageName = mPackageName;
- this.mPackageVersionCode = mPackageVersionCode;
- this.mPackageSignatures = mPackageSignatures;
- }
- /**
- * @return the mPackageName
- */
- public String getPackageName() {
- return mPackageName;
- }
- /**
- * @return the mPackageVersionCode
- */
- public long getPackageVersionCode() {
- return mPackageVersionCode;
- }
- /**
- * @return the mPackageSignatures
- */
- public Signature[] getPackageSignatures() {
- return mPackageSignatures;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mPackageName);
- dest.writeLong(mPackageVersionCode);
- dest.writeTypedArray(mPackageSignatures, flags);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<KeyAttestationPackageInfo> CREATOR
- = new Parcelable.Creator<KeyAttestationPackageInfo>() {
- @Override
- public KeyAttestationPackageInfo createFromParcel(Parcel source) {
- return new KeyAttestationPackageInfo(source);
- }
-
- @Override
- public KeyAttestationPackageInfo[] newArray(int size) {
- return new KeyAttestationPackageInfo[size];
- }
- };
-
- private KeyAttestationPackageInfo(Parcel source) {
- mPackageName = source.readString();
- mPackageVersionCode = source.readLong();
- mPackageSignatures = source.createTypedArray(Signature.CREATOR);
- }
-}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index dc28fa4..a1f8de4 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -171,7 +171,6 @@
*/
public static final int USER_FRP = UserHandle.USER_NULL + 1;
- public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
@Deprecated
public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
@@ -597,16 +596,6 @@
}
/**
- * Return true if the user has ever chosen a pattern. This is true even if the pattern is
- * currently cleared.
- *
- * @return True if the user has ever chosen a pattern.
- */
- public boolean isPatternEverChosen(int userId) {
- return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
- }
-
- /**
* Returns the length of the PIN set by a particular user.
* @param userId user id of the user whose pin length we have to return
* @return
@@ -639,13 +628,6 @@
return false;
}
}
- /**
- * Records that the user has chosen a pattern at some time, even if the pattern is
- * currently cleared.
- */
- public void reportPatternWasChosen(int userId) {
- setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
- }
/**
* Used by device policy manager to validate the current password
diff --git a/keystore/aaid/aidl/Android.bp b/keystore/aaid/aidl/Android.bp
new file mode 100644
index 0000000..97acfb4
--- /dev/null
+++ b/keystore/aaid/aidl/Android.bp
@@ -0,0 +1,31 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+ name: "android.security.aaid_aidl",
+ srcs: ["android/security/keystore/*.aidl"],
+ unstable: true,
+ backend: {
+ rust: {
+ enabled: true,
+ },
+ cpp: {
+ enabled: true,
+ },
+ },
+}
diff --git a/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl
new file mode 100644
index 0000000..c360cb8
--- /dev/null
+++ b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.security.keystore.KeyAttestationApplicationId;
+
+/** @hide */
+interface IKeyAttestationApplicationIdProvider {
+ /**
+ * Provides information describing the possible applications identified by a UID.
+ * @hide
+ */
+ KeyAttestationApplicationId getKeyAttestationApplicationId(int uid);
+}
diff --git a/keystore/aaid/aidl/android/security/keystore/KeyAttestationApplicationId.aidl b/keystore/aaid/aidl/android/security/keystore/KeyAttestationApplicationId.aidl
new file mode 100644
index 0000000..c33e830
--- /dev/null
+++ b/keystore/aaid/aidl/android/security/keystore/KeyAttestationApplicationId.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.security.keystore.KeyAttestationPackageInfo;
+
+/**
+ * @hide
+ * The information aggregated by this parcelable is used by keystore to identify a caller of the
+ * keystore API toward a remote party. It aggregates multiple PackageInfos because keystore
+ * can only determine a caller by uid granularity, and a uid can be shared by multiple packages.
+ * The remote party must decide if it trusts all of the packages enough to consider the
+ * confidentiality of the key material in question intact.
+ */
+parcelable KeyAttestationApplicationId {
+ KeyAttestationPackageInfo[] packageInfos;
+}
diff --git a/keystore/aaid/aidl/android/security/keystore/KeyAttestationPackageInfo.aidl b/keystore/aaid/aidl/android/security/keystore/KeyAttestationPackageInfo.aidl
new file mode 100644
index 0000000..5f647d0
--- /dev/null
+++ b/keystore/aaid/aidl/android/security/keystore/KeyAttestationPackageInfo.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.security.keystore.Signature;
+
+/**
+ * @hide
+ * This parcelable constitutes and excerpt from the PackageManager's PackageInfo for the purpose of
+ * key attestation. It is part of the KeyAttestationApplicationId, which is used by
+ * keystore to identify the caller of the keystore API towards a remote party.
+ */
+parcelable KeyAttestationPackageInfo {
+ String packageName;
+
+ long versionCode;
+
+ Signature[] signatures;
+}
diff --git a/keystore/aaid/aidl/android/security/keystore/Signature.aidl b/keystore/aaid/aidl/android/security/keystore/Signature.aidl
new file mode 100644
index 0000000..800499a
--- /dev/null
+++ b/keystore/aaid/aidl/android/security/keystore/Signature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+/**
+ * @hide
+ * Represents a signature data read from the package file. Extracted from from the PackageManager's
+ * PackageInfo for the purpose of key attestation. It is part of the KeyAttestationPackageInfo,
+ * which is used by keystore to identify the caller of the keystore API towards a remote party.
+ */
+parcelable Signature {
+ /**
+ * Represents signing certificate data associated with application package, signatures are
+ * expected to be a hex-encoded ASCII string representing valid X509 certificate.
+ */
+ byte[] data;
+}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index b0cdb05..1d66868 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -875,18 +875,7 @@
/**
* Sets the attribute describing what is the intended use of the audio signal,
* such as alarm or ringtone.
- * @param usage one of {@link AttributeSdkUsage#USAGE_UNKNOWN},
- * {@link AttributeSdkUsage#USAGE_MEDIA},
- * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION},
- * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION_SIGNALLING},
- * {@link AttributeSdkUsage#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
- * {@link AttributeSdkUsage#USAGE_NOTIFICATION_RINGTONE},
- * {@link AttributeSdkUsage#USAGE_NOTIFICATION_EVENT},
- * {@link AttributeSdkUsage#USAGE_ASSISTANT},
- * {@link AttributeSdkUsage#USAGE_ASSISTANCE_ACCESSIBILITY},
- * {@link AttributeSdkUsage#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
- * {@link AttributeSdkUsage#USAGE_ASSISTANCE_SONIFICATION},
- * {@link AttributeSdkUsage#USAGE_GAME}.
+ * @param usage the usage to set.
* @return the same Builder instance.
*/
public Builder setUsage(@AttributeSdkUsage int usage) {
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index a311296..ceb3858 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -1284,8 +1284,7 @@
* {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT}.
* <p> For a valid {@link AudioTrack} channel position mask,
* the following conditions apply:
- * <br> (1) at most {@link AudioSystem#OUT_CHANNEL_COUNT_MAX} channel positions may be
- * used;
+ * <br> (1) at most eight channel positions may be used;
* <br> (2) right/left pairs should be matched.
* <p> For input or {@link AudioRecord}, the mask should be
* {@link AudioFormat#CHANNEL_IN_MONO} or
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
index 0f962f9..4e61549 100644
--- a/media/java/android/media/AudioMetadata.java
+++ b/media/java/android/media/AudioMetadata.java
@@ -226,16 +226,15 @@
*
* An Integer value representing presentation content classifier.
*
- * @see AudioPresentation.ContentClassifier
- * One of {@link AudioPresentation#CONTENT_UNKNOWN},
- * {@link AudioPresentation#CONTENT_MAIN},
- * {@link AudioPresentation#CONTENT_MUSIC_AND_EFFECTS},
- * {@link AudioPresentation#CONTENT_VISUALLY_IMPAIRED},
- * {@link AudioPresentation#CONTENT_HEARING_IMPAIRED},
- * {@link AudioPresentation#CONTENT_DIALOG},
- * {@link AudioPresentation#CONTENT_COMMENTARY},
- * {@link AudioPresentation#CONTENT_EMERGENCY},
- * {@link AudioPresentation#CONTENT_VOICEOVER}.
+ * @see AudioPresentation#CONTENT_UNKNOWN
+ * @see AudioPresentation#CONTENT_MAIN
+ * @see AudioPresentation#CONTENT_MUSIC_AND_EFFECTS
+ * @see AudioPresentation#CONTENT_VISUALLY_IMPAIRED
+ * @see AudioPresentation#CONTENT_HEARING_IMPAIRED
+ * @see AudioPresentation#CONTENT_DIALOG
+ * @see AudioPresentation#CONTENT_COMMENTARY
+ * @see AudioPresentation#CONTENT_EMERGENCY
+ * @see AudioPresentation#CONTENT_VOICEOVER
*/
@NonNull public static final Key<Integer> KEY_PRESENTATION_CONTENT_CLASSIFIER =
createKey("presentation-content-classifier", Integer.class);
diff --git a/media/java/android/media/tv/SectionRequest.java b/media/java/android/media/tv/SectionRequest.java
index 078e832..ec0d7f7 100644
--- a/media/java/android/media/tv/SectionRequest.java
+++ b/media/java/android/media/tv/SectionRequest.java
@@ -81,7 +81,7 @@
/**
* Gets the version number of requested session. If it is null, value will be -1.
* <p>The consistency of version numbers between request and response depends on
- * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * {@link BroadcastInfoRequest#getOption()}. If the request has RequestOption value
* REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
* different from the version of the request. Otherwise, response with a different version from
* its request will be considered invalid.
diff --git a/media/java/android/media/tv/SectionResponse.java b/media/java/android/media/tv/SectionResponse.java
index f38ea9d..10333fe 100644
--- a/media/java/android/media/tv/SectionResponse.java
+++ b/media/java/android/media/tv/SectionResponse.java
@@ -76,7 +76,7 @@
/**
* Gets the Version number of requested session. If it is null, value will be -1.
* <p>The consistency of version numbers between request and response depends on
- * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * {@link BroadcastInfoRequest#getOption()}. If the request has RequestOption value
* REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
* different from the version of the request. Otherwise, response with a different version from
* its request will be considered invalid.
diff --git a/media/java/android/media/tv/TableRequest.java b/media/java/android/media/tv/TableRequest.java
index d9587f6..06df07f 100644
--- a/media/java/android/media/tv/TableRequest.java
+++ b/media/java/android/media/tv/TableRequest.java
@@ -129,7 +129,7 @@
/**
* Gets the version number of requested table. If it is null, value will be -1.
* <p>The consistency of version numbers between request and response depends on
- * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * {@link BroadcastInfoRequest#getOption()}. If the request has RequestOption value
* REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
* different from the version of the request. Otherwise, response with a different version from
* its request will be considered invalid.
diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java
index c4fc26e..1daf452 100644
--- a/media/java/android/media/tv/TableResponse.java
+++ b/media/java/android/media/tv/TableResponse.java
@@ -269,7 +269,7 @@
/**
* Gets the version number of requested table. If it is null, value will be -1.
* <p>The consistency of version numbers between request and response depends on
- * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * {@link BroadcastInfoRequest#getOption()}. If the request has RequestOption value
* REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
* different from the version of the request. Otherwise, response with a different version from
* its request will be considered invalid.
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index c616b84f..1c25080 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -38,6 +38,8 @@
#include <mediadrm/IDrmMetricsConsumer.h>
#include <mediadrm/IDrm.h>
#include <utils/Vector.h>
+#include <map>
+#include <string>
using ::android::os::PersistableBundle;
namespace drm = ::android::hardware::drm;
@@ -193,6 +195,11 @@
jclass classId;
};
+struct DrmExceptionFields {
+ jmethodID init;
+ jclass classId;
+};
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -215,6 +222,7 @@
jclass parcelCreatorClassId;
KeyStatusFields keyStatus;
LogMessageFields logMessage;
+ std::map<std::string, DrmExceptionFields> exceptionCtors;
};
static fields_t gFields;
@@ -245,18 +253,32 @@
return arrayList;
}
-int drmThrowException(JNIEnv* env, const char *className, const DrmStatus &err, const char *msg) {
+void resolveDrmExceptionCtor(JNIEnv *env, const char *className) {
+ jclass clazz;
+ jmethodID init;
+ FIND_CLASS(clazz, className);
+ GET_METHOD_ID(init, clazz, "<init>", "(Ljava/lang/String;III)V");
+ gFields.exceptionCtors[std::string(className)] = {
+ .init = init,
+ .classId = static_cast<jclass>(env->NewGlobalRef(clazz))
+ };
+}
+
+void drmThrowException(JNIEnv* env, const char *className, const DrmStatus &err, const char *msg) {
using namespace android::jnihelp;
- jstring _detailMessage = CreateExceptionMsg(env, msg);
- int _status = ThrowException(env, className, "(Ljava/lang/String;III)V",
- _detailMessage,
- err.getCdmErr(),
- err.getOemErr(),
- err.getContext());
- if (_detailMessage != NULL) {
- env->DeleteLocalRef(_detailMessage);
+
+ if (gFields.exceptionCtors.count(std::string(className)) == 0) {
+ jniThrowException(env, className, msg);
+ } else {
+ jstring _detailMessage = CreateExceptionMsg(env, msg);
+ jobject exception = env->NewObject(gFields.exceptionCtors[std::string(className)].classId,
+ gFields.exceptionCtors[std::string(className)].init, _detailMessage,
+ err.getCdmErr(), err.getOemErr(), err.getContext());
+ env->Throw(static_cast<jthrowable>(exception));
+ if (_detailMessage != NULL) {
+ env->DeleteLocalRef(_detailMessage);
+ }
}
- return _status;
}
} // namespace anonymous
@@ -952,6 +974,10 @@
FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
+
+ resolveDrmExceptionCtor(env, "android/media/NotProvisionedException");
+ resolveDrmExceptionCtor(env, "android/media/ResourceBusyException");
+ resolveDrmExceptionCtor(env, "android/media/DeniedByServerException");
}
static void android_media_MediaDrm_native_setup(
@@ -2192,4 +2218,4 @@
int register_android_media_Drm(JNIEnv *env) {
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaDrm", gMethods, NELEM(gMethods));
-}
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS
index 5ade971..86ae581 100644
--- a/packages/SettingsProvider/OWNERS
+++ b/packages/SettingsProvider/OWNERS
@@ -1,5 +1 @@
-hackbod@android.com
-hackbod@google.com
-narayan@google.com
-svetoslavganov@google.com
include /PACKAGE_MANAGER_OWNERS
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 3efb41d..cf26937 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -163,12 +163,10 @@
Settings.Secure.CHARGING_VIBRATION_ENABLED,
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
- Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
Settings.Secure.UI_NIGHT_MODE,
Settings.Secure.UI_NIGHT_MODE_CUSTOM_TYPE,
Settings.Secure.DARK_THEME_CUSTOM_START_TIME,
Settings.Secure.DARK_THEME_CUSTOM_END_TIME,
- Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
Settings.Secure.SKIP_DIRECTION,
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index f6c2f69..f78f202 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -242,9 +242,7 @@
Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.TRUST_AGENTS_EXTEND_UNLOCK, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, JSON_OBJECT_VALIDATOR);
- VALIDATORS.put(Secure.LOCK_SCREEN_WHEN_TRUST_LOST, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SKIP_GESTURE, BOOLEAN_VALIDATOR);
/*
* Only used if FeatureFlag "settings_skip_direction_mutable" is enabled.
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index b404465..b19d349 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -961,7 +961,6 @@
lockPatternUtils.setOwnerInfo(value, userId);
break;
case KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED:
- lockPatternUtils.reportPatternWasChosen(userId);
lockPatternUtils.setVisiblePatternEnabled("1".equals(value), userId);
break;
case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS:
diff --git a/ravenwood/OWNERS b/ravenwood/OWNERS
new file mode 100644
index 0000000..c06b3b9
--- /dev/null
+++ b/ravenwood/OWNERS
@@ -0,0 +1,3 @@
+jsharkey@google.com
+omakoto@google.com
+jaggies@google.com
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 4e412bb..9ac30f3 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -180,6 +180,7 @@
"android.hidl.manager-V1.2-java",
"cbor-java",
"icu4j_calendar_astronomer",
+ "android.security.aaid_aidl-java",
"netd-client",
"overlayable_policy_aidl-java",
"SurfaceFlingerProperties",
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index d94f4f2..5b496f4 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.os.Flags.stateOfHealthPublic;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import static com.android.server.health.Utils.copyV1Battery;
@@ -27,7 +28,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.database.ContentObserver;
import android.hardware.health.HealthInfo;
import android.hardware.health.V2_1.BatteryCapacityLevel;
@@ -1316,10 +1316,14 @@
@Override
public int getProperty(int id, final BatteryProperty prop) throws RemoteException {
switch (id) {
+ case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
+ if (stateOfHealthPublic()) {
+ break;
+ }
+
case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE:
case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE:
case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY:
- case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
mContext.enforceCallingPermission(
android.Manifest.permission.BATTERY_STATS, null);
break;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index f532122c1..8da9473 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1241,11 +1241,10 @@
killProcessGroup = true;
}
if (killProcessGroup) {
- if (async) {
- ProcessList.killProcessGroup(uid, mPid);
- } else {
+ if (!async) {
Process.sendSignalToProcessGroup(uid, mPid, OsConstants.SIGKILL);
}
+ ProcessList.killProcessGroup(uid, mPid);
}
}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index b890bbd..eae417e 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1845,7 +1845,7 @@
private void parseListenForTickles(TypedXmlPullParser parser) {
int userId = 0;
try {
- parser.getAttributeInt(null, XML_ATTR_USER);
+ userId = parser.getAttributeInt(null, XML_ATTR_USER);
} catch (XmlPullParserException e) {
Slog.e(TAG, "error parsing the user for listen-for-tickles", e);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ff959de..09d0bc7 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -346,17 +346,17 @@
@Override
public void onUserStarting(@NonNull TargetUser user) {
- mLockSettingsService.onStartUser(user.getUserIdentifier());
+ mLockSettingsService.onUserStarting(user.getUserIdentifier());
}
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
- mLockSettingsService.onUnlockUser(user.getUserIdentifier());
+ mLockSettingsService.onUserUnlocking(user.getUserIdentifier());
}
@Override
public void onUserStopped(@NonNull TargetUser user) {
- mLockSettingsService.onCleanupUser(user.getUserIdentifier());
+ mLockSettingsService.onUserStopped(user.getUserIdentifier());
}
}
@@ -778,7 +778,7 @@
}
@VisibleForTesting
- void onCleanupUser(int userId) {
+ void onUserStopped(int userId) {
hideEncryptionNotification(new UserHandle(userId));
// User is stopped with its CE key evicted. Restore strong auth requirement to the default
// flags after boot since stopping and restarting a user later is equivalent to rebooting
@@ -790,7 +790,7 @@
}
}
- private void onStartUser(final int userId) {
+ private void onUserStarting(final int userId) {
maybeShowEncryptionNotificationForUser(userId, "user started");
}
@@ -826,7 +826,7 @@
}
}
- private void onUnlockUser(final int userId) {
+ private void onUserUnlocking(final int userId) {
// Perform tasks which require locks in LSS on a handler, as we are callbacks from
// ActivityManager.unlockUser()
mHandler.post(new Runnable() {
@@ -1767,10 +1767,6 @@
}
private void onPostPasswordChanged(LockscreenCredential newCredential, int userHandle) {
- if (newCredential.isPattern()) {
- setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
- }
-
updatePasswordHistory(newCredential, userHandle);
mContext.getSystemService(TrustManager.class).reportEnabledTrustAgentsChanged(userHandle);
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 7fec377..3d3703a 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -31,6 +31,7 @@
import android.hardware.weaver.WeaverConfig;
import android.hardware.weaver.WeaverReadResponse;
import android.hardware.weaver.WeaverReadStatus;
+import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -71,7 +72,6 @@
import java.util.Objects;
import java.util.Set;
-
/**
* A class that manages a user's synthetic password (SP) ({@link #SyntheticPassword}), along with a
* set of SP protectors that are independent ways that the SP is protected.
@@ -500,7 +500,7 @@
private final Context mContext;
private LockSettingsStorage mStorage;
- private IWeaver mWeaver;
+ private volatile IWeaver mWeaver;
private WeaverConfig mWeaverConfig;
private PasswordSlotManager mPasswordSlotManager;
@@ -531,17 +531,63 @@
}
}
- private IWeaver getWeaverService() {
- // Try to get the AIDL service first
+ private class WeaverDiedRecipient implements IBinder.DeathRecipient {
+ // Not synchronized on the outer class, since setting the pointer to null is atomic, and we
+ // don't want to have to worry about any sort of deadlock here.
+ @Override
+ public void binderDied() {
+ // Weaver died. Try to recover by setting mWeaver to null, which makes
+ // getWeaverService() look up the service again. This is done only as a simple
+ // robustness measure; it should not be relied on. If this triggers, the root cause is
+ // almost certainly a bug in the device's Weaver implementation, which must be fixed.
+ Slog.wtf(TAG, "Weaver service has died");
+ mWeaver.asBinder().unlinkToDeath(this, 0);
+ mWeaver = null;
+ }
+ }
+
+ private @Nullable IWeaver getWeaverAidlService() {
+ final IWeaver aidlWeaver;
try {
- IWeaver aidlWeaver = IWeaver.Stub.asInterface(
- ServiceManager.waitForDeclaredService(IWeaver.DESCRIPTOR + "/default"));
- if (aidlWeaver != null) {
- Slog.i(TAG, "Using AIDL weaver service");
- return aidlWeaver;
- }
+ aidlWeaver =
+ IWeaver.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(IWeaver.DESCRIPTOR + "/default"));
} catch (SecurityException e) {
Slog.w(TAG, "Does not have permissions to get AIDL weaver service");
+ return null;
+ }
+ if (aidlWeaver == null) {
+ return null;
+ }
+ final int aidlVersion;
+ try {
+ aidlVersion = aidlWeaver.getInterfaceVersion();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Cannot get AIDL weaver service version", e);
+ return null;
+ }
+ if (aidlVersion < 2) {
+ Slog.w(TAG,
+ "Ignoring AIDL weaver service v"
+ + aidlVersion
+ + " because only v2 and later are supported");
+ return null;
+ }
+ Slog.i(TAG, "Found AIDL weaver service v" + aidlVersion);
+ return aidlWeaver;
+ }
+
+ private @Nullable IWeaver getWeaverServiceInternal() {
+ // Try to get the AIDL service first
+ IWeaver aidlWeaver = getWeaverAidlService();
+ if (aidlWeaver != null) {
+ Slog.i(TAG, "Using AIDL weaver service");
+ try {
+ aidlWeaver.asBinder().linkToDeath(new WeaverDiedRecipient(), 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to register Weaver death recipient", e);
+ }
+ return aidlWeaver;
}
// If the AIDL service can't be found, look for the HIDL service
@@ -563,15 +609,20 @@
return LockPatternUtils.isAutoPinConfirmFeatureAvailable();
}
- private synchronized boolean isWeaverAvailable() {
- if (mWeaver != null) {
- return true;
+ /**
+ * Returns a handle to the Weaver service, or null if Weaver is unavailable. Note that not all
+ * devices support Weaver.
+ */
+ private synchronized @Nullable IWeaver getWeaverService() {
+ IWeaver weaver = mWeaver;
+ if (weaver != null) {
+ return weaver;
}
// Re-initialize weaver in case there was a transient error preventing access to it.
- IWeaver weaver = getWeaverService();
+ weaver = getWeaverServiceInternal();
if (weaver == null) {
- return false;
+ return null;
}
final WeaverConfig weaverConfig;
@@ -579,19 +630,18 @@
weaverConfig = weaver.getConfig();
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Failed to get weaver config", e);
- return false;
+ return null;
}
if (weaverConfig == null || weaverConfig.slots <= 0) {
Slog.e(TAG, "Invalid weaver config");
- return false;
+ return null;
}
mWeaver = weaver;
mWeaverConfig = weaverConfig;
mPasswordSlotManager.refreshActiveSlots(getUsedWeaverSlots());
Slog.i(TAG, "Weaver service initialized");
-
- return true;
+ return weaver;
}
/**
@@ -601,7 +651,7 @@
*
* @return the value stored in the weaver slot, or null if the operation fails
*/
- private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value) {
+ private byte[] weaverEnroll(IWeaver weaver, int slot, byte[] key, @Nullable byte[] value) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
throw new IllegalArgumentException("Invalid slot for weaver");
}
@@ -614,7 +664,7 @@
value = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize);
}
try {
- mWeaver.write(slot, key, value);
+ weaver.write(slot, key, value);
} catch (RemoteException e) {
Slog.e(TAG, "weaver write binder call failed, slot: " + slot, e);
return null;
@@ -643,7 +693,7 @@
* the verification is successful, throttled or failed. If successful, the bound secret
* is also returned.
*/
- private VerifyCredentialResponse weaverVerify(int slot, byte[] key) {
+ private VerifyCredentialResponse weaverVerify(IWeaver weaver, int slot, byte[] key) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
throw new IllegalArgumentException("Invalid slot for weaver");
}
@@ -654,7 +704,7 @@
}
final WeaverReadResponse readResponse;
try {
- readResponse = mWeaver.read(slot, key);
+ readResponse = weaver.read(slot, key);
} catch (RemoteException e) {
Slog.e(TAG, "weaver read failed, slot: " + slot, e);
return VerifyCredentialResponse.ERROR;
@@ -846,14 +896,15 @@
int slot = loadWeaverSlot(protectorId, userId);
destroyState(WEAVER_SLOT_NAME, protectorId, userId);
if (slot != INVALID_WEAVER_SLOT) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Cannot erase Weaver slot because Weaver is unavailable");
return;
}
Set<Integer> usedSlots = getUsedWeaverSlots();
if (!usedSlots.contains(slot)) {
Slogf.i(TAG, "Erasing Weaver slot %d", slot);
- weaverEnroll(slot, null, null);
+ weaverEnroll(weaver, slot, null, null);
mPasswordSlotManager.markSlotDeleted(slot);
} else {
Slogf.i(TAG, "Weaver slot %d was already reused; not erasing it", slot);
@@ -931,13 +982,14 @@
Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId);
- if (isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver != null) {
// Weaver is available, so make the protector use it to verify the LSKF. Do this even
// if the LSKF is empty, as that gives us support for securely deleting the protector.
int weaverSlot = getNextAvailableWeaverSlot();
Slogf.i(TAG, "Enrolling LSKF for user %d into Weaver slot %d", userId, weaverSlot);
- byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
- null);
+ byte[] weaverSecret = weaverEnroll(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf), null);
if (weaverSecret == null) {
throw new IllegalStateException(
"Fail to enroll user password under weaver " + userId);
@@ -1024,7 +1076,8 @@
}
return VerifyCredentialResponse.fromGateKeeperResponse(response);
} else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "No weaver service to verify SP-based FRP credential");
return VerifyCredentialResponse.ERROR;
}
@@ -1032,7 +1085,8 @@
byte[] stretchedLskf = stretchLskf(userCredential, pwd);
int weaverSlot = persistentData.userId;
- return weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf)).stripPayload();
+ return weaverVerify(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf)).stripPayload();
} else {
Slog.e(TAG, "persistentData.type must be TYPE_SP_GATEKEEPER or TYPE_SP_WEAVER, but is "
+ persistentData.type);
@@ -1134,7 +1188,7 @@
TokenData tokenData = new TokenData();
tokenData.mType = type;
final byte[] secdiscardable = SecureRandomUtils.randomBytes(SECDISCARDABLE_LENGTH);
- if (isWeaverAvailable()) {
+ if (getWeaverService() != null) {
tokenData.weaverSecret = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize);
tokenData.secdiscardableOnDisk = SyntheticPasswordCrypto.encrypt(tokenData.weaverSecret,
PERSONALIZATION_WEAVER_TOKEN, secdiscardable);
@@ -1177,10 +1231,11 @@
return false;
}
Slogf.i(TAG, "Creating token-based protector %016x for user %d", tokenHandle, userId);
- if (isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver != null) {
int slot = getNextAvailableWeaverSlot();
Slogf.i(TAG, "Using Weaver slot %d for new token-based protector", slot);
- if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
+ if (weaverEnroll(weaver, slot, null, tokenData.weaverSecret) == null) {
Slog.e(TAG, "Failed to enroll weaver secret when activating token");
return false;
}
@@ -1269,12 +1324,14 @@
int weaverSlot = loadWeaverSlot(protectorId, userId);
if (weaverSlot != INVALID_WEAVER_SLOT) {
// Protector uses Weaver to verify the LSKF
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable");
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
- result.gkResponse = weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf));
+ result.gkResponse = weaverVerify(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf));
if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
return result;
}
@@ -1442,12 +1499,13 @@
}
int slotId = loadWeaverSlot(protectorId, userId);
if (slotId != INVALID_WEAVER_SLOT) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable");
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
- VerifyCredentialResponse response = weaverVerify(slotId, null);
+ VerifyCredentialResponse response = weaverVerify(weaver, slotId, null);
if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
response.getGatekeeperHAT() == null) {
Slog.e(TAG,
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2f9536f..23532c1 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -261,6 +261,8 @@
private final OverlayActorEnforcer mActorEnforcer;
+ private int mPrevStartedUserId = -1;
+
public OverlayManagerService(@NonNull final Context context) {
super(context);
try {
@@ -338,6 +340,10 @@
}
private void onStartUser(@UserIdInt int newUserId) {
+ // Do nothing when start a user that is the same as the one started previously.
+ if (newUserId == mPrevStartedUserId) {
+ return;
+ }
try {
traceBegin(TRACE_TAG_RRO, "OMS#onStartUser " + newUserId);
// ensure overlays in the settings are up-to-date, and propagate
@@ -348,6 +354,7 @@
} finally {
traceEnd(TRACE_TAG_RRO);
}
+ mPrevStartedUserId = newUserId;
}
private static String[] getDefaultOverlayPackages() {
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 39cd888..8bd2982 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -1050,7 +1050,7 @@
context.unregisterReceiver(this);
artManager.scheduleBackgroundDexoptJob();
}
- }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }, new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index 80d6ebb..85e11d6 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -34,8 +34,11 @@
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
@@ -155,10 +158,27 @@
private long getApksSize(File apkDir) {
// TODO(b/249294752): also count apk sizes for failed installs
final AtomicLong apksSize = new AtomicLong();
- try (Stream<Path> walkStream = Files.walk(apkDir.toPath())) {
- walkStream.filter(p -> p.toFile().isFile()
- && ApkLiteParseUtils.isApkFile(p.toFile())).forEach(
- f -> apksSize.addAndGet(f.toFile().length()));
+ try {
+ Files.walkFileTree(apkDir.toPath(), new SimpleFileVisitor<>() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ if (dir.equals(apkDir.toPath())) {
+ return FileVisitResult.CONTINUE;
+ } else {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ if (file.toFile().isFile() && ApkLiteParseUtils.isApkFile(file.toFile())) {
+ apksSize.addAndGet(file.toFile().length());
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
} catch (IOException e) {
// ignore
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index f0bf1ea8..d0c346a 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -334,7 +334,10 @@
ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_UNKNOWN),
cancellationReason,
durationMs,
- 0); // deprecated, used to be durationIncludingSleepMs
+ 0, // deprecated, used to be durationIncludingSleepMs
+ 0, // optimizedPackagesCount
+ 0, // packagesDependingOnBootClasspathCount
+ 0); // totalPackagesCount
}
}
}
diff --git a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
index c908acd..d5bc912 100644
--- a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
+++ b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
@@ -24,9 +24,10 @@
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.security.keymaster.IKeyAttestationApplicationIdProvider;
-import android.security.keymaster.KeyAttestationApplicationId;
-import android.security.keymaster.KeyAttestationPackageInfo;
+import android.security.keystore.IKeyAttestationApplicationIdProvider;
+import android.security.keystore.KeyAttestationApplicationId;
+import android.security.keystore.KeyAttestationPackageInfo;
+import android.security.keystore.Signature;
/**
* @hide
@@ -64,14 +65,25 @@
for (int i = 0; i < packageNames.length; ++i) {
PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageNames[i],
PackageManager.GET_SIGNATURES, userId);
- keyAttestationPackageInfos[i] = new KeyAttestationPackageInfo(packageNames[i],
- packageInfo.getLongVersionCode(), packageInfo.signatures);
+ KeyAttestationPackageInfo pInfo = new KeyAttestationPackageInfo();
+ pInfo.packageName = new String(packageNames[i]);
+ pInfo.versionCode = packageInfo.getLongVersionCode();
+ pInfo.signatures = new Signature[packageInfo.signatures.length];
+ for (int index = 0; index < packageInfo.signatures.length; index++) {
+ Signature sign = new Signature();
+ sign.data = packageInfo.signatures[index].toByteArray();
+ pInfo.signatures[index] = sign;
+ }
+
+ keyAttestationPackageInfos[i] = pInfo;
}
} catch (NameNotFoundException nnfe) {
throw new RemoteException(nnfe.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
- return new KeyAttestationApplicationId(keyAttestationPackageInfos);
+ KeyAttestationApplicationId attestAppId = new KeyAttestationApplicationId();
+ attestAppId.packageInfos = keyAttestationPackageInfos;
+ return attestAppId;
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 21bfdd8..635e11b 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -31,7 +31,6 @@
import android.app.trust.ITrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -42,11 +41,9 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
-import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -237,7 +234,6 @@
mIdleTrustableTimeoutAlarmListenerForUser = new SparseArray<>();
private AlarmManager mAlarmManager;
private final Object mAlarmLock = new Object();
- private final SettingsObserver mSettingsObserver;
private final StrongAuthTracker mStrongAuthTracker;
@@ -279,7 +275,6 @@
mLockPatternUtils = injector.getLockPatternUtils();
mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper());
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mSettingsObserver = new SettingsObserver(mHandler);
}
@Override
@@ -307,103 +302,10 @@
}
}
- // Extend unlock config and logic
- private final class SettingsObserver extends ContentObserver {
- private final Uri TRUST_AGENTS_EXTEND_UNLOCK =
- Settings.Secure.getUriFor(Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK);
-
- private final Uri LOCK_SCREEN_WHEN_TRUST_LOST =
- Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST);
-
- private final boolean mIsAutomotive;
- private final ContentResolver mContentResolver;
- private boolean mTrustAgentsNonrenewableTrust;
- private boolean mLockWhenTrustLost;
-
- /**
- * Creates a settings observer
- *
- * @param handler The handler to run {@link #onChange} on, or null if none.
- */
- SettingsObserver(Handler handler) {
- super(handler);
-
- PackageManager packageManager = getContext().getPackageManager();
- mIsAutomotive = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
-
- mContentResolver = getContext().getContentResolver();
- updateContentObserver();
- }
-
- void updateContentObserver() {
- mContentResolver.unregisterContentObserver(this);
- mContentResolver.registerContentObserver(TRUST_AGENTS_EXTEND_UNLOCK,
- false /* notifyForDescendents */,
- this /* observer */,
- mCurrentUser);
- mContentResolver.registerContentObserver(LOCK_SCREEN_WHEN_TRUST_LOST,
- false /* notifyForDescendents */,
- this /* observer */,
- mCurrentUser);
-
- // Update the value immediately
- onChange(true /* selfChange */, TRUST_AGENTS_EXTEND_UNLOCK);
- onChange(true /* selfChange */, LOCK_SCREEN_WHEN_TRUST_LOST);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (TRUST_AGENTS_EXTEND_UNLOCK.equals(uri)) {
- // Smart lock should only grant non-renewable trust. The only exception is for
- // automotive, where it can actively unlock the head unit.
- int defaultValue = mIsAutomotive ? 0 : 1;
-
- mTrustAgentsNonrenewableTrust =
- Settings.Secure.getIntForUser(
- mContentResolver,
- Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
- defaultValue,
- mCurrentUser) != 0;
- } else if (LOCK_SCREEN_WHEN_TRUST_LOST.equals(uri)) {
- mLockWhenTrustLost =
- Settings.Secure.getIntForUser(
- mContentResolver,
- Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
- 0 /* default */,
- mCurrentUser) != 0;
- }
- }
-
- boolean getTrustAgentsNonrenewableTrust() {
- return mTrustAgentsNonrenewableTrust;
- }
-
- boolean getLockWhenTrustLost() {
- return mLockWhenTrustLost;
- }
- }
-
- private void maybeLockScreen(int userId) {
- if (userId != mCurrentUser) {
- return;
- }
-
- if (mSettingsObserver.getLockWhenTrustLost()) {
- if (DEBUG) Slog.d(TAG, "Locking device because trust was lost");
- try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error locking screen when trust was lost");
- }
-
- // If active unlocking is not allowed, cancel any pending trust timeouts because the
- // screen is already locked.
- TrustedTimeoutAlarmListener alarm = mTrustTimeoutAlarmListenerForUser.get(userId);
- if (alarm != null && mSettingsObserver.getTrustAgentsNonrenewableTrust()) {
- mAlarmManager.cancel(alarm);
- alarm.setQueued(false /* isQueued */);
- }
- }
+ // Automotive head units can be unlocked by a trust agent, even when the agent doesn't use
+ // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE.
+ private boolean isAutomotive() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
private void scheduleTrustTimeout(boolean override, boolean isTrustableTimeout) {
@@ -600,12 +502,10 @@
synchronized (mUserTrustState) {
wasTrusted = (mUserTrustState.get(userId) == TrustState.TRUSTED);
wasTrustable = (mUserTrustState.get(userId) == TrustState.TRUSTABLE);
- boolean isAutomotive = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
boolean renewingTrust = wasTrustable && (
(flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0);
boolean canMoveToTrusted =
- alreadyUnlocked || isFromUnlock || renewingTrust || isAutomotive;
+ alreadyUnlocked || isFromUnlock || renewingTrust || isAutomotive();
boolean upgradingTrustForCurrentUser = (userId == mCurrentUser);
if (trustedByAtLeastOneAgent && wasTrusted) {
@@ -632,9 +532,7 @@
isNowTrusted, newlyUnlocked, userId, flags, getTrustGrantedMessages(userId));
if (isNowTrusted != wasTrusted) {
refreshDeviceLockedForUser(userId);
- if (!isNowTrusted) {
- maybeLockScreen(userId);
- } else {
+ if (isNowTrusted) {
boolean isTrustableTimeout =
(flags & FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0;
// Every time we grant renewable trust we should override the idle trustable
@@ -1855,9 +1753,7 @@
synchronized(mUsersUnlockedByBiometric) {
mUsersUnlockedByBiometric.put(userId, true);
}
- // In non-renewable trust mode we need to refresh trust state here, which will call
- // refreshDeviceLockedForUser()
- int updateTrustOnUnlock = mSettingsObserver.getTrustAgentsNonrenewableTrust() ? 1 : 0;
+ int updateTrustOnUnlock = isAutomotive() ? 0 : 1;
mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, userId,
updateTrustOnUnlock).sendToTarget();
mHandler.obtainMessage(MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH, userId).sendToTarget();
@@ -1966,7 +1862,6 @@
break;
case MSG_SWITCH_USER:
mCurrentUser = msg.arg1;
- mSettingsObserver.updateContentObserver();
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_STOP_USER:
@@ -2196,7 +2091,6 @@
mLockPatternUtils.requireStrongAuth(
mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, mUserId);
}
- maybeLockScreen(mUserId);
}
protected abstract void handleAlarm();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index dee7780..37a6d22 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -781,7 +781,7 @@
password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.onCleanupUser(PRIMARY_USER_ID);
+ mService.onUserStopped(PRIMARY_USER_ID);
assertNull(mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));
assertTrue(mLocalService.unlockUserWithToken(handle, token, PRIMARY_USER_ID));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java
index 2c9ba34..e8b7ad7 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java
@@ -169,7 +169,7 @@
assertTrue(mService.isWeakEscrowTokenActive(handle, PRIMARY_USER_ID));
assertTrue(mService.isWeakEscrowTokenValid(handle, token, PRIMARY_USER_ID));
- mService.onCleanupUser(PRIMARY_USER_ID);
+ mService.onUserStopped(PRIMARY_USER_ID);
assertNull(mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));
assertTrue(mLocalService.unlockUserWithToken(handle, token, PRIMARY_USER_ID));
diff --git a/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java
new file mode 100644
index 0000000..949f8e7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.text.TextUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
+import com.android.server.connectivity.Vpn;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LockdownVpnTrackerTest {
+ private static final NetworkCapabilities TEST_CELL_NC = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .build();
+ private static final LinkProperties TEST_CELL_LP = new LinkProperties();
+
+ static {
+ TEST_CELL_LP.setInterfaceName("rmnet0");
+ TEST_CELL_LP.addLinkAddress(new LinkAddress("192.0.2.2/25"));
+ }
+
+ // Use a context wrapper instead of a mock since LockdownVpnTracker builds notifications which
+ // is tedious and currently unnecessary to mock.
+ private final Context mContext = new ContextWrapper(InstrumentationRegistry.getContext()) {
+ @Override
+ public Object getSystemService(String name) {
+ if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
+ if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
+
+ return super.getSystemService(name);
+ }
+ };
+ @Mock private ConnectivityManager mCm;
+ @Mock private Vpn mVpn;
+ @Mock private NotificationManager mNotificationManager;
+ @Mock private NetworkInfo mVpnNetworkInfo;
+ @Mock private VpnConfig mVpnConfig;
+ @Mock private Network mNetwork;
+ @Mock private Network mNetwork2;
+ @Mock private Network mVpnNetwork;
+
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+ private VpnProfile mProfile;
+
+ private VpnProfile createTestVpnProfile() {
+ final String profileName = "testVpnProfile";
+ final VpnProfile profile = new VpnProfile(profileName);
+ profile.name = "My VPN";
+ profile.server = "192.0.2.1";
+ profile.dnsServers = "8.8.8.8";
+ profile.ipsecIdentifier = "My ipsecIdentifier";
+ profile.ipsecSecret = "My PSK";
+ profile.type = VpnProfile.TYPE_IKEV2_IPSEC_PSK;
+
+ return profile;
+ }
+
+ private NetworkCallback getDefaultNetworkCallback() {
+ final ArgumentCaptor<NetworkCallback> callbackCaptor =
+ ArgumentCaptor.forClass(NetworkCallback.class);
+ verify(mCm).registerSystemDefaultNetworkCallback(callbackCaptor.capture(), eq(mHandler));
+ return callbackCaptor.getValue();
+ }
+
+ private NetworkCallback getVpnNetworkCallback() {
+ final ArgumentCaptor<NetworkCallback> callbackCaptor =
+ ArgumentCaptor.forClass(NetworkCallback.class);
+ verify(mCm).registerNetworkCallback(any(), callbackCaptor.capture(), eq(mHandler));
+ return callbackCaptor.getValue();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mHandlerThread = new HandlerThread("LockdownVpnTrackerTest");
+ mHandlerThread.start();
+ mHandler = mHandlerThread.getThreadHandler();
+
+ doReturn(mVpnNetworkInfo).when(mVpn).getNetworkInfo();
+ doReturn(false).when(mVpnNetworkInfo).isConnectedOrConnecting();
+ doReturn(mVpnConfig).when(mVpn).getLegacyVpnConfig();
+ // mVpnConfig is a mock but the production code will try to add addresses in this array
+ // assuming it's non-null, so it needs to be initialized.
+ mVpnConfig.addresses = new ArrayList<>();
+
+ mProfile = createTestVpnProfile();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ mHandlerThread.join();
+ }
+ }
+
+ private LockdownVpnTracker initAndVerifyLockdownVpnTracker() {
+ final LockdownVpnTracker lockdownVpnTracker =
+ new LockdownVpnTracker(mContext, mHandler, mVpn, mProfile);
+ lockdownVpnTracker.init();
+ verify(mVpn).setEnableTeardown(false);
+ verify(mVpn).setLockdown(true);
+ verify(mCm).setLegacyLockdownVpnEnabled(true);
+ verify(mVpn).stopVpnRunnerPrivileged();
+ verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS));
+
+ return lockdownVpnTracker;
+ }
+
+ private void callCallbacksForNetworkConnect(NetworkCallback callback, Network network,
+ NetworkCapabilities nc, LinkProperties lp, boolean blocked) {
+ callback.onAvailable(network);
+ callback.onCapabilitiesChanged(network, nc);
+ callback.onLinkPropertiesChanged(network, lp);
+ callback.onBlockedStatusChanged(network, blocked);
+ }
+
+ private void callCallbacksForNetworkConnect(NetworkCallback callback, Network network) {
+ callCallbacksForNetworkConnect(
+ callback, network, TEST_CELL_NC, TEST_CELL_LP, true /* blocked */);
+ }
+
+ private boolean isExpectedNotification(Notification notification, int titleRes, int iconRes) {
+ if (!NOTIFICATION_CHANNEL_VPN.equals(notification.getChannelId())) {
+ return false;
+ }
+ final CharSequence expectedTitle = mContext.getString(titleRes);
+ final CharSequence actualTitle = notification.extras.getCharSequence(
+ Notification.EXTRA_TITLE);
+ if (!TextUtils.equals(expectedTitle, actualTitle)) {
+ return false;
+ }
+ return notification.getSmallIcon().getResId() == iconRes;
+ }
+
+ @Test
+ public void testShutdown() {
+ final LockdownVpnTracker lockdownVpnTracker = initAndVerifyLockdownVpnTracker();
+ final NetworkCallback defaultCallback = getDefaultNetworkCallback();
+ final NetworkCallback vpnCallback = getVpnNetworkCallback();
+ clearInvocations(mVpn, mCm, mNotificationManager);
+
+ lockdownVpnTracker.shutdown();
+ verify(mVpn).stopVpnRunnerPrivileged();
+ verify(mVpn).setLockdown(false);
+ verify(mCm).setLegacyLockdownVpnEnabled(false);
+ verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS));
+ verify(mVpn).setEnableTeardown(true);
+ verify(mCm).unregisterNetworkCallback(defaultCallback);
+ verify(mCm).unregisterNetworkCallback(vpnCallback);
+ }
+
+ @Test
+ public void testDefaultNetworkConnected() {
+ initAndVerifyLockdownVpnTracker();
+ final NetworkCallback defaultCallback = getDefaultNetworkCallback();
+ clearInvocations(mVpn, mCm, mNotificationManager);
+
+ // mNetwork connected and available.
+ callCallbacksForNetworkConnect(defaultCallback, mNetwork);
+
+ // Vpn is starting
+ verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork, TEST_CELL_LP);
+ verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS),
+ argThat(notification -> isExpectedNotification(notification,
+ R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected)));
+ }
+
+ private void doTestDefaultLpChanged(LinkProperties startingLp, LinkProperties newLp) {
+ initAndVerifyLockdownVpnTracker();
+ final NetworkCallback defaultCallback = getDefaultNetworkCallback();
+ callCallbacksForNetworkConnect(
+ defaultCallback, mNetwork, TEST_CELL_NC, startingLp, true /* blocked */);
+ clearInvocations(mVpn, mCm, mNotificationManager);
+
+ // LockdownVpnTracker#handleStateChangedLocked() is not called on the same network even if
+ // the LinkProperties change.
+ defaultCallback.onLinkPropertiesChanged(mNetwork, newLp);
+
+ // Ideally the VPN should start if it hasn't already, but it doesn't because nothing calls
+ // LockdownVpnTracker#handleStateChangedLocked. This is a bug.
+ // TODO: consider fixing this.
+ verify(mVpn, never()).stopVpnRunnerPrivileged();
+ verify(mVpn, never()).startLegacyVpnPrivileged(any(), any(), any());
+ verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS));
+ }
+
+ @Test
+ public void testDefaultLPChanged_V4AddLinkAddressV4() {
+ final LinkProperties lp = new LinkProperties(TEST_CELL_LP);
+ lp.setInterfaceName("rmnet0");
+ lp.addLinkAddress(new LinkAddress("192.0.2.3/25"));
+ doTestDefaultLpChanged(TEST_CELL_LP, lp);
+ }
+
+ @Test
+ public void testDefaultLPChanged_V4AddLinkAddressV6() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("rmnet0");
+ lp.addLinkAddress(new LinkAddress("192.0.2.3/25"));
+ final LinkProperties newLp = new LinkProperties(lp);
+ newLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+ doTestDefaultLpChanged(lp, newLp);
+ }
+
+ @Test
+ public void testDefaultLPChanged_V6AddLinkAddressV4() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("rmnet0");
+ lp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+ final LinkProperties newLp = new LinkProperties(lp);
+ newLp.addLinkAddress(new LinkAddress("192.0.2.3/25"));
+ doTestDefaultLpChanged(lp, newLp);
+ }
+
+ @Test
+ public void testDefaultLPChanged_AddLinkAddressV4() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("rmnet0");
+ doTestDefaultLpChanged(lp, TEST_CELL_LP);
+ }
+
+ @Test
+ public void testDefaultNetworkChanged() {
+ initAndVerifyLockdownVpnTracker();
+ final NetworkCallback defaultCallback = getDefaultNetworkCallback();
+ final NetworkCallback vpnCallback = getVpnNetworkCallback();
+ callCallbacksForNetworkConnect(defaultCallback, mNetwork);
+ clearInvocations(mVpn, mCm, mNotificationManager);
+
+ // New network and LinkProperties received
+ final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .build();
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName("wlan0");
+ callCallbacksForNetworkConnect(
+ defaultCallback, mNetwork2, wifiNc, wifiLp, true /* blocked */);
+
+ // Vpn is restarted.
+ verify(mVpn).stopVpnRunnerPrivileged();
+ verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork2, wifiLp);
+ verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS));
+ verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS),
+ argThat(notification -> isExpectedNotification(notification,
+ R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected)));
+
+ // Vpn is Connected
+ doReturn(true).when(mVpnNetworkInfo).isConnectedOrConnecting();
+ doReturn(true).when(mVpnNetworkInfo).isConnected();
+ vpnCallback.onAvailable(mVpnNetwork);
+ verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS),
+ argThat(notification -> isExpectedNotification(notification,
+ R.string.vpn_lockdown_connected, R.drawable.vpn_connected)));
+
+ }
+
+ @Test
+ public void testSystemDefaultLost() {
+ initAndVerifyLockdownVpnTracker();
+ final NetworkCallback defaultCallback = getDefaultNetworkCallback();
+ // mNetwork connected
+ callCallbacksForNetworkConnect(defaultCallback, mNetwork);
+ clearInvocations(mVpn, mCm, mNotificationManager);
+
+ defaultCallback.onLost(mNetwork);
+
+ // Vpn is stopped
+ verify(mVpn).stopVpnRunnerPrivileged();
+ verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS));
+ }
+}
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index 87da09a..8c644cf 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -49,16 +49,19 @@
kDeprecated = 0x01,
kSystemApi = 0x02,
kTestApi = 0x04,
+ kFlaggedApi = 0x08,
};
StringPiece doc_str;
uint32_t bit_mask;
StringPiece annotation;
+ bool preserve_params;
};
-static std::array<AnnotationRule, 2> sAnnotationRules = {{
- {"@SystemApi", AnnotationRule::kSystemApi, "@android.annotation.SystemApi"},
- {"@TestApi", AnnotationRule::kTestApi, "@android.annotation.TestApi"},
+static std::array<AnnotationRule, 3> sAnnotationRules = {{
+ {"@SystemApi", AnnotationRule::kSystemApi, "@android.annotation.SystemApi", true},
+ {"@TestApi", AnnotationRule::kTestApi, "@android.annotation.TestApi", false},
+ {"@FlaggedApi", AnnotationRule::kFlaggedApi, "@android.annotation.FlaggedApi", true},
}};
void AnnotationProcessor::AppendCommentLine(std::string comment) {
@@ -73,12 +76,11 @@
std::string::size_type idx = comment.find(rule.doc_str.data());
if (idx != std::string::npos) {
// Captures all parameters associated with the specified annotation rule
- // by matching the first pair of parantheses after the rule.
- std::regex re(std::string(rule.doc_str) += "\\s*\\((.+)\\)");
+ // by matching the first pair of parentheses after the rule.
+ std::regex re(std::string(rule.doc_str).append(R"(\s*\((.+)\))"));
std::smatch match_result;
const bool is_match = std::regex_search(comment, match_result, re);
- // We currently only capture and preserve parameters for SystemApi.
- if (is_match && rule.bit_mask == AnnotationRule::kSystemApi) {
+ if (is_match && rule.preserve_params) {
annotation_parameter_map_[rule.bit_mask] = match_result[1].str();
comment.erase(comment.begin() + match_result.position(),
comment.begin() + match_result.position() + match_result.length());
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
index 6bc8902..e98e96b 100644
--- a/tools/aapt2/java/AnnotationProcessor_test.cpp
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -76,6 +76,36 @@
EXPECT_THAT(annotations, HasSubstr("This is a system API"));
}
+TEST(AnnotationProcessorTest, EmitsFlaggedApiAnnotationAndRemovesFromComment) {
+ AnnotationProcessor processor;
+ processor.AppendComment("@FlaggedApi This is a flagged API");
+
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
+
+ EXPECT_THAT(annotations, HasSubstr("@android.annotation.FlaggedApi"));
+ EXPECT_THAT(annotations, Not(HasSubstr("@FlaggedApi")));
+ EXPECT_THAT(annotations, HasSubstr("This is a flagged API"));
+}
+
+TEST(AnnotationProcessorTest, EmitsFlaggedApiAnnotationParamsAndRemovesFromComment) {
+ AnnotationProcessor processor;
+ processor.AppendComment("@FlaggedApi (\"android.flags.my_flag\") This is a flagged API");
+
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
+
+ EXPECT_THAT(annotations, HasSubstr("@android.annotation.FlaggedApi(\"android.flags.my_flag\")"));
+ EXPECT_THAT(annotations, Not(HasSubstr("@FlaggedApi")));
+ EXPECT_THAT(annotations, HasSubstr("This is a flagged API"));
+}
+
TEST(AnnotationProcessorTest, EmitsTestApiAnnotationAndRemovesFromComment) {
AnnotationProcessor processor;
processor.AppendComment("@TestApi This is a test API");