Merge "Ignore null action in AlarmManagerService$UninstallReceiver." into main
diff --git a/PERFORMANCE_OWNERS b/PERFORMANCE_OWNERS
index 02b0a1e..d5d752f 100644
--- a/PERFORMANCE_OWNERS
+++ b/PERFORMANCE_OWNERS
@@ -7,3 +7,4 @@
jdduke@google.com
shombert@google.com
kevinjeon@google.com
+yforta@google.com
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index cd7e40c..d363e19 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -38,6 +38,7 @@
per-file IGameManager* = file:/GAME_MANAGER_OWNERS
per-file IGameMode* = file:/GAME_MANAGER_OWNERS
per-file BackgroundStartPrivileges.java = file:/BAL_OWNERS
+per-file activity_manager.aconfig = file:/ACTIVITY_MANAGER_OWNERS
# ActivityThread
per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 91cdf8d..1c9be6f 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -76,11 +76,15 @@
* PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION} before querying the service. If the feature is
* absent, {@link Context#getSystemService} may return null.
*/
-@SystemService(Context.VCN_MANAGEMENT_SERVICE)
+@SystemService(VcnManager.VCN_MANAGEMENT_SERVICE_STRING)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
+ // TODO: b/366598445: Expose and use Context.VCN_MANAGEMENT_SERVICE
+ /** @hide */
+ public static final String VCN_MANAGEMENT_SERVICE_STRING = "vcn_management";
+
/**
* Key for WiFi entry RSSI thresholds
*
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index c38ee08..325d274 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -10,3 +10,4 @@
per-file FileIntegrityManager.java = file:platform/system/security:/fsverity/OWNERS
per-file IFileIntegrityService.aidl = file:platform/system/security:/fsverity/OWNERS
per-file *.aconfig = victorhsieh@google.com,eranm@google.com
+per-file *responsible_apis_flags.aconfig = haok@google.com
\ No newline at end of file
diff --git a/core/java/android/security/forensic/OWNERS b/core/java/android/security/forensic/OWNERS
new file mode 100644
index 0000000..d9e82a6
--- /dev/null
+++ b/core/java/android/security/forensic/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 1630302
+
+lizprucka@google.com
+mteffeteller@google.com
+myriamleggieri@google.com
+rmneal@google.com
+wenhaowang@google.com
+willcoster@google.com
diff --git a/core/java/com/android/internal/os/anr/OWNERS b/core/java/com/android/internal/os/anr/OWNERS
index 9816752..1ad642f 100644
--- a/core/java/com/android/internal/os/anr/OWNERS
+++ b/core/java/com/android/internal/os/anr/OWNERS
@@ -1,3 +1,2 @@
benmiles@google.com
-gaillard@google.com
mohamadmahmoud@google.com
\ No newline at end of file
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index c0fe098..af10623 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -116,3 +116,6 @@
# IF Tools
per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/OWNERS
+
+# ApplicationSharedMemory
+per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index 5a444bb..c364451 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -83,7 +83,7 @@
return 0;
}
- ResXMLParser* st = new ResXMLParser(*osb);
+ ResXMLParser* st = new(std::nothrow) ResXMLParser(*osb);
if (st == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return 0;
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 9603c0a..d17a9b6 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -60,7 +60,7 @@
method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback);
- method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOn(int);
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOnMode(int);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback);
field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int DISABLE = 0; // 0x0
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index 2804546..951702c 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -560,13 +560,13 @@
public @interface TagIntentAppPreferenceResult {}
/**
- * Mode Type for {@link NfcOemExtension#setControllerAlwaysOn(int)}.
+ * Mode Type for {@link NfcOemExtension#setControllerAlwaysOnMode(int)}.
* @hide
*/
public static final int CONTROLLER_ALWAYS_ON_MODE_DEFAULT = 1;
/**
- * Mode Type for {@link NfcOemExtension#setControllerAlwaysOn(int)}.
+ * Mode Type for {@link NfcOemExtension#setControllerAlwaysOnMode(int)}.
* @hide
*/
public static final int CONTROLLER_ALWAYS_ON_DISABLE = 0;
@@ -2323,7 +2323,7 @@
* <p>This API is for the NFCC internal state management. It allows to discriminate
* the controller function from the NFC function by keeping the NFC controller on without
* any NFC RF enabled if necessary.
- * <p>This call is asynchronous. Register a listener {@link #ControllerAlwaysOnListener}
+ * <p>This call is asynchronous. Register a listener {@link ControllerAlwaysOnListener}
* by {@link #registerControllerAlwaysOnListener} to find out when the operation is
* complete.
* <p>If this returns true, then either NFCC always on state has been set based on the value,
@@ -2337,7 +2337,7 @@
* FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
* FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
* are unavailable
- * @return true if feature is supported by the device and operation has bee initiated,
+ * @return true if feature is supported by the device and operation has been initiated,
* false if the feature is not supported by the device.
* @hide
*/
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 45038d4..011c60b 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -70,7 +70,7 @@
private boolean mRfDiscoveryStarted = false;
/**
- * Mode Type for {@link #setControllerAlwaysOn(int)}.
+ * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
* Enables the controller in default mode when NFC is disabled (existing API behavior).
* works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}.
* @hide
@@ -80,7 +80,7 @@
public static final int ENABLE_DEFAULT = NfcAdapter.CONTROLLER_ALWAYS_ON_MODE_DEFAULT;
/**
- * Mode Type for {@link #setControllerAlwaysOn(int)}.
+ * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
* Enables the controller in transparent mode when NFC is disabled.
* @hide
*/
@@ -89,7 +89,7 @@
public static final int ENABLE_TRANSPARENT = 2;
/**
- * Mode Type for {@link #setControllerAlwaysOn(int)}.
+ * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
* Enables the controller and initializes and enables the EE subsystem when NFC is disabled.
* @hide
*/
@@ -98,7 +98,7 @@
public static final int ENABLE_EE = 3;
/**
- * Mode Type for {@link #setControllerAlwaysOn(int)}.
+ * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
* Disable the Controller Always On Mode.
* works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}.
* @hide
@@ -108,7 +108,7 @@
public static final int DISABLE = NfcAdapter.CONTROLLER_ALWAYS_ON_DISABLE;
/**
- * Possible controller modes for {@link #setControllerAlwaysOn(int)}.
+ * Possible controller modes for {@link #setControllerAlwaysOnMode(int)}.
*
* @hide
*/
@@ -449,6 +449,9 @@
* <p>This call is asynchronous, register listener {@link NfcAdapter.ControllerAlwaysOnListener}
* by {@link NfcAdapter#registerControllerAlwaysOnListener} to find out when the operation is
* complete.
+ * <p> Note: This adds more always on modes on top of existing
+ * {@link NfcAdapter#setControllerAlwaysOn(boolean)} API which can be used to set the NFCC in
+ * only {@link #ENABLE_DEFAULT} and {@link #DISABLE} modes.
* @param mode one of {@link ControllerMode} modes
* @throws UnsupportedOperationException if
* <li> if FEATURE_NFC, FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
@@ -456,11 +459,12 @@
* are unavailable </li>
* <li> if the feature is unavailable @see NfcAdapter#isNfcControllerAlwaysOnSupported() </li>
* @hide
+ * @see NfcAdapter#setControllerAlwaysOn(boolean)
*/
@SystemApi
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
- public void setControllerAlwaysOn(@ControllerMode int mode) {
+ public void setControllerAlwaysOnMode(@ControllerMode int mode) {
if (!NfcAdapter.sHasNfcFeature && !NfcAdapter.sHasCeFeature) {
throw new UnsupportedOperationException();
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f696036..f4451de 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3265,6 +3265,24 @@
if (forceNotify || success) {
notifyForSettingsChange(key, name);
+
+ // If this is an aconfig flag, it will be written as a staged flag.
+ // Notify that its staged flag value will be updated.
+ if (Flags.notifyIndividualAconfigSyspropChanged() && type == SETTINGS_TYPE_CONFIG) {
+ int slashIndex = name.indexOf('/');
+ boolean validSlashIndex = slashIndex != -1
+ && slashIndex != 0
+ && slashIndex != name.length();
+ if (validSlashIndex) {
+ String namespace = name.substring(0, slashIndex);
+ String flagName = name.substring(slashIndex + 1);
+ if (settingsState.getAconfigDefaultFlags().containsKey(flagName)) {
+ String stagedName = "staged/" + namespace + "*" + flagName;
+ notifyForSettingsChange(key, stagedName);
+ }
+ }
+ }
+
if (wasUnsetNonPredefinedSetting) {
// Increment the generation number for all non-predefined, unset settings,
// because a new non-predefined setting has been inserted
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
index 4f5955b..27335ed 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
+++ b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig
@@ -28,6 +28,17 @@
}
flag {
+ name: "notify_individual_aconfig_sysprop_changed"
+ namespace: "core_experiments_team_internal"
+ description: "When enabled, propagate individual aconfig sys props on flag stage."
+ bug: "331963764"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "load_apex_aconfig_protobufs"
namespace: "core_experiments_team_internal"
description: "When enabled, loads aconfig default values in apex flag protobufs into DeviceConfig on boot."
diff --git a/packages/SystemUI/TEST_OWNERS b/packages/SystemUI/TEST_OWNERS
new file mode 100644
index 0000000..eadc86e
--- /dev/null
+++ b/packages/SystemUI/TEST_OWNERS
@@ -0,0 +1,5 @@
+# Test maintainers for system UI
+# usernames listed here are able to approve changes to sysui unit tests,
+# for restructuring and test maintenance only
+
+saff@google.com
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS
index cd04e82..d3eec97 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS
@@ -1,3 +1,4 @@
set noparent
include /packages/SystemUI/src/com/android/systemui/qs/OWNERS
+include /packages/SystemUI/TEST_OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
index 5420c37..58ae2b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
@@ -3,3 +3,4 @@
# Bug component: 879035
include /services/core/java/com/android/server/biometrics/OWNERS
beverlyt@google.com
+include /packages/SystemUI/TEST_OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS
index 1c52b8d..48a20dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OWNERS
@@ -1,3 +1,4 @@
set noparent
include /packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
+include /packages/SystemUI/TEST_OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS
index 7f5384d..1da7007 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS
@@ -1,3 +1,4 @@
set noparent
-include /packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
\ No newline at end of file
+include /packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
+include /packages/SystemUI/TEST_OWNERS
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c2cb5e9..0daeaf4 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -659,7 +659,7 @@
@Override
public void run() {
try {
- RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
+ RecoverySystem.rebootPromptAndWipeUserData(context, TAG + "," + failedPackage);
} catch (Throwable t) {
logRescueException(level, failedPackage, t);
}
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index d19899f..12e8c57 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -178,9 +178,10 @@
public static final boolean VDBG = false; // STOPSHIP: if true
+ // The system path is copied from Environment.getDataSystemDirectory
@VisibleForTesting(visibility = Visibility.PRIVATE)
static final String VCN_CONFIG_FILE =
- new File(Environment.getDataSystemDirectory(), "vcn/configs.xml").getPath();
+ new File(Environment.getDataDirectory(), "system/vcn/configs.xml").getPath();
// TODO(b/176956496): Directly use CarrierServiceBindHelper.UNBIND_DELAY_MILLIS
@VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -379,10 +380,12 @@
}
/** Gets transports that need to be marked as restricted by the VCN from CarrierConfig */
+ // TODO: b/262269892 This method was created to perform experiments before the relevant API
+ // was exposed. Now it is obsolete and should be removed.
@VisibleForTesting(visibility = Visibility.PRIVATE)
public Set<Integer> getRestrictedTransportsFromCarrierConfig(
ParcelUuid subGrp, TelephonySubscriptionSnapshot lastSnapshot) {
- if (!Build.IS_ENG && !Build.IS_USERDEBUG) {
+ if (!Build.isDebuggable()) {
return RESTRICTED_TRANSPORTS_DEFAULT;
}
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index b271d7e..ab69cd1 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -118,8 +118,11 @@
if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LINEOUT_INSERT) == 1) {
switchValues |= SW_LINEOUT_INSERT_BIT;
}
- notifyWiredAccessoryChanged(0, switchValues,
- SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT);
+ notifyWiredAccessoryChanged(
+ 0,
+ switchValues,
+ SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT,
+ true /*isSynchronous*/);
}
@@ -135,7 +138,13 @@
}
@Override
- public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
+ public void notifyWiredAccessoryChanged(
+ long whenNanos, int switchValues, int switchMask) {
+ notifyWiredAccessoryChanged(whenNanos, switchValues, switchMask, false /*isSynchronous*/);
+ }
+
+ public void notifyWiredAccessoryChanged(
+ long whenNanos, int switchValues, int switchMask, boolean isSynchronous) {
if (LOG) {
Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
+ " bits=" + switchCodeToString(switchValues, switchMask)
@@ -172,8 +181,10 @@
break;
}
- updateLocked(NAME_H2W,
- (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
+ updateLocked(
+ NAME_H2W,
+ (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset,
+ isSynchronous);
}
}
@@ -195,8 +206,9 @@
*
* @param newName One of the NAME_xxx variables defined above.
* @param newState 0 or one of the BIT_xxx variables defined above.
+ * @param isSynchronous boolean to determine whether should happen sync or async
*/
- private void updateLocked(String newName, int newState) {
+ private void updateLocked(String newName, int newState, boolean isSynchronous) {
// Retain only relevant bits
int headsetState = newState & SUPPORTED_HEADSETS;
int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
@@ -234,12 +246,15 @@
return;
}
- mWakeLock.acquire();
-
- Log.i(TAG, "MSG_NEW_DEVICE_STATE");
- Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
- mHeadsetState, "");
- mHandler.sendMessage(msg);
+ if (isSynchronous) {
+ setDevicesState(headsetState, mHeadsetState, "");
+ } else {
+ mWakeLock.acquire();
+ Log.i(TAG, "MSG_NEW_DEVICE_STATE");
+ Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
+ mHeadsetState, "");
+ mHandler.sendMessage(msg);
+ }
mHeadsetState = headsetState;
}
@@ -439,7 +454,10 @@
for (int i = 0; i < mUEventInfo.size(); ++i) {
UEventInfo uei = mUEventInfo.get(i);
if (devPath.equals(uei.getDevPath())) {
- updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
+ updateLocked(
+ name,
+ uei.computeNewHeadsetState(mHeadsetState, state),
+ false /*isSynchronous*/);
return;
}
}
@@ -550,7 +568,10 @@
synchronized (mLock) {
int mask = maskAndState.first;
int state = maskAndState.second;
- updateLocked(name, mHeadsetState & ~(mask & ~state) | (mask & state));
+ updateLocked(
+ name,
+ mHeadsetState & ~(mask & ~state) | (mask & state),
+ false /*isSynchronous*/);
return;
}
}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 1bcf825..2a30ad0 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -19,12 +19,12 @@
per-file AppFGSTracker.java = file:/ACTIVITY_MANAGER_OWNERS
per-file FgsTempAllowList.java = file:/ACTIVITY_MANAGER_OWNERS
per-file HostingRecord.java = file:/ACTIVITY_MANAGER_OWNERS
-
-# Windows & Activities
-ogunwale@google.com
+per-file App*ExitInfo* = file:/ACTIVITY_MANAGER_OWNERS
+per-file appexitinfo.proto = file:/ACTIVITY_MANAGER_OWNERS
+per-file App*StartInfo* = file:/PERFORMANCE_OWNERS
+per-file appstartinfo.proto = file:/PERFORMANCE_OWNERS
# Permissions & Packages
-patb@google.com
per-file AccessCheckDelegateHelper.java = file:/core/java/android/permission/OWNERS
# Battery Stats
@@ -66,6 +66,6 @@
narayan@google.com #{LAST_RESORT_SUGGESTION}
# Default
+yamasani@google.com
hackbod@google.com #{LAST_RESORT_SUGGESTION}
-omakoto@google.com #{LAST_RESORT_SUGGESTION}
-yamasani@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
+omakoto@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 550d878..428bf13 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -332,8 +332,8 @@
Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid);
}
- synchronized (mDeviceStateLock) {
- if (device == null) {
+ if (device == null) {
+ synchronized (mDeviceStateLock) {
CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
if (client == null) {
return false;
@@ -1483,38 +1483,6 @@
sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
}
- /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy,
- List<AudioDeviceAttributes> devices)
- {
- sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices);
- }
-
- /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) {
- sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy);
- }
-
- /*package*/ void postSaveSetDeviceAsNonDefaultForStrategy(
- int strategy, AudioDeviceAttributes device) {
- sendILMsgNoDelay(MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
- }
-
- /*package*/ void postSaveRemoveDeviceAsNonDefaultForStrategy(
- int strategy, AudioDeviceAttributes device) {
- sendILMsgNoDelay(
- MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
- }
-
- /*package*/ void postSaveSetPreferredDevicesForCapturePreset(
- int capturePreset, List<AudioDeviceAttributes> devices) {
- sendILMsgNoDelay(
- MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices);
- }
-
- /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
- sendIMsgNoDelay(
- MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset);
- }
-
/*package*/ void postUpdateCommunicationRouteClient(
boolean wasBtScoRequested, String eventSource) {
sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE,
@@ -2025,40 +1993,9 @@
mDeviceInventory.setBluetoothActiveDevice(btInfo);
}
} break;
- case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: {
- final int strategy = msg.arg1;
- final List<AudioDeviceAttributes> devices =
- (List<AudioDeviceAttributes>) msg.obj;
- mDeviceInventory.onSaveSetPreferredDevices(strategy, devices);
- } break;
- case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
- final int strategy = msg.arg1;
- mDeviceInventory.onSaveRemovePreferredDevices(strategy);
- } break;
- case MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY: {
- final int strategy = msg.arg1;
- final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
- mDeviceInventory.onSaveSetDeviceAsNonDefault(strategy, device);
- } break;
- case MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY: {
- final int strategy = msg.arg1;
- final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
- mDeviceInventory.onSaveRemoveDeviceAsNonDefault(strategy, device);
- } break;
case MSG_CHECK_MUTE_MUSIC:
checkMessagesMuteMusic(0);
break;
- case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: {
- final int capturePreset = msg.arg1;
- final List<AudioDeviceAttributes> devices =
- (List<AudioDeviceAttributes>) msg.obj;
- mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset(
- capturePreset, devices);
- } break;
- case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: {
- final int capturePreset = msg.arg1;
- mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
- } break;
case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: {
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
@@ -2151,16 +2088,10 @@
// process external command to (dis)connect a hearing aid device
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
- private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32;
- private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33;
-
private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34;
private static final int MSG_CHECK_MUTE_MUSIC = 35;
private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36;
- private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37;
- private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
-
private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42;
private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43;
@@ -2169,8 +2100,6 @@
// process set volume for Le Audio, obj is BleVolumeInfo
private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
- private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
- private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
private static final int MSG_IIL_BTLEAUDIO_TIMEOUT = 49;
private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index ea3d821..6fb5598 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -536,14 +536,17 @@
@GuardedBy("mDevicesLock")
private final ArrayMap<Integer, String> mApmConnectedDevices = new ArrayMap<>();
+ @GuardedBy("mDevicesLock")
// List of preferred devices for strategies
private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevices =
new ArrayMap<>();
+ @GuardedBy("mDevicesLock")
// List of non-default devices for strategies
private final ArrayMap<Integer, List<AudioDeviceAttributes>> mNonDefaultDevices =
new ArrayMap<>();
+ @GuardedBy("mDevicesLock")
// List of preferred devices of capture preset
private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevicesForCapturePreset =
new ArrayMap<>();
@@ -781,24 +784,18 @@
synchronized (mDevicesLock) {
mAppliedStrategyRoles.clear();
mAppliedPresetRoles.clear();
- }
- synchronized (mPreferredDevices) {
mPreferredDevices.forEach((strategy, devices) -> {
setPreferredDevicesForStrategy(strategy, devices);
});
- }
- synchronized (mNonDefaultDevices) {
mNonDefaultDevices.forEach((strategy, devices) -> {
addDevicesRoleForStrategy(strategy, AudioSystem.DEVICE_ROLE_DISABLED,
devices, false /* internal */);
});
- }
- synchronized (mPreferredDevicesForCapturePreset) {
mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
setDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
});
- }
+ }
}
/** only public for mocking/spying, do not call outside of AudioService */
@@ -1198,7 +1195,8 @@
mmi.record();
}
- /*package*/ void onSaveSetPreferredDevices(int strategy,
+ @GuardedBy("mDevicesLock")
+ private void saveSetPreferredDevices(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
mPreferredDevices.put(strategy, devices);
List<AudioDeviceAttributes> nonDefaultDevices = mNonDefaultDevices.get(strategy);
@@ -1216,12 +1214,14 @@
dispatchPreferredDevice(strategy, devices);
}
- /*package*/ void onSaveRemovePreferredDevices(int strategy) {
+ @GuardedBy("mDevicesLock")
+ private void saveRemovePreferredDevices(int strategy) {
mPreferredDevices.remove(strategy);
dispatchPreferredDevice(strategy, new ArrayList<AudioDeviceAttributes>());
}
- /*package*/ void onSaveSetDeviceAsNonDefault(int strategy,
+ @GuardedBy("mDevicesLock")
+ private void saveSetDeviceAsNonDefault(int strategy,
@NonNull AudioDeviceAttributes device) {
List<AudioDeviceAttributes> nonDefaultDevices = mNonDefaultDevices.get(strategy);
if (nonDefaultDevices == null) {
@@ -1245,7 +1245,8 @@
}
}
- /*package*/ void onSaveRemoveDeviceAsNonDefault(int strategy,
+ @GuardedBy("mDevicesLock")
+ private void saveRemoveDeviceAsNonDefault(int strategy,
@NonNull AudioDeviceAttributes device) {
List<AudioDeviceAttributes> nonDefaultDevices = mNonDefaultDevices.get(strategy);
if (nonDefaultDevices != null) {
@@ -1255,14 +1256,16 @@
}
}
- /*package*/ void onSaveSetPreferredDevicesForCapturePreset(
+ @GuardedBy("mDevicesLock")
+ private void saveSetPreferredDevicesForCapturePreset(
int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
mPreferredDevicesForCapturePreset.put(capturePreset, devices);
dispatchDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
}
- /*package*/ void onSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
+ @GuardedBy("mDevicesLock")
+ private void saveClearPreferredDevicesForCapturePreset(int capturePreset) {
mPreferredDevicesForCapturePreset.remove(capturePreset);
dispatchDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED,
@@ -1274,21 +1277,22 @@
/*package*/ int setPreferredDevicesForStrategyAndSave(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- final int status = setPreferredDevicesForStrategy(strategy, devices);
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForStrategy(strategy, devices);
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ final int status = setPreferredDevicesForStrategy(strategy, devices);
+ if (status == AudioSystem.SUCCESS) {
+ saveSetPreferredDevices(strategy, devices);
+ }
+ return status;
+ }
}
- return status;
}
// Only used for external requests coming from an API
/*package*/ int setPreferredDevicesForStrategy(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = setDevicesRoleForStrategy(
- strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices, false /* internal */);
- }
- return status;
+
+ return setDevicesRoleForStrategy(
+ strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices, false /* internal */);
}
// Only used for internal requests
/*package*/ int setPreferredDevicesForStrategyInt(int strategy,
@@ -1299,21 +1303,21 @@
}
/*package*/ int removePreferredDevicesForStrategyAndSave(int strategy) {
- final int status = removePreferredDevicesForStrategy(strategy);
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveRemovePreferredDevicesForStrategy(strategy);
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ final int status = removePreferredDevicesForStrategy(strategy);
+ if (status == AudioSystem.SUCCESS) {
+ saveRemovePreferredDevices(strategy);
+ }
+ return status;
+ }
}
- return status;
}
// Only used for external requests coming from an API
/*package*/ int removePreferredDevicesForStrategy(int strategy) {
- int status = AudioSystem.ERROR;
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = clearDevicesRoleForStrategy(
+ return clearDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, false /*internal */);
- }
- return status;
}
// Only used for internal requests
/*package*/ int removePreferredDevicesForStrategyInt(int strategy) {
@@ -1324,16 +1328,17 @@
/*package*/ int setDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- List<AudioDeviceAttributes> devices = new ArrayList<>();
- devices.add(device);
- status = addDevicesRoleForStrategy(
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ List<AudioDeviceAttributes> devices = new ArrayList<>();
+ devices.add(device);
+ status = addDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices, false /* internal */);
- }
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetDeviceAsNonDefaultForStrategy(strategy, device);
+ if (status == AudioSystem.SUCCESS) {
+ saveSetDeviceAsNonDefault(strategy, device);
+ }
+ }
}
return status;
}
@@ -1341,16 +1346,17 @@
/*package*/ int removeDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- List<AudioDeviceAttributes> devices = new ArrayList<>();
- devices.add(device);
- status = removeDevicesRoleForStrategy(
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ List<AudioDeviceAttributes> devices = new ArrayList<>();
+ devices.add(device);
+ status = removeDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices, false /* internal */);
- }
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveRemoveDeviceAsNonDefaultForStrategy(strategy, device);
+ if (status == AudioSystem.SUCCESS) {
+ saveRemoveDeviceAsNonDefault(strategy, device);
+ }
+ }
}
return status;
}
@@ -1378,41 +1384,40 @@
/*package*/ int setPreferredDevicesForCapturePresetAndSave(
int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
- final int status = setPreferredDevicesForCapturePreset(capturePreset, devices);
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ final int status = setPreferredDevicesForCapturePreset(capturePreset, devices);
+ if (status == AudioSystem.SUCCESS) {
+ saveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ }
+ return status;
+ }
}
- return status;
}
// Only used for external requests coming from an API
private int setPreferredDevicesForCapturePreset(
int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = setDevicesRoleForCapturePreset(
+ return setDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
- }
- return status;
}
/*package*/ int clearPreferredDevicesForCapturePresetAndSave(int capturePreset) {
- final int status = clearPreferredDevicesForCapturePreset(capturePreset);
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
+ synchronized(mDevicesLock){
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ final int status = clearPreferredDevicesForCapturePreset(capturePreset);
+ if (status == AudioSystem.SUCCESS) {
+ saveClearPreferredDevicesForCapturePreset(capturePreset);
+ }
+ return status;
+ }
}
- return status;
}
// Only used for external requests coming from an API
private int clearPreferredDevicesForCapturePreset(int capturePreset) {
- int status = AudioSystem.ERROR;
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = clearDevicesRoleForCapturePreset(
+ return clearDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED);
- }
- return status;
}
// Only used for internal requests
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index a346a9b..f42bdee 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -603,7 +603,11 @@
break;
case BluetoothProfile.LE_AUDIO:
if (mLeAudio != null && mLeAudioCallback != null) {
- mLeAudio.unregisterCallback(mLeAudioCallback);
+ try {
+ mLeAudio.unregisterCallback(mLeAudioCallback);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while unregistering callback for LE audio", e);
+ }
}
mLeAudio = null;
mLeAudioCallback = null;
@@ -680,12 +684,21 @@
return;
}
if (mLeAudio != null && mLeAudioCallback != null) {
- mLeAudio.unregisterCallback(mLeAudioCallback);
+ try {
+ mLeAudio.unregisterCallback(mLeAudioCallback);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while unregistering callback for LE audio", e);
+ }
}
mLeAudio = (BluetoothLeAudio) proxy;
mLeAudioCallback = new MyLeAudioCallback();
- mLeAudio.registerCallback(
- mContext.getMainExecutor(), mLeAudioCallback);
+ try{
+ mLeAudio.registerCallback(
+ mContext.getMainExecutor(), mLeAudioCallback);
+ } catch (Exception e) {
+ mLeAudioCallback = null;
+ Log.e(TAG, "Exception while registering callback for LE audio", e);
+ }
break;
case BluetoothProfile.A2DP_SINK:
case BluetoothProfile.LE_AUDIO_BROADCAST:
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 978a8c0..2000eb7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -249,6 +249,7 @@
.setDisplayName(HdmiUtils.getDefaultDeviceName(source))
.setDeviceType(deviceTypes.get(0))
.setVendorId(Constants.VENDOR_ID_UNKNOWN)
+ .setPortId(mService.getHdmiCecNetwork().physicalAddressToPortId(physicalAddress))
.build();
mService.getHdmiCecNetwork().addCecDevice(newDevice);
}
@@ -1398,6 +1399,7 @@
protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) {
assertRunOnServiceThread();
mService.unregisterTvInputCallback(mTvInputCallback);
+ mTvInputs.clear();
// Remove any repeated working actions.
// HotplugDetectionAction will be reinstated during the wake up process.
// HdmiControlService.onWakeUp() -> initializeLocalDevices() ->
diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
index c5e2bb8..1e35a27 100644
--- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
@@ -170,7 +170,6 @@
static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
public static final int DIGEST_SIZE_BYTES = 32;
- private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
private static final String FLASH_LOCK_LOCKED = "1";
private static final String FLASH_LOCK_UNLOCKED = "0";
@@ -274,7 +273,6 @@
enforceChecksumValidity();
if (mFrpEnforced) {
automaticallyDeactivateFrpIfPossible();
- setOemUnlockEnabledProperty(doGetOemUnlockEnabled());
setOldSettingForBackworkCompatibility(mFrpActive);
} else {
formatIfOemUnlockEnabled();
@@ -302,10 +300,6 @@
}
}
- private void setOemUnlockEnabledProperty(boolean oemUnlockEnabled) {
- setProperty(OEM_UNLOCK_PROP, oemUnlockEnabled ? "1" : "0");
- }
-
@Override
public void onBootPhase(int phase) {
// Wait for initialization in onStart to finish
@@ -341,7 +335,6 @@
formatPartitionLocked(true);
}
}
- setOemUnlockEnabledProperty(enabled);
}
private void enforceOemUnlockReadPermission() {
@@ -808,17 +801,9 @@
channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e);
- return;
- } finally {
- setOemUnlockEnabledProperty(enabled);
}
}
- @VisibleForTesting
- void setProperty(String name, String value) {
- SystemProperties.set(name, value);
- }
-
private boolean doGetOemUnlockEnabled() {
DataInputStream inputStream;
try {
diff --git a/services/core/java/com/android/server/security/forensic/OWNERS b/services/core/java/com/android/server/security/forensic/OWNERS
new file mode 100644
index 0000000..3bc3eb5
--- /dev/null
+++ b/services/core/java/com/android/server/security/forensic/OWNERS
@@ -0,0 +1 @@
+file:platform/frameworks/base:main:/core/java/android/security/forensic/OWNERS
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 5a5f7ef..5bc2c2d 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -86,6 +86,9 @@
private static final int MSG_EVENT_BASE = 0;
private static final int MSG_CMD_BASE = 100;
+ // Copied from Settings.Global.MOBILE_DATA
+ private static final String SETTINGS_GLOBAL_MOBILE_DATA_STRING = "mobile_data";
+
/**
* A carrier app updated the configuration.
*
@@ -219,7 +222,8 @@
mContentResolver = mDeps.newVcnContentResolver(mVcnContext);
mMobileDataSettingsObserver = new VcnMobileDataContentObserver(this /* handler */);
- final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
+ // TODO: b/364740845: Replace it with DataEnabledListener
+ final Uri uri = Settings.Global.getUriFor(SETTINGS_GLOBAL_MOBILE_DATA_STRING);
mContentResolver.registerContentObserver(
uri, true /* notifyForDescendants */, mMobileDataSettingsObserver);
diff --git a/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java b/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java
index f91f77a..cdfc521 100644
--- a/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java
@@ -86,7 +86,6 @@
private File mDataBlockFile;
private File mFrpSecretFile;
private File mFrpSecretTmpFile;
- private String mOemUnlockPropertyValue;
private boolean mIsUpgradingFromPreV = false;
@Mock private UserManager mUserManager;
@@ -105,13 +104,6 @@
}
@Override
- void setProperty(String key, String value) {
- // Override to capture the value instead of actually setting the property.
- assertThat(key).isEqualTo("sys.oem_unlock_allowed");
- mOemUnlockPropertyValue = value;
- }
-
- @Override
boolean isUpgradingFromPreVRelease() {
return mIsUpgradingFromPreV;
}
@@ -598,7 +590,6 @@
mInterface.setOemUnlockEnabled(true);
assertThat(mInterface.getOemUnlockEnabled()).isTrue();
- assertThat(mOemUnlockPropertyValue).isEqualTo("1");
}
@Test
@@ -635,7 +626,6 @@
// The current implementation does not check digest before set or get the oem unlock bit.
tamperWithDigest();
mInterface.setOemUnlockEnabled(true);
- assertThat(mOemUnlockPropertyValue).isEqualTo("1");
tamperWithDigest();
assertThat(mInterface.getOemUnlockEnabled()).isTrue();
}
@@ -676,7 +666,6 @@
mInternalInterface.forceOemUnlockEnabled(true);
- assertThat(mOemUnlockPropertyValue).isEqualTo("1");
assertThat(readBackingFile(mPdbService.getOemUnlockDataOffset(), 1).array())
.isEqualTo(new byte[] { 1 });
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
index 9dac23f..d7004e7 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -1746,10 +1746,6 @@
assertTrue("Tested duration=" + duration4, duration4 < 2000);
// Effect5: played normally after effect4, which may or may not have played.
-
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId5));
- verifyCallbacksTriggered(vibrationId5, Vibration.Status.FINISHED);
-
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
fakeVibrator.getEffectSegments(vibrationId5));
}
diff --git a/tools/systemfeatures/Android.bp b/tools/systemfeatures/Android.bp
index a9e6328..590f719 100644
--- a/tools/systemfeatures/Android.bp
+++ b/tools/systemfeatures/Android.bp
@@ -30,8 +30,8 @@
name: "systemfeatures-gen-tests-srcs",
cmd: "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwNoFeatures --readonly=false > $(location RwNoFeatures.java) && " +
"$(location systemfeatures-gen-tool) com.android.systemfeatures.RoNoFeatures --readonly=true --feature-apis=WATCH > $(location RoNoFeatures.java) && " +
- "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwFeatures --readonly=false --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: > $(location RwFeatures.java) && " +
- "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoFeatures --readonly=true --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: --feature-apis=WATCH,PC > $(location RoFeatures.java)",
+ "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwFeatures --readonly=false --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:UNAVAILABLE --feature=AUTO: > $(location RwFeatures.java) && " +
+ "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoFeatures --readonly=true --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:UNAVAILABLE --feature=AUTO: --feature-apis=WATCH,PC > $(location RoFeatures.java)",
out: [
"RwNoFeatures.java",
"RoNoFeatures.java",
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
index 5df453d..cba521e 100644
--- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
@@ -20,7 +20,10 @@
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeSpec
+import java.util.HashMap
+import java.util.Map
import javax.lang.model.element.Modifier
/*
@@ -31,7 +34,7 @@
*
* <pre>
* <cmd> com.foo.RoSystemFeatures --readonly=true \
- * --feature=WATCH:0 --feature=AUTOMOTIVE: --feature=VULKAN:9348
+ * --feature=WATCH:0 --feature=AUTOMOTIVE: --feature=VULKAN:9348 --feature=PC:UNAVAILABLE
* --feature-apis=WATCH,PC,LEANBACK
* </pre>
*
@@ -43,12 +46,13 @@
* @AssumeTrueForR8
* public static boolean hasFeatureWatch(Context context);
* @AssumeFalseForR8
- * public static boolean hasFeatureAutomotive(Context context);
+ * public static boolean hasFeaturePc(Context context);
* @AssumeTrueForR8
* public static boolean hasFeatureVulkan(Context context);
- * public static boolean hasFeaturePc(Context context);
+ * public static boolean hasFeatureAutomotive(Context context);
* public static boolean hasFeatureLeanback(Context context);
* public static Boolean maybeHasFeature(String feature, int version);
+ * public static ArrayMap<String, FeatureInfo> getCompileTimeAvailableFeatures();
* }
* </pre>
*/
@@ -58,6 +62,7 @@
private const val READONLY_ARG = "--readonly="
private val PACKAGEMANAGER_CLASS = ClassName.get("android.content.pm", "PackageManager")
private val CONTEXT_CLASS = ClassName.get("android.content", "Context")
+ private val FEATUREINFO_CLASS = ClassName.get("android.content.pm", "FeatureInfo")
private val ASSUME_TRUE_CLASS =
ClassName.get("com.android.aconfig.annotations", "AssumeTrueForR8")
private val ASSUME_FALSE_CLASS =
@@ -67,7 +72,10 @@
println("Usage: SystemFeaturesGenerator <outputClassName> [options]")
println(" Options:")
println(" --readonly=true|false Whether to encode features as build-time constants")
- println(" --feature=\$NAME:\$VER A feature+version pair (blank version == disabled)")
+ println(" --feature=\$NAME:\$VER A feature+version pair, where \$VER can be:")
+ println(" * blank/empty == undefined (variable API)")
+ println(" * valid int == enabled (constant API)")
+ println(" * UNAVAILABLE == disabled (constant API)")
println(" This will always generate associated query APIs,")
println(" adding to or replacing those from `--feature-apis=`.")
println(" --feature-apis=\$NAME_1,\$NAME_2")
@@ -89,7 +97,7 @@
var readonly = false
var outputClassName: ClassName? = null
- val featureArgs = mutableListOf<FeatureArg>()
+ val featureArgs = mutableListOf<FeatureInfo>()
// We could just as easily hardcode this list, as the static API surface should change
// somewhat infrequently, but this decouples the codegen from the framework completely.
val featureApiArgs = mutableSetOf<String>()
@@ -122,7 +130,7 @@
featureArgs.associateByTo(
features,
{ it.name },
- { FeatureInfo(it.name, it.version, readonly) },
+ { FeatureInfo(it.name, it.version, it.readonly && readonly) },
)
outputClassName
@@ -139,6 +147,7 @@
addFeatureMethodsToClass(classBuilder, features.values)
addMaybeFeatureMethodToClass(classBuilder, features.values)
+ addGetFeaturesMethodToClass(classBuilder, features.values)
// TODO(b/203143243): Add validation of build vs runtime values to ensure consistency.
JavaFile.builder(outputClassName.packageName(), classBuilder.build())
@@ -154,13 +163,17 @@
* Parses a feature argument of the form "--feature=$NAME:$VER", where "$VER" is optional.
* * "--feature=WATCH:0" -> Feature enabled w/ version 0 (default version when enabled)
* * "--feature=WATCH:7" -> Feature enabled w/ version 7
- * * "--feature=WATCH:" -> Feature disabled
+ * * "--feature=WATCH:" -> Feature status undefined, runtime API generated
+ * * "--feature=WATCH:UNAVAILABLE" -> Feature disabled
*/
- private fun parseFeatureArg(arg: String): FeatureArg {
+ private fun parseFeatureArg(arg: String): FeatureInfo {
val featureArgs = arg.substring(FEATURE_ARG.length).split(":")
val name = parseFeatureName(featureArgs[0])
- val version = featureArgs.getOrNull(1)?.toIntOrNull()
- return FeatureArg(name, version)
+ return when (featureArgs.getOrNull(1)) {
+ null, "" -> FeatureInfo(name, null, readonly = false)
+ "UNAVAILABLE" -> FeatureInfo(name, null, readonly = true)
+ else -> FeatureInfo(name, featureArgs[1].toIntOrNull(), readonly = true)
+ }
}
private fun parseFeatureName(name: String): String =
@@ -218,7 +231,7 @@
/*
* Adds a generic query method to the class with the form: {@code public static boolean
* maybeHasFeature(String featureName, int version)}, returning null if the feature version is
- * undefined or not readonly.
+ * undefined or not (compile-time) readonly.
*
* This method is useful for internal usage within the framework, e.g., from the implementation
* of {@link android.content.pm.PackageManager#hasSystemFeature(Context)}, when we may only
@@ -267,7 +280,41 @@
builder.addMethod(methodBuilder.build())
}
- private data class FeatureArg(val name: String, val version: Int?)
+ /*
+ * Adds a method to get all compile-time enabled features.
+ *
+ * This method is useful for internal usage within the framework to augment
+ * any system features that are parsed from the various partitions.
+ */
+ private fun addGetFeaturesMethodToClass(
+ builder: TypeSpec.Builder,
+ features: Collection<FeatureInfo>,
+ ) {
+ val methodBuilder =
+ MethodSpec.methodBuilder("getCompileTimeAvailableFeatures")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addAnnotation(ClassName.get("android.annotation", "NonNull"))
+ .addJavadoc("Gets features marked as available at compile-time, keyed by name." +
+ "\n\n@hide")
+ .returns(ParameterizedTypeName.get(
+ ClassName.get(Map::class.java),
+ ClassName.get(String::class.java),
+ FEATUREINFO_CLASS))
+
+ val availableFeatures = features.filter { it.readonly && it.version != null }
+ methodBuilder.addStatement("Map<String, FeatureInfo> features = new \$T<>(\$L)",
+ HashMap::class.java, availableFeatures.size)
+ if (!availableFeatures.isEmpty()) {
+ methodBuilder.addStatement("FeatureInfo fi = new FeatureInfo()")
+ }
+ for (feature in availableFeatures) {
+ methodBuilder.addStatement("fi.name = \$T.\$N", PACKAGEMANAGER_CLASS, feature.name)
+ methodBuilder.addStatement("fi.version = \$L", feature.version)
+ methodBuilder.addStatement("features.put(fi.name, new FeatureInfo(fi))")
+ }
+ methodBuilder.addStatement("return features")
+ builder.addMethod(methodBuilder.build())
+ }
private data class FeatureInfo(val name: String, val version: Int?, val readonly: Boolean)
}
diff --git a/tools/systemfeatures/tests/golden/RoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
index 724639b..edbfc42 100644
--- a/tools/systemfeatures/tests/golden/RoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
@@ -3,16 +3,20 @@
// --readonly=true \
// --feature=WATCH:1 \
// --feature=WIFI:0 \
-// --feature=VULKAN:-1 \
+// --feature=VULKAN:UNAVAILABLE \
// --feature=AUTO: \
// --feature-apis=WATCH,PC
package com.android.systemfeatures;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import com.android.aconfig.annotations.AssumeFalseForR8;
import com.android.aconfig.annotations.AssumeTrueForR8;
+import java.util.HashMap;
+import java.util.Map;
/**
* @hide
@@ -62,9 +66,8 @@
*
* @hide
*/
- @AssumeFalseForR8
public static boolean hasFeatureAuto(Context context) {
- return false;
+ return hasFeatureFallback(context, PackageManager.FEATURE_AUTO);
}
private static boolean hasFeatureFallback(Context context, String featureName) {
@@ -79,10 +82,27 @@
switch (featureName) {
case PackageManager.FEATURE_WATCH: return 1 >= version;
case PackageManager.FEATURE_WIFI: return 0 >= version;
- case PackageManager.FEATURE_VULKAN: return -1 >= version;
- case PackageManager.FEATURE_AUTO: return false;
+ case PackageManager.FEATURE_VULKAN: return false;
default: break;
}
return null;
}
+
+ /**
+ * Gets features marked as available at compile-time, keyed by name.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+ Map<String, FeatureInfo> features = new HashMap<>(2);
+ FeatureInfo fi = new FeatureInfo();
+ fi.name = PackageManager.FEATURE_WATCH;
+ fi.version = 1;
+ features.put(fi.name, new FeatureInfo(fi));
+ fi.name = PackageManager.FEATURE_WIFI;
+ fi.version = 0;
+ features.put(fi.name, new FeatureInfo(fi));
+ return features;
+ }
}
diff --git a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
index 59c5b4e..bf7a006 100644
--- a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
@@ -4,9 +4,13 @@
// --feature-apis=WATCH
package com.android.systemfeatures;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
+import java.util.HashMap;
+import java.util.Map;
/**
* @hide
@@ -32,4 +36,15 @@
public static Boolean maybeHasFeature(String featureName, int version) {
return null;
}
+
+ /**
+ * Gets features marked as available at compile-time, keyed by name.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+ Map<String, FeatureInfo> features = new HashMap<>(0);
+ return features;
+ }
}
diff --git a/tools/systemfeatures/tests/golden/RwFeatures.java.gen b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
index 6f89759..b20b228 100644
--- a/tools/systemfeatures/tests/golden/RwFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
@@ -3,13 +3,17 @@
// --readonly=false \
// --feature=WATCH:1 \
// --feature=WIFI:0 \
-// --feature=VULKAN:-1 \
+// --feature=VULKAN:UNAVAILABLE \
// --feature=AUTO:
package com.android.systemfeatures;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
+import java.util.HashMap;
+import java.util.Map;
/**
* @hide
@@ -62,4 +66,15 @@
public static Boolean maybeHasFeature(String featureName, int version) {
return null;
}
+
+ /**
+ * Gets features marked as available at compile-time, keyed by name.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+ Map<String, FeatureInfo> features = new HashMap<>(0);
+ return features;
+ }
}
diff --git a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
index 2111d56..d91f5b6 100644
--- a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
@@ -3,8 +3,12 @@
// --readonly=false
package com.android.systemfeatures;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.FeatureInfo;
+import java.util.HashMap;
+import java.util.Map;
/**
* @hide
@@ -21,4 +25,15 @@
public static Boolean maybeHasFeature(String featureName, int version) {
return null;
}
+
+ /**
+ * Gets features marked as available at compile-time, keyed by name.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+ Map<String, FeatureInfo> features = new HashMap<>(0);
+ return features;
+ }
}
diff --git a/tools/systemfeatures/tests/src/FeatureInfo.java b/tools/systemfeatures/tests/src/FeatureInfo.java
new file mode 100644
index 0000000..9d57edc
--- /dev/null
+++ b/tools/systemfeatures/tests/src/FeatureInfo.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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;
+
+/** Stub for testing */
+public final class FeatureInfo {
+ public String name;
+ public int version;
+
+ public FeatureInfo() {}
+
+ public FeatureInfo(FeatureInfo orig) {
+ name = orig.name;
+ version = orig.version;
+ }
+}
diff --git a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
index 6dfd244..39f8fc4 100644
--- a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
+++ b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import org.junit.Before;
@@ -36,6 +37,8 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.Map;
+
@RunWith(JUnit4.class)
public class SystemFeaturesGeneratorTest {
@@ -57,6 +60,7 @@
assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
assertThat(RwNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+ assertThat(RwNoFeatures.getCompileTimeAvailableFeatures()).isEmpty();
}
@Test
@@ -68,6 +72,7 @@
assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
assertThat(RoNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+ assertThat(RoNoFeatures.getCompileTimeAvailableFeatures()).isEmpty();
// Also ensure we fall back to the PackageManager for feature APIs without an accompanying
// versioned feature definition.
@@ -101,6 +106,7 @@
assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
assertThat(RwFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+ assertThat(RwFeatures.getCompileTimeAvailableFeatures()).isEmpty();
}
@Test
@@ -110,10 +116,13 @@
assertThat(RoFeatures.hasFeatureWatch(mContext)).isTrue();
assertThat(RoFeatures.hasFeatureWifi(mContext)).isTrue();
assertThat(RoFeatures.hasFeatureVulkan(mContext)).isFalse();
- assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
verify(mPackageManager, never()).hasSystemFeature(anyString(), anyInt());
- // For defined feature types, conditional queries should reflect the build-time versions.
+ // For defined feature types, conditional queries should reflect either:
+ // * Enabled if the feature version is specified
+ // * Disabled if UNAVAILABLE is specified
+ // * Unknown if no version value is provided
+
// VERSION=1
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, -1)).isTrue();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isTrue();
@@ -124,15 +133,19 @@
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isTrue();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 100)).isFalse();
- // VERSION=-1
- assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, -1)).isTrue();
+ // VERSION=UNAVAILABLE
+ assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, -1)).isFalse();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isFalse();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 100)).isFalse();
- // DISABLED
- assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isFalse();
- assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isFalse();
- assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isFalse();
+ // VERSION=
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(false);
+ assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(true);
+ assertThat(RoFeatures.hasFeatureAuto(mContext)).isTrue();
+ assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isNull();
+ assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
+ assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isNull();
// For feature APIs without an associated feature definition, conditional queries should
// report null, and explicit queries should report runtime-defined versions.
@@ -148,5 +161,12 @@
assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", -1)).isNull();
assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 100)).isNull();
+ assertThat(RoFeatures.maybeHasFeature("", 0)).isNull();
+
+ Map<String, FeatureInfo> compiledFeatures = RoFeatures.getCompileTimeAvailableFeatures();
+ assertThat(compiledFeatures.keySet())
+ .containsExactly(PackageManager.FEATURE_WATCH, PackageManager.FEATURE_WIFI);
+ assertThat(compiledFeatures.get(PackageManager.FEATURE_WATCH).version).isEqualTo(1);
+ assertThat(compiledFeatures.get(PackageManager.FEATURE_WIFI).version).isEqualTo(0);
}
}