Merge "[Reland] VCN: Require capability matching on test networks for CTS"
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
index 6b3278f..4f5b620 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "9653376"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimPriv.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/frameworks/base"
- git_branch: "tm-dev"
+ git_branch: "master"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
index 34c9c4d..404bcac 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "9653376"
target: "CtsShim"
source_file: "aosp_arm64/CtsShim.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/frameworks/base"
- git_branch: "tm-dev"
+ git_branch: "master"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb
new file mode 100644
index 0000000..e898091
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb
@@ -0,0 +1,15 @@
+drops {
+ android_build_drop {
+ build_id: "9653376"
+ target: "CtsShim"
+ source_file: "aosp_riscv64/CtsShimPriv.apk"
+ }
+ dest_file: "packages/CtsShim/apk//riscv64/CtsShimPriv.apk"
+ version: ""
+ version_group: ""
+ git_project: "platform/frameworks/base"
+ git_branch: "master"
+ transform: TRANSFORM_NONE
+ transform_options {
+ }
+}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb
new file mode 100644
index 0000000..04092366
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb
@@ -0,0 +1,15 @@
+drops {
+ android_build_drop {
+ build_id: "9653376"
+ target: "CtsShim"
+ source_file: "aosp_riscv64/CtsShim.apk"
+ }
+ dest_file: "packages/CtsShim/apk//riscv64/CtsShim.apk"
+ version: ""
+ version_group: ""
+ git_project: "platform/frameworks/base"
+ git_branch: "master"
+ transform: TRANSFORM_NONE
+ transform_options {
+ }
+}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
index 6897a02..045af02 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "9653376"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimPriv.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/frameworks/base"
- git_branch: "tm-dev"
+ git_branch: "master"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
index 6dfa7810..483b2f17 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "9653376"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShim.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/frameworks/base"
- git_branch: "tm-dev"
+ git_branch: "master"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a48ce0c..0ba24d1 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -73,14 +73,6 @@
]
},
{
- "name": "TestablesTests",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
- },
- {
"name": "FrameworksCoreTests",
"options": [
{
diff --git a/core/api/current.txt b/core/api/current.txt
index b243374..4c1594b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -18727,8 +18727,8 @@
method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int, int);
method public boolean claimInterface(android.hardware.usb.UsbInterface, boolean);
method public void close();
- method public int controlTransfer(int, int, int, int, byte[], int, int);
- method public int controlTransfer(int, int, int, int, byte[], int, int, int);
+ method public int controlTransfer(int, int, int, int, @Nullable byte[], int, int);
+ method public int controlTransfer(int, int, int, int, @Nullable byte[], int, int, int);
method public int getFileDescriptor();
method public byte[] getRawDescriptors();
method public String getSerial();
@@ -41362,6 +41362,8 @@
field public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY = "carrier_nr_availabilities_int_array";
field public static final String KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL = "carrier_provisions_wifi_merged_networks_bool";
field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+ field public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
+ field public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY = "carrier_service_number_array";
field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool";
@@ -42743,9 +42745,12 @@
method public int getDomain();
method @Nullable public String getRegisteredPlmn();
method public int getTransportType();
- method public boolean isRegistered();
- method public boolean isRoaming();
- method public boolean isSearching();
+ method public boolean isNetworkRegistered();
+ method public boolean isNetworkRoaming();
+ method public boolean isNetworkSearching();
+ method @Deprecated public boolean isRegistered();
+ method @Deprecated public boolean isRoaming();
+ method @Deprecated public boolean isSearching();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
field public static final int DOMAIN_CS = 1; // 0x1
@@ -43499,6 +43504,7 @@
method public int describeContents();
method public int getNetworkType();
method public int getOverrideNetworkType();
+ method public boolean isRoaming();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyDisplayInfo> CREATOR;
field public static final int OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO = 2; // 0x2
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 398b596..821944f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12828,7 +12828,8 @@
public final class NetworkRegistrationInfo implements android.os.Parcelable {
method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getRegistrationState();
+ method public int getNetworkRegistrationState();
+ method @Deprecated public int getRegistrationState();
method public int getRejectCause();
method public int getRoamingType();
method public boolean isEmergencyEnabled();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 7cfb66a..6a5ef3a 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -141,8 +141,9 @@
field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
- field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
+ field @Deprecated public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
+ field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8
field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
field public static final int PROCESS_STATE_TOP = 2; // 0x2
field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index eadf758..d328b34 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -643,9 +643,17 @@
@TestApi
public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
- /** @hide Process can access network despite any power saving resrictions */
+ /** @hide Process can access network despite any power saving restrictions */
@TestApi
- public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
+ public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 1 << 3;
+ /**
+ * @hide
+ * @deprecated Use {@link #PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK} instead.
+ */
+ @TestApi
+ @Deprecated
+ public static final int PROCESS_CAPABILITY_NETWORK =
+ PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
/** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
@TestApi
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5599893..5ba7a4c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -238,6 +238,7 @@
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.net.InetAddress;
+import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -4221,18 +4222,20 @@
static void handleAttachStartupAgents(String dataDir) {
try {
- Path code_cache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
- if (!Files.exists(code_cache)) {
+ Path codeCache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
+ if (!Files.exists(codeCache)) {
return;
}
- Path startup_path = code_cache.resolve("startup_agents");
- if (Files.exists(startup_path)) {
- for (Path p : Files.newDirectoryStream(startup_path)) {
- handleAttachAgent(
- p.toAbsolutePath().toString()
- + "="
- + dataDir,
- null);
+ Path startupPath = codeCache.resolve("startup_agents");
+ if (Files.exists(startupPath)) {
+ try (DirectoryStream<Path> startupFiles = Files.newDirectoryStream(startupPath)) {
+ for (Path p : startupFiles) {
+ handleAttachAgent(
+ p.toAbsolutePath().toString()
+ + "="
+ + dataDir,
+ null);
+ }
}
}
} catch (Exception e) {
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index bccbb38..2a854b2 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -37,8 +37,6 @@
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerExemptionManager.TempAllowListType;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -61,7 +59,8 @@
private long mRequireCompatChangeId = CHANGE_INVALID;
private long mIdForResponseEvent;
private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
- private @Nullable String mDeliveryGroupMatchingKey;
+ private @Nullable String mDeliveryGroupMatchingNamespaceFragment;
+ private @Nullable String mDeliveryGroupMatchingKeyFragment;
private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
private @Nullable IntentFilter mDeliveryGroupMatchingFilter;
private @DeferralPolicy int mDeferralPolicy;
@@ -209,7 +208,13 @@
"android:broadcast.deliveryGroupPolicy";
/**
- * Corresponds to {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * Corresponds to namespace fragment of {@link #setDeliveryGroupMatchingKey(String, String)}.
+ */
+ private static final String KEY_DELIVERY_GROUP_NAMESPACE =
+ "android:broadcast.deliveryGroupMatchingNamespace";
+
+ /**
+ * Corresponds to key fragment of {@link #setDeliveryGroupMatchingKey(String, String)}.
*/
private static final String KEY_DELIVERY_GROUP_KEY =
"android:broadcast.deliveryGroupMatchingKey";
@@ -350,7 +355,8 @@
mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
DELIVERY_GROUP_POLICY_ALL);
- mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
+ mDeliveryGroupMatchingNamespaceFragment = opts.getString(KEY_DELIVERY_GROUP_NAMESPACE);
+ mDeliveryGroupMatchingKeyFragment = opts.getString(KEY_DELIVERY_GROUP_KEY);
mDeliveryGroupExtrasMerger = opts.getParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER,
BundleMerger.class);
mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
@@ -864,11 +870,8 @@
@NonNull
public BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String namespace,
@NonNull String key) {
- Preconditions.checkArgument(!namespace.contains(":"),
- "namespace should not contain ':'");
- Preconditions.checkArgument(!key.contains(":"),
- "key should not contain ':'");
- mDeliveryGroupMatchingKey = namespace + ":" + key;
+ mDeliveryGroupMatchingNamespaceFragment = Objects.requireNonNull(namespace);
+ mDeliveryGroupMatchingKeyFragment = Objects.requireNonNull(key);
return this;
}
@@ -881,7 +884,38 @@
*/
@Nullable
public String getDeliveryGroupMatchingKey() {
- return mDeliveryGroupMatchingKey;
+ if (mDeliveryGroupMatchingNamespaceFragment == null
+ || mDeliveryGroupMatchingKeyFragment == null) {
+ return null;
+ }
+ return String.join(":", mDeliveryGroupMatchingNamespaceFragment,
+ mDeliveryGroupMatchingKeyFragment);
+ }
+
+ /**
+ * Return the namespace fragment that is used to identify the delivery group that this
+ * broadcast belongs to.
+ *
+ * @return the delivery group namespace fragment that was previously set using
+ * {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * @hide
+ */
+ @Nullable
+ public String getDeliveryGroupMatchingNamespaceFragment() {
+ return mDeliveryGroupMatchingNamespaceFragment;
+ }
+
+ /**
+ * Return the key fragment that is used to identify the delivery group that this
+ * broadcast belongs to.
+ *
+ * @return the delivery group key fragment that was previously set using
+ * {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * @hide
+ */
+ @Nullable
+ public String getDeliveryGroupMatchingKeyFragment() {
+ return mDeliveryGroupMatchingKeyFragment;
}
/**
@@ -889,7 +923,8 @@
* {@link #setDeliveryGroupMatchingKey(String, String)}.
*/
public void clearDeliveryGroupMatchingKey() {
- mDeliveryGroupMatchingKey = null;
+ mDeliveryGroupMatchingNamespaceFragment = null;
+ mDeliveryGroupMatchingKeyFragment = null;
}
/**
@@ -1101,8 +1136,11 @@
if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
}
- if (mDeliveryGroupMatchingKey != null) {
- b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKey);
+ if (mDeliveryGroupMatchingNamespaceFragment != null) {
+ b.putString(KEY_DELIVERY_GROUP_NAMESPACE, mDeliveryGroupMatchingNamespaceFragment);
+ }
+ if (mDeliveryGroupMatchingKeyFragment != null) {
+ b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKeyFragment);
}
if (mDeliveryGroupPolicy == DELIVERY_GROUP_POLICY_MERGED) {
if (mDeliveryGroupExtrasMerger != null) {
diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS
index 01b2cb9..1e41886 100644
--- a/core/java/android/hardware/soundtrigger/OWNERS
+++ b/core/java/android/hardware/soundtrigger/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 7c2e518..44144d9 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -238,7 +238,7 @@
* or negative value for failure
*/
public int controlTransfer(int requestType, int request, int value,
- int index, byte[] buffer, int length, int timeout) {
+ int index, @Nullable byte[] buffer, int length, int timeout) {
return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);
}
@@ -263,7 +263,7 @@
* or negative value for failure
*/
public int controlTransfer(int requestType, int request, int value, int index,
- byte[] buffer, int offset, int length, int timeout) {
+ @Nullable byte[] buffer, int offset, int length, int timeout) {
checkBounds(buffer, offset, length);
return native_control_request(requestType, request, value, index,
buffer, offset, length, timeout);
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index a20191c..74775a8 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -769,6 +769,19 @@
}
}
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("IkeV2VpnProfile [");
+ sb.append(" MaxMtu=" + mMaxMtu);
+ if (mIsBypassable) sb.append(" Bypassable");
+ if (mRequiresInternetValidation) sb.append(" RequiresInternetValidation");
+ if (mIsRestrictedToTestNetworks) sb.append(" RestrictedToTestNetworks");
+ if (mAutomaticNattKeepaliveTimerEnabled) sb.append(" AutomaticNattKeepaliveTimerEnabled");
+ if (mAutomaticIpVersionSelectionEnabled) sb.append(" AutomaticIpVersionSelectionEnabled");
+ sb.append("]");
+ return sb.toString();
+ }
+
/** A incremental builder for IKEv2 VPN profiles */
public static final class Builder {
private int mType = -1;
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 878e141..970f419 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -21,6 +21,12 @@
/**
* Parent exception for all Binder remote-invocation errors
+ *
+ * Note: not all exceptions from binder services will be subclasses of this.
+ * For instance, RuntimeException and several subclasses of it may be
+ * thrown as well as OutOfMemoryException.
+ *
+ * One common subclass is {@link DeadObjectException}.
*/
public class RemoteException extends AndroidException {
public RemoteException() {
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 6d64022..a3c278f 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -15,6 +15,10 @@
# Autofill
per-file ViewStructure.java = file:/core/java/android/service/autofill/OWNERS
+# Choreographer
+per-file Choreographer.java = file:platform/frameworks/native:/services/surfaceflinger/OWNERS
+per-file DisplayEventReceiver.java = file:platform/frameworks/native:/services/surfaceflinger/OWNERS
+
# Display
per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
per-file Display*.aidl = file:/services/core/java/com/android/server/display/OWNERS
@@ -56,6 +60,9 @@
per-file SurfaceHolder.java = file:/graphics/java/android/graphics/OWNERS
per-file SurfaceHolder.java = file:/services/core/java/com/android/server/wm/OWNERS
+# Text
+per-file HandwritingInitiator.java = file:/core/java/android/text/OWNERS
+
# View
per-file View.java = file:/services/accessibility/OWNERS
per-file View.java = file:/core/java/android/service/autofill/OWNERS
diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java
index 65fbb03..2fe784a 100644
--- a/core/java/com/android/internal/expresslog/Histogram.java
+++ b/core/java/com/android/internal/expresslog/Histogram.java
@@ -54,6 +54,19 @@
/*count*/ 1, binIndex);
}
+ /**
+ * Logs increment sample count for automatically calculated bin
+ *
+ * @param uid used as a dimension for the count metric
+ * @param sample value
+ * @hide
+ */
+ public void logSampleWithUid(int uid, float sample) {
+ final int binIndex = mBinOptions.getBinForSample(sample);
+ FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED,
+ mMetricIdHash, /*count*/ 1, binIndex, uid);
+ }
+
/** Used by Histogram to map data sample to corresponding bin */
public interface BinOptions {
/**
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index c99a27a..1e7a93c 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -5,6 +5,9 @@
# Connectivity
per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
+# Choreographer
+per-file android_view_DisplayEventReceiver* = file:platform/frameworks/native:/services/surfaceflinger/OWNERS
+
# CPU
per-file *Cpu* = file:/core/java/com/android/internal/os/CPU_OWNERS
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index a7c7d0b..b24dc8a 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -413,9 +413,13 @@
if (env->ExceptionCheck()) {
ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
- binder_report_exception(env, excep.get(),
- "*** Uncaught remote exception! "
- "(Exceptions are not yet supported across processes.)");
+
+ auto state = IPCThreadState::self();
+ String8 msg;
+ msg.appendFormat("*** Uncaught remote exception! Exceptions are not yet supported "
+ "across processes. Client PID %d UID %d.",
+ state->getCallingPid(), state->getCallingUid());
+ binder_report_exception(env, excep.get(), msg.c_str());
res = JNI_FALSE;
}
@@ -431,6 +435,7 @@
ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
binder_report_exception(env, excep.get(),
"*** Uncaught exception in onBinderStrictModePolicyChange");
+ // TODO: should turn this to fatal?
}
// Need to always call through the native implementation of
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a5e9617..277bdf3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1334,8 +1334,7 @@
android:permissionFlags="hardRestricted"
android:protectionLevel="dangerous" />
- <!-- Allows an application to write (but not read) the user's
- call log data.
+ <!-- Allows an application to write and read the user's call log data.
<p class="note"><strong>Note:</strong> If your app uses the
{@link #WRITE_CONTACTS} permission and <em>both</em> your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index c2cd6ff..74597c5 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -161,6 +161,15 @@
}
/**
+ * List all entries in the keystore for in the given namespace.
+ */
+ public KeyDescriptor[] listBatch(int domain, long namespace, String startPastAlias)
+ throws KeyStoreException {
+ return handleRemoteExceptionWithRetry(
+ (service) -> service.listEntriesBatched(domain, namespace, startPastAlias));
+ }
+
+ /**
* Grant string prefix as used by the keystore boringssl engine. Must be kept in sync
* with system/security/keystore-engine. Note: The prefix here includes the 0x which
* std::stringstream used in keystore-engine needs to identify the number as hex represented.
@@ -301,6 +310,13 @@
});
}
+ /**
+ * Returns the number of Keystore entries for a given domain and namespace.
+ */
+ public int getNumberOfEntries(int domain, long namespace) throws KeyStoreException {
+ return handleRemoteExceptionWithRetry((service)
+ -> service.getNumberOfEntries(domain, namespace));
+ }
protected static void interruptedPreservingSleep(long millis) {
boolean wasInterrupted = false;
Calendar calendar = Calendar.getInstance();
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 91f216f..045e318 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -79,13 +79,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
+import java.util.NoSuchElementException;
import javax.crypto.SecretKey;
@@ -1043,26 +1041,22 @@
}
}
- private Set<String> getUniqueAliases() {
+ private KeyDescriptor[] getAliasesBatch(String startPastAlias) {
try {
- final KeyDescriptor[] keys = mKeyStore.list(
+ return mKeyStore.listBatch(
getTargetDomain(),
- mNamespace
+ mNamespace,
+ startPastAlias
);
- final Set<String> aliases = new HashSet<>(keys.length);
- for (KeyDescriptor d : keys) {
- aliases.add(d.alias);
- }
- return aliases;
} catch (android.security.KeyStoreException e) {
Log.e(TAG, "Failed to list keystore entries.", e);
- return new HashSet<>();
+ return new KeyDescriptor[0];
}
}
@Override
public Enumeration<String> engineAliases() {
- return Collections.enumeration(getUniqueAliases());
+ return new KeyEntriesEnumerator();
}
@Override
@@ -1073,12 +1067,18 @@
return getKeyMetadata(alias) != null;
}
-
@Override
public int engineSize() {
- return getUniqueAliases().size();
+ try {
+ return mKeyStore.getNumberOfEntries(
+ getTargetDomain(),
+ mNamespace
+ );
+ } catch (android.security.KeyStoreException e) {
+ Log.e(TAG, "Failed to get the number of keystore entries.", e);
+ return 0;
+ }
}
-
@Override
public boolean engineIsKeyEntry(String alias) {
return isKeyEntry(alias);
@@ -1251,4 +1251,38 @@
+ "or TrustedCertificateEntry; was " + entry);
}
}
+
+ private class KeyEntriesEnumerator implements Enumeration<String> {
+ private KeyDescriptor[] mCurrentBatch;
+ private int mCurrentEntry = 0;
+ private String mLastAlias = null;
+ private KeyEntriesEnumerator() {
+ getAndValidateNextBatch();
+ }
+
+ private void getAndValidateNextBatch() {
+ mCurrentBatch = getAliasesBatch(mLastAlias);
+ mCurrentEntry = 0;
+ }
+
+ public boolean hasMoreElements() {
+ return (mCurrentBatch != null) && (mCurrentBatch.length > 0);
+ }
+
+ public String nextElement() {
+ if ((mCurrentBatch == null) || (mCurrentBatch.length == 0)) {
+ throw new NoSuchElementException("Error while fetching entries.");
+ }
+ final KeyDescriptor currentEntry = mCurrentBatch[mCurrentEntry];
+ mLastAlias = currentEntry.alias;
+
+ mCurrentEntry++;
+ // This was the last entry in the batch.
+ if (mCurrentEntry >= mCurrentBatch.length) {
+ getAndValidateNextBatch();
+ }
+
+ return mLastAlias;
+ }
+ }
}
diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
index f96c39c8..1e1f68a 100644
--- a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
+++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
@@ -17,9 +17,14 @@
package android.security.keystore2;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.security.KeyStore2;
@@ -36,6 +41,12 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.NoSuchElementException;
+
public class AndroidKeyStoreSpiTest {
@Mock
@@ -48,14 +59,176 @@
@Test
public void testEngineAliasesReturnsEmptySetOnKeyStoreError() throws Exception {
- when(mKeystore2.list(anyInt(), anyLong()))
+ when(mKeystore2.listBatch(anyInt(), anyLong(), isNull()))
.thenThrow(new KeyStoreException(6, "Some Error"));
AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
spi.initForTesting(mKeystore2);
assertThat("Empty collection expected", !spi.engineAliases().hasMoreElements());
- verify(mKeystore2).list(anyInt(), anyLong());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsZeroEntriesEmptyArray() throws Exception {
+ when(mKeystore2.listBatch(anyInt(), anyLong(), anyString()))
+ .thenReturn(new KeyDescriptor[0]);
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should not have any elements", !aliases.hasMoreElements());
+ assertThrows("Should have no elements to return", NoSuchElementException.class,
+ () -> aliases.nextElement());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsZeroEntriesNullArray() throws Exception {
+ when(mKeystore2.listBatch(anyInt(), anyLong(), anyString()))
+ .thenReturn(null);
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should not have any elements", !aliases.hasMoreElements());
+ assertThrows("Should have no elements to return", NoSuchElementException.class,
+ () -> aliases.nextElement());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ private static KeyDescriptor newKeyDescriptor(String alias) {
+ KeyDescriptor result = new KeyDescriptor();
+ result.alias = alias;
+ return result;
+ }
+
+ private static KeyDescriptor[] createKeyDescriptorsArray(int numEntries) {
+ KeyDescriptor[] kds = new KeyDescriptor[numEntries];
+ for (int i = 0; i < kds.length; i++) {
+ kds[i] = newKeyDescriptor(String.format("alias-%d", i));
+ }
+
+ return kds;
+ }
+
+ private static void assertAliasListsEqual(
+ KeyDescriptor[] keyDescriptors, Enumeration<String> aliasesEnumerator) {
+ List<String> aliases = Collections.list(aliasesEnumerator);
+ Assert.assertArrayEquals(Arrays.stream(keyDescriptors).map(kd -> kd.alias).toArray(),
+ aliases.toArray());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesInASingleBatch() throws Exception {
+ final String alias1 = "testAlias1";
+ final String alias2 = "testAlias2";
+ final String alias3 = "testAlias3";
+ KeyDescriptor[] kds = {newKeyDescriptor(alias1),
+ newKeyDescriptor(alias2), newKeyDescriptor(alias3)};
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("testAlias3")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should have more elements before first.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias1);
+ assertThat("Should have more elements before second.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias2);
+ assertThat("Should have more elements before third.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias3);
+ assertThat("Should have no more elements after third.", !aliases.hasMoreElements());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("testAlias3"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesInMultipleBatches() throws Exception {
+ final int numEntries = 2500;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(Arrays.copyOfRange(kds, 0, 1000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(Arrays.copyOfRange(kds, 1000, 2000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-1999")))
+ .thenReturn(Arrays.copyOfRange(kds, 2000, 2500));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-2499")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-1999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-2499"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenNumEntriesIsExactlyOneBatchSize()
+ throws Exception {
+ final int numEntries = 1000;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenNumEntriesIsAMultiplyOfBatchSize()
+ throws Exception {
+ final int numEntries = 2000;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(Arrays.copyOfRange(kds, 0, 1000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(Arrays.copyOfRange(kds, 1000, 2000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-1999")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-1999"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenReturningLessThanBatchSize()
+ throws Exception {
+ final int numEntries = 500;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-499")))
+ .thenReturn(new KeyDescriptor[0]);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-499"));
+ verifyNoMoreInteractions(mKeystore2);
}
@Mock
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 5a67eb9..738f1ab 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -98,7 +98,7 @@
debugOverdraw = false;
std::string debugOverdrawProperty = base::GetProperty(PROPERTY_DEBUG_OVERDRAW, "");
if (debugOverdrawProperty != "") {
- INIT_LOGD(" Overdraw debug enabled: %s", debugOverdrawProperty);
+ INIT_LOGD(" Overdraw debug enabled: %s", debugOverdrawProperty.c_str());
if (debugOverdrawProperty == "show") {
debugOverdraw = true;
overdrawColorSet = OverdrawColorSet::Default;
diff --git a/media/OWNERS b/media/OWNERS
index 5f50137..4a6648e 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 1344
+atneya@google.com
elaurent@google.com
essick@google.com
etalvala@google.com
diff --git a/media/aidl/android/media/soundtrigger_middleware/OWNERS b/media/aidl/android/media/soundtrigger_middleware/OWNERS
index 01b2cb9..1e41886 100644
--- a/media/aidl/android/media/soundtrigger_middleware/OWNERS
+++ b/media/aidl/android/media/soundtrigger_middleware/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 22033c6..6b29fc3 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -72,7 +72,7 @@
throw new UnsupportedOperationException("Trying to instantiate AudioSystem");
}
- /* These values must be kept in sync with system/audio.h */
+ /* These values must be kept in sync with system/media/audio/include/system/audio-hal-enums.h */
/*
* If these are modified, please also update Settings.System.VOLUME_SETTINGS
* and attrs.xml and AudioManager.java.
@@ -963,7 +963,8 @@
*/
//
- // audio device definitions: must be kept in sync with values in system/core/audio.h
+ // audio device definitions: must be kept in sync with values
+ // in system/media/audio/include/system/audio-hal-enums.h
//
/** @hide */
public static final int DEVICE_NONE = 0x0;
diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS
index 01b2cb9..85f7a4d 100644
--- a/media/java/android/media/soundtrigger/OWNERS
+++ b/media/java/android/media/soundtrigger/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 48436
atneya@google.com
elaurent@google.com
diff --git a/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp
index 31cd760..baafe7b 100644
--- a/packages/CtsShim/Android.bp
+++ b/packages/CtsShim/Android.bp
@@ -44,6 +44,9 @@
arm64: {
apk: "apk/arm/CtsShimPriv.apk",
},
+ riscv64: {
+ apk: "apk/riscv64/CtsShimPriv.apk",
+ },
x86: {
apk: "apk/x86/CtsShimPriv.apk",
},
@@ -82,6 +85,9 @@
arm64: {
apk: "apk/arm/CtsShim.apk",
},
+ riscv64: {
+ apk: "apk/riscv64/CtsShim.apk",
+ },
x86: {
apk: "apk/x86/CtsShim.apk",
},
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index fb09286..af306a5 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 07915ce..98c5351 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/riscv64/CtsShim.apk b/packages/CtsShim/apk/riscv64/CtsShim.apk
new file mode 100644
index 0000000..af306a5
--- /dev/null
+++ b/packages/CtsShim/apk/riscv64/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/riscv64/CtsShimPriv.apk b/packages/CtsShim/apk/riscv64/CtsShimPriv.apk
new file mode 100644
index 0000000..9a9997d
--- /dev/null
+++ b/packages/CtsShim/apk/riscv64/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index fb09286..af306a5 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 20e94b6..29ad478 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 6669d6b..868867d 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.packageinstaller">
<original-package android:name="com.android.packageinstaller" />
@@ -142,6 +143,9 @@
android:authorities="com.google.android.packageinstaller.wear.provider"
android:grantUriPermissions="true"
android:exported="true" />
+
+ <receiver android:name="androidx.profileinstaller.ProfileInstallReceiver"
+ tools:node="remove" />
</application>
</manifest>
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index f305fd3..e92157e 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -47,7 +47,7 @@
* Annotation processor for {@link SearchIndexable} that generates {@link SearchIndexableResources}
* subclasses.
*/
-@SupportedSourceVersion(SourceVersion.RELEASE_11)
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
@SupportedAnnotationTypes({"com.android.settingslib.search.SearchIndexable"})
public class IndexableProcessor extends AbstractProcessor {
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
index 39b4b8e..35e3dd3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
@@ -231,7 +231,7 @@
public SignalStrength signalStrength;
public TelephonyDisplayInfo telephonyDisplayInfo =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
/**
* Empty constructor
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
index ab9b5dc..c01528fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
@@ -1,4 +1,7 @@
# Default reviewers for this and subdirectories.
-bonianchen@google.com
+songferngwang@google.com
+zoeychen@google.com
# Emergency approvers in case the above are not available
+changbetty@google.com
+tomhsu@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
index ab9b5dc..c01528fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
@@ -1,4 +1,7 @@
# Default reviewers for this and subdirectories.
-bonianchen@google.com
+songferngwang@google.com
+zoeychen@google.com
# Emergency approvers in case the above are not available
+changbetty@google.com
+tomhsu@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 2e6ea0e..54946ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -144,7 +144,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final TelephonyDisplayInfo DEFAULT_TELEPHONY_DISPLAY_INFO =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
static final int MAX_WIFI_ENTRY_COUNT = 3;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
index 1fb6a98..c37b01f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
@@ -49,7 +49,7 @@
) : ConnectivityState() {
@JvmField var telephonyDisplayInfo = TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE)
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false)
@JvmField var serviceState: ServiceState? = null
@JvmField var signalStrength: SignalStrength? = null
@@ -131,7 +131,7 @@
}
fun isRoaming(): Boolean {
- return serviceState != null && serviceState!!.roaming
+ return telephonyDisplayInfo != null && telephonyDisplayInfo.isRoaming
}
/**
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 59db686..f149fda 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -45,6 +45,7 @@
import android.util.Slog;
import com.android.internal.telephony.IMms;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -337,6 +338,14 @@
throws RemoteException {
Slog.d(TAG, "sendMessage() by " + callingPkg);
mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
+
+ // Check if user is associated with the subscription
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(mContext, subId,
+ Binder.getCallingUserHandle())) {
+ // TODO(b/258629881): Display error dialog.
+ return;
+ }
+
if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) {
Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a69d3f0..77a54a5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1957,7 +1957,8 @@
&& overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) {
overrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE;
}
- return new TelephonyDisplayInfo(networkType, overrideNetworkType);
+ boolean isRoaming = telephonyDisplayInfo.isRoaming();
+ return new TelephonyDisplayInfo(networkType, overrideNetworkType, isRoaming);
}
public void notifyCallForwardingChanged(boolean cfi) {
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index f652cb0..78d4708 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -1104,7 +1104,7 @@
final NetworkCapabilities result = ncBuilder.build();
final VcnUnderlyingNetworkPolicy policy = new VcnUnderlyingNetworkPolicy(
mTrackingNetworkCallback
- .requiresRestartForImmutableCapabilityChanges(result),
+ .requiresRestartForImmutableCapabilityChanges(result, linkProperties),
result);
logVdbg("getUnderlyingNetworkPolicy() called for caps: " + networkCapabilities
@@ -1354,19 +1354,29 @@
* without requiring a Network restart.
*/
private class TrackingNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final Object mLockObject = new Object();
private final Map<Network, NetworkCapabilities> mCaps = new ArrayMap<>();
+ private final Map<Network, LinkProperties> mLinkProperties = new ArrayMap<>();
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) {
- synchronized (mCaps) {
+ synchronized (mLockObject) {
mCaps.put(network, caps);
}
}
@Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+ synchronized (mLockObject) {
+ mLinkProperties.put(network, lp);
+ }
+ }
+
+ @Override
public void onLost(Network network) {
- synchronized (mCaps) {
+ synchronized (mLockObject) {
mCaps.remove(network);
+ mLinkProperties.remove(network);
}
}
@@ -1393,22 +1403,28 @@
return true;
}
- private boolean requiresRestartForImmutableCapabilityChanges(NetworkCapabilities caps) {
+ private boolean requiresRestartForImmutableCapabilityChanges(
+ NetworkCapabilities caps, LinkProperties lp) {
if (caps.getSubscriptionIds() == null) {
return false;
}
- synchronized (mCaps) {
- for (NetworkCapabilities existing : mCaps.values()) {
- if (caps.getSubscriptionIds().equals(existing.getSubscriptionIds())
- && hasSameTransportsAndCapabilities(caps, existing)) {
- // Restart if any immutable capabilities have changed
- return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ synchronized (mLockObject) {
+ // Search for an existing network (using interfce names)
+ // TODO: Get network from NetworkFactory (if exists) for this match.
+ for (Entry<Network, LinkProperties> lpEntry : mLinkProperties.entrySet()) {
+ if (lp.getInterfaceName() != null
+ && !lp.getInterfaceName().isEmpty()
+ && Objects.equals(
+ lp.getInterfaceName(), lpEntry.getValue().getInterfaceName())) {
+ return mCaps.get(lpEntry.getKey())
+ .hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
!= caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED);
}
}
}
+ // If no network found, by definition does not need restart.
return false;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d48723a..99f1863 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8415,13 +8415,16 @@
}
}
+ boolean recoverable = eventType.equals("native_recoverable_crash");
+
EventLogTags.writeAmCrash(Binder.getCallingPid(),
UserHandle.getUserId(Binder.getCallingUid()), processName,
r == null ? -1 : r.info.flags,
crashInfo.exceptionClassName,
crashInfo.exceptionMessage,
crashInfo.throwFileName,
- crashInfo.throwLineNumber);
+ crashInfo.throwLineNumber,
+ recoverable ? 1 : 0);
int processClassEnum = processName.equals("system_server") ? ServerProtoEnums.SYSTEM_SERVER
: (r != null) ? r.getProcessClassEnum()
@@ -8489,7 +8492,13 @@
eventType, r, processName, null, null, null, null, null, null, crashInfo,
new Float(loadingProgress), incrementalMetrics, null);
- mAppErrors.crashApplication(r, crashInfo);
+ // For GWP-ASan recoverable crashes, don't make the app crash (the whole point of
+ // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes,
+ // debuggerd will terminate the process, but there's a backup where ActivityManager will
+ // also kill it. Avoid that.
+ if (!recoverable) {
+ mAppErrors.crashApplication(r, crashInfo);
+ }
}
public void handleApplicationStrictModeViolation(
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index d080036..6ce70a1 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -53,7 +53,7 @@
30037 am_process_start_timeout (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3)
# Unhandled exception
-30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
+30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5),(Recoverable|1|5)
# Log.wtf() called
30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3)
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index 94eb076..cd119e7 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -64,12 +64,15 @@
class NativeCrashReporter extends Thread {
ProcessRecord mApp;
int mSignal;
+ boolean mGwpAsanRecoverableCrash;
String mCrashReport;
- NativeCrashReporter(ProcessRecord app, int signal, String report) {
+ NativeCrashReporter(ProcessRecord app, int signal, boolean gwpAsanRecoverableCrash,
+ String report) {
super("NativeCrashReport");
mApp = app;
mSignal = signal;
+ mGwpAsanRecoverableCrash = gwpAsanRecoverableCrash;
mCrashReport = report;
}
@@ -85,7 +88,9 @@
ci.stackTrace = mCrashReport;
if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()");
- mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci);
+ mAm.handleApplicationCrashInner(
+ mGwpAsanRecoverableCrash ? "native_recoverable_crash" : "native_crash",
+ mApp, mApp.processName, ci);
if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned");
} catch (Exception e) {
Slog.e(TAG, "Unable to report native crash", e);
@@ -207,9 +212,14 @@
// permits crash_dump to connect to it. This allows us to trust the
// received values.
- // first, the pid and signal number
- int headerBytes = readExactly(fd, buf, 0, 8);
- if (headerBytes != 8) {
+ // Activity Manager protocol:
+ // - 32-bit network-byte-order: pid
+ // - 32-bit network-byte-order: signal number
+ // - byte: gwpAsanRecoverableCrash
+ // - bytes: raw text of the dump
+ // - null terminator
+ int headerBytes = readExactly(fd, buf, 0, 9);
+ if (headerBytes != 9) {
// protocol failure; give up
Slog.e(TAG, "Unable to read from debuggerd");
return;
@@ -217,69 +227,76 @@
int pid = unpackInt(buf, 0);
int signal = unpackInt(buf, 4);
+ boolean gwpAsanRecoverableCrash = buf[8] != 0;
if (DEBUG) {
- Slog.v(TAG, "Read pid=" + pid + " signal=" + signal);
+ Slog.v(TAG, "Read pid=" + pid + " signal=" + signal
+ + " recoverable=" + gwpAsanRecoverableCrash);
+ }
+ if (pid < 0) {
+ Slog.e(TAG, "Bogus pid!");
+ return;
}
// now the text of the dump
- if (pid > 0) {
- final ProcessRecord pr;
- synchronized (mAm.mPidsSelfLocked) {
- pr = mAm.mPidsSelfLocked.get(pid);
- }
- if (pr != null) {
- // Don't attempt crash reporting for persistent apps
- if (pr.isPersistent()) {
- if (DEBUG) {
- Slog.v(TAG, "Skipping report for persistent app " + pr);
- }
- return;
- }
-
- int bytes;
- do {
- // get some data
- bytes = Os.read(fd, buf, 0, buf.length);
- if (bytes > 0) {
- if (MORE_DEBUG) {
- String s = new String(buf, 0, bytes, "UTF-8");
- Slog.v(TAG, "READ=" + bytes + "> " + s);
- }
- // did we just get the EOD null byte?
- if (buf[bytes-1] == 0) {
- os.write(buf, 0, bytes-1); // exclude the EOD token
- break;
- }
- // no EOD, so collect it and read more
- os.write(buf, 0, bytes);
- }
- } while (bytes > 0);
-
- // Okay, we've got the report.
- if (DEBUG) Slog.v(TAG, "processing");
-
- // Mark the process record as being a native crash so that the
- // cleanup mechanism knows we're still submitting the report
- // even though the process will vanish as soon as we let
- // debuggerd proceed.
- synchronized (mAm) {
- synchronized (mAm.mProcLock) {
- pr.mErrorState.setCrashing(true);
- pr.mErrorState.setForceCrashReport(true);
- }
- }
-
- // Crash reporting is synchronous but we want to let debuggerd
- // go about it business right away, so we spin off the actual
- // reporting logic on a thread and let it take it's time.
- final String reportString = new String(os.toByteArray(), "UTF-8");
- (new NativeCrashReporter(pr, signal, reportString)).start();
- } else {
- Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid);
- }
- } else {
- Slog.e(TAG, "Bogus pid!");
+ final ProcessRecord pr;
+ synchronized (mAm.mPidsSelfLocked) {
+ pr = mAm.mPidsSelfLocked.get(pid);
}
+ if (pr == null) {
+ Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid);
+ return;
+ }
+
+ // Don't attempt crash reporting for persistent apps
+ if (pr.isPersistent()) {
+ if (DEBUG) {
+ Slog.v(TAG, "Skipping report for persistent app " + pr);
+ }
+ return;
+ }
+
+ int bytes;
+ do {
+ // get some data
+ bytes = Os.read(fd, buf, 0, buf.length);
+ if (bytes > 0) {
+ if (MORE_DEBUG) {
+ String s = new String(buf, 0, bytes, "UTF-8");
+ Slog.v(TAG, "READ=" + bytes + "> " + s);
+ }
+ // did we just get the EOD null byte?
+ if (buf[bytes - 1] == 0) {
+ os.write(buf, 0, bytes - 1); // exclude the EOD token
+ break;
+ }
+ // no EOD, so collect it and read more
+ os.write(buf, 0, bytes);
+ }
+ } while (bytes > 0);
+
+ // Okay, we've got the report.
+ if (DEBUG) Slog.v(TAG, "processing");
+
+ // Mark the process record as being a native crash so that the
+ // cleanup mechanism knows we're still submitting the report even
+ // though the process will vanish as soon as we let debuggerd
+ // proceed. This isn't relevant for recoverable crashes, as we don't
+ // show the user an "app crashed" dialogue because the app (by
+ // design) didn't crash.
+ if (!gwpAsanRecoverableCrash) {
+ synchronized (mAm) {
+ synchronized (mAm.mProcLock) {
+ pr.mErrorState.setCrashing(true);
+ pr.mErrorState.setForceCrashReport(true);
+ }
+ }
+ }
+
+ // Crash reporting is synchronous but we want to let debuggerd
+ // go about it business right away, so we spin off the actual
+ // reporting logic on a thread and let it take it's time.
+ final String reportString = new String(os.toByteArray(), "UTF-8");
+ (new NativeCrashReporter(pr, signal, gwpAsanRecoverableCrash, reportString)).start();
} catch (Exception e) {
Slog.e(TAG, "Exception dealing with report", e);
// ugh, fail.
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index abddc43..256df98 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2573,7 +2573,10 @@
+ ", " + reason);
app.setPendingStart(false);
killProcessQuiet(pid);
- Process.killProcessGroup(app.uid, app.getPid());
+ final int appPid = app.getPid();
+ if (appPid != 0) {
+ Process.killProcessGroup(app.uid, appPid);
+ }
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_START, reason);
return false;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5ca03b8..df9a750 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1014,9 +1014,14 @@
mSfxHelper = new SoundEffectsHelper(mContext, playerBase -> ignorePlayerLogs(playerBase));
- final boolean headTrackingDefault = mContext.getResources().getBoolean(
+ final boolean binauralEnabledDefault = SystemProperties.getBoolean(
+ "ro.audio.spatializer_binaural_enabled_default", true);
+ final boolean transauralEnabledDefault = SystemProperties.getBoolean(
+ "ro.audio.spatializer_transaural_enabled_default", true);
+ final boolean headTrackingEnabledDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_spatial_audio_head_tracking_enabled_default);
- mSpatializerHelper = new SpatializerHelper(this, mAudioSystem, headTrackingDefault);
+ mSpatializerHelper = new SpatializerHelper(this, mAudioSystem,
+ binauralEnabledDefault, transauralEnabledDefault, headTrackingEnabledDefault);
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
@@ -4082,13 +4087,14 @@
return;
}
- // Forcefully set LE audio volume as a workaround, since in some cases
- // (like the outgoing call) the value of 'device' is not DEVICE_OUT_BLE_*
- // even when BLE is connected.
+ // In some cases (like the outgoing or rejected call) the value of 'device' is not
+ // DEVICE_OUT_BLE_* even when BLE is connected. Changing the volume level in such case
+ // may cuase the other devices volume level leaking into the LeAudio device settings.
if (!AudioSystem.isLeAudioDeviceType(device)) {
- Log.w(TAG, "setLeAudioVolumeOnModeUpdate got unexpected device=" + device
- + ", forcing to device=" + AudioSystem.DEVICE_OUT_BLE_HEADSET);
- device = AudioSystem.DEVICE_OUT_BLE_HEADSET;
+ Log.w(TAG, "setLeAudioVolumeOnModeUpdate ignoring invalid device="
+ + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
+ + " streamType=" + streamType);
+ return;
}
if (DEBUG_VOL) {
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 2b56666..c9cdba9 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -106,12 +106,12 @@
};
// Spatializer state machine
- private static final int STATE_UNINITIALIZED = 0;
- private static final int STATE_NOT_SUPPORTED = 1;
- private static final int STATE_DISABLED_UNAVAILABLE = 3;
- private static final int STATE_ENABLED_UNAVAILABLE = 4;
- private static final int STATE_ENABLED_AVAILABLE = 5;
- private static final int STATE_DISABLED_AVAILABLE = 6;
+ /*package*/ static final int STATE_UNINITIALIZED = 0;
+ /*package*/ static final int STATE_NOT_SUPPORTED = 1;
+ /*package*/ static final int STATE_DISABLED_UNAVAILABLE = 3;
+ /*package*/ static final int STATE_ENABLED_UNAVAILABLE = 4;
+ /*package*/ static final int STATE_ENABLED_AVAILABLE = 5;
+ /*package*/ static final int STATE_DISABLED_AVAILABLE = 6;
private int mState = STATE_UNINITIALIZED;
private boolean mFeatureEnabled = false;
@@ -147,9 +147,9 @@
.setSampleRate(48000)
.setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
.build();
- // device array to store the routing for the default attributes and format, size 1 because
- // media is never expected to be duplicated
- private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1];
+ // device array to store the routing for the default attributes and format, initialized to
+ // an empty list as routing hasn't been established yet
+ private static ArrayList<AudioDeviceAttributes> sRoutingDevices = new ArrayList<>(0);
//---------------------------------------------------------------
// audio device compatibility / enabled
@@ -171,18 +171,17 @@
// initialization
@SuppressWarnings("StaticAssignmentInConstructor")
SpatializerHelper(@NonNull AudioService mother, @NonNull AudioSystemAdapter asa,
- boolean headTrackingEnabledByDefault) {
+ boolean binauralEnabledDefault,
+ boolean transauralEnabledDefault,
+ boolean headTrackingEnabledDefault) {
mAudioService = mother;
mASA = asa;
// "StaticAssignmentInConstructor" warning is suppressed as the SpatializerHelper being
// constructed here is the factory for SADeviceState, thus SADeviceState and its
// private static field sHeadTrackingEnabledDefault should never be accessed directly.
- SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledByDefault;
- }
-
- synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
- mBinauralSupported = hasBinaural;
- mTransauralSupported = hasTransaural;
+ SADeviceState.sBinauralEnabledDefault = binauralEnabledDefault;
+ SADeviceState.sTransauralEnabledDefault = transauralEnabledDefault;
+ SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledDefault;
}
synchronized void init(boolean effectExpected, @Nullable String settings) {
@@ -318,8 +317,7 @@
return;
}
mState = STATE_DISABLED_UNAVAILABLE;
- mASA.getDevicesForAttributes(
- DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+ sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
// note at this point mSpat is still not instantiated
}
@@ -361,34 +359,35 @@
case STATE_DISABLED_AVAILABLE:
break;
}
- mASA.getDevicesForAttributes(
- DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+
+ sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
// check validity of routing information
- if (ROUTING_DEVICES[0] == null) {
- logloge("onRoutingUpdated: device is null, no Spatial Audio");
+ if (sRoutingDevices.isEmpty()) {
+ logloge("onRoutingUpdated: no device, no Spatial Audio");
setDispatchAvailableState(false);
// not changing the spatializer level as this is likely a transient state
return;
}
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
// is media routed to a new device?
- if (isWireless(ROUTING_DEVICES[0].getType())) {
- addWirelessDeviceIfNew(ROUTING_DEVICES[0]);
+ if (isWireless(currentDevice.getType())) {
+ addWirelessDeviceIfNew(currentDevice);
}
// find if media device enabled / available
- final Pair<Boolean, Boolean> enabledAvailable = evaluateState(ROUTING_DEVICES[0]);
+ final Pair<Boolean, Boolean> enabledAvailable = evaluateState(currentDevice);
boolean able = false;
if (enabledAvailable.second) {
// available for Spatial audio, check w/ effect
- able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES);
+ able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, sRoutingDevices);
loglogi("onRoutingUpdated: can spatialize media 5.1:" + able
- + " on device:" + ROUTING_DEVICES[0]);
+ + " on device:" + currentDevice);
setDispatchAvailableState(able);
} else {
- loglogi("onRoutingUpdated: device:" + ROUTING_DEVICES[0]
+ loglogi("onRoutingUpdated: device:" + currentDevice
+ " not available for Spatial Audio");
setDispatchAvailableState(false);
}
@@ -396,10 +395,10 @@
boolean enabled = able && enabledAvailable.first;
if (enabled) {
loglogi("Enabling Spatial Audio since enabled for media device:"
- + ROUTING_DEVICES[0]);
+ + currentDevice);
} else {
loglogi("Disabling Spatial Audio since disabled for media device:"
- + ROUTING_DEVICES[0]);
+ + currentDevice);
}
if (mSpat != null) {
byte level = enabled ? (byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL
@@ -732,9 +731,13 @@
}
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
- @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) {
- if (isDeviceCompatibleWithSpatializationModes(devices[0])) {
- return AudioSystem.canBeSpatialized(attributes, format, devices);
+ @NonNull AudioFormat format, @NonNull ArrayList<AudioDeviceAttributes> devices) {
+ if (devices.isEmpty()) {
+ return false;
+ }
+ if (isDeviceCompatibleWithSpatializationModes(devices.get(0))) {
+ AudioDeviceAttributes[] devArray = new AudioDeviceAttributes[devices.size()];
+ return AudioSystem.canBeSpatialized(attributes, format, devices.toArray(devArray));
}
return false;
}
@@ -1010,10 +1013,13 @@
logd("canBeSpatialized false due to usage:" + attributes.getUsage());
return false;
}
- AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1];
+
// going through adapter to take advantage of routing cache
- mASA.getDevicesForAttributes(
- attributes, false /* forVolume */).toArray(devices);
+ final ArrayList<AudioDeviceAttributes> devices = getRoutingDevices(attributes);
+ if (devices.isEmpty()) {
+ logloge("canBeSpatialized got no device for " + attributes);
+ return false;
+ }
final boolean able = canBeSpatializedOnDevice(attributes, format, devices);
logd("canBeSpatialized usage:" + attributes.getUsage()
+ " format:" + format.toLogFriendlyString() + " returning " + able);
@@ -1144,8 +1150,13 @@
logDeviceState(deviceState, "setHeadTrackerEnabled");
// check current routing to see if it affects the headtracking mode
- if (ROUTING_DEVICES[0] != null && ROUTING_DEVICES[0].getType() == ada.getType()
- && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
+ if (sRoutingDevices.isEmpty()) {
+ logloge("setHeadTrackerEnabled: no device, bailing");
+ return;
+ }
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
+ if (currentDevice.getType() == ada.getType()
+ && currentDevice.getAddress().equals(ada.getAddress())) {
setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled
: Spatializer.HEAD_TRACKING_MODE_DISABLED);
if (enabled && !mHeadTrackerAvailable) {
@@ -1539,10 +1550,12 @@
}
/*package*/ static final class SADeviceState {
+ private static boolean sBinauralEnabledDefault = true;
+ private static boolean sTransauralEnabledDefault = true;
private static boolean sHeadTrackingEnabledDefault = false;
final @AudioDeviceInfo.AudioDeviceType int mDeviceType;
final @NonNull String mDeviceAddress;
- boolean mEnabled = true; // by default, SA is enabled on any device
+ boolean mEnabled;
boolean mHasHeadTracker = false;
boolean mHeadTrackerEnabled;
static final String SETTING_FIELD_SEPARATOR = ",";
@@ -1558,6 +1571,12 @@
SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @Nullable String address) {
mDeviceType = deviceType;
mDeviceAddress = isWireless(deviceType) ? Objects.requireNonNull(address) : "";
+ final int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(deviceType, Integer.MIN_VALUE);
+ mEnabled = spatMode == SpatializationMode.SPATIALIZER_BINAURAL
+ ? sBinauralEnabledDefault
+ : spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL
+ ? sTransauralEnabledDefault
+ : false;
mHeadTrackerEnabled = sHeadTrackingEnabledDefault;
}
@@ -1694,10 +1713,11 @@
private int getHeadSensorHandleUpdateTracker() {
int headHandle = -1;
- final AudioDeviceAttributes currentDevice = ROUTING_DEVICES[0];
- if (currentDevice == null) {
+ if (sRoutingDevices.isEmpty()) {
+ logloge("getHeadSensorHandleUpdateTracker: no device, no head tracker");
return headHandle;
}
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice);
// We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion
// with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR
@@ -1731,6 +1751,23 @@
return screenHandle;
}
+ /**
+ * Returns routing for the given attributes
+ * @param aa AudioAttributes whose routing is being queried
+ * @return a non-null never-empty list of devices. If the routing query failed, the list
+ * will contain null.
+ */
+ private @NonNull ArrayList<AudioDeviceAttributes> getRoutingDevices(AudioAttributes aa) {
+ final ArrayList<AudioDeviceAttributes> devices = mASA.getDevicesForAttributes(
+ aa, false /* forVolume */);
+ for (AudioDeviceAttributes ada : devices) {
+ if (ada == null) {
+ // invalid entry, reject this routing query by returning an empty list
+ return new ArrayList<>(0);
+ }
+ }
+ return devices;
+ }
private static void loglogi(String msg) {
AudioService.sSpatialLogger.loglogi(msg, TAG);
@@ -1747,4 +1784,13 @@
/*package*/ void clearSADevices() {
mSADevices.clear();
}
+
+ /*package*/ synchronized void forceStateForTest(int state) {
+ mState = state;
+ }
+
+ /*package*/ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
+ mBinauralSupported = hasBinaural;
+ mTransauralSupported = hasTransaural;
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1e9352d1..b25206d 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -271,6 +271,13 @@
static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
/**
+ * Default keepalive value to consider long-lived TCP connections are expensive on the
+ * VPN network from battery usage point of view.
+ * TODO: consider reading from setting.
+ */
+ @VisibleForTesting
+ static final int DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC = 60;
+ /**
* Prefer using {@link IkeSessionParams.ESP_IP_VERSION_AUTO} and
* {@link IkeSessionParams.ESP_ENCAP_TYPE_AUTO} for ESP packets.
*
@@ -358,9 +365,8 @@
return mVpnProfileStore;
}
- private static final int MAX_EVENTS_LOGS = 20;
- private final LocalLog mUnderlyNetworkChanges = new LocalLog(MAX_EVENTS_LOGS);
- private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS);
+ private static final int MAX_EVENTS_LOGS = 100;
+ private final LocalLog mEventChanges = new LocalLog(MAX_EVENTS_LOGS);
/**
* Cached Map of <subscription ID, CarrierConfigInfo> since retrieving the PersistableBundle
@@ -950,7 +956,7 @@
int errorCode, @NonNull final String packageName, @Nullable final String sessionKey,
@NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork,
@Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) {
- mVpnManagerEvents.log("Event class=" + getVpnManagerEventClassName(errorClass)
+ mEventChanges.log("[VMEvent] Event class=" + getVpnManagerEventClassName(errorClass)
+ ", err=" + getVpnManagerEventErrorName(errorCode) + " for " + packageName
+ " on session " + sessionKey);
final Intent intent = buildVpnManagerEventIntent(category, errorClass, errorCode,
@@ -1100,6 +1106,8 @@
mLockdownAllowlist = (mLockdown && lockdownAllowlist != null)
? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist))
: Collections.emptyList();
+ mEventChanges.log("[LockdownAlwaysOn] Mode changed: lockdown=" + mLockdown + " alwaysOn="
+ + mAlwaysOn + " calling from " + Binder.getCallingUid());
if (isCurrentPreparedPackage(packageName)) {
updateAlwaysOnNotification(mNetworkInfo.getDetailedState());
@@ -1670,9 +1678,12 @@
capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
- capsBuilder.setTransportInfo(
- new VpnTransportInfo(getActiveVpnType(), mConfig.session, mConfig.allowBypass,
- false /* longLivedTcpConnectionsExpensive */));
+ final boolean expensive = areLongLivedTcpConnectionsExpensive(mVpnRunner);
+ capsBuilder.setTransportInfo(new VpnTransportInfo(
+ getActiveVpnType(),
+ mConfig.session,
+ mConfig.allowBypass,
+ expensive));
// Only apps targeting Q and above can explicitly declare themselves as metered.
// These VPNs are assumed metered unless they state otherwise.
@@ -1704,6 +1715,17 @@
updateState(DetailedState.CONNECTED, "agentConnect");
}
+ private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) {
+ if (!(runner instanceof IkeV2VpnRunner)) return false;
+
+ final int delay = ((IkeV2VpnRunner) runner).getOrGuessKeepaliveDelaySeconds();
+ return areLongLivedTcpConnectionsExpensive(delay);
+ }
+
+ private static boolean areLongLivedTcpConnectionsExpensive(int keepaliveDelaySec) {
+ return keepaliveDelaySec < DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC;
+ }
+
private boolean canHaveRestrictedProfile(int userId) {
final long token = Binder.clearCallingIdentity();
try {
@@ -1715,7 +1737,7 @@
}
private void logUnderlyNetworkChanges(List<Network> networks) {
- mUnderlyNetworkChanges.log("Switch to "
+ mEventChanges.log("[UnderlyingNW] Switch to "
+ ((networks != null) ? TextUtils.join(", ", networks) : "null"));
}
@@ -2982,16 +3004,17 @@
@Override
public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
int specificCarrierId) {
+ mEventChanges.log("[CarrierConfig] Changed on slot " + slotIndex + " subId="
+ + subId + " carrerId=" + carrierId
+ + " specificCarrierId=" + specificCarrierId);
synchronized (Vpn.this) {
mCachedCarrierConfigInfoPerSubId.remove(subId);
// Ignore stale runner.
if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return;
- maybeMigrateIkeSession(mActiveNetwork);
+ maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork);
}
- // TODO: update the longLivedTcpConnectionsExpensive value in the
- // networkcapabilities of the VPN network.
}
};
@@ -3074,6 +3097,8 @@
*/
public void onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration) {
if (!isActiveToken(token)) {
+ mEventChanges.log("[IKEEvent-" + mSessionKey + "] onIkeOpened obsolete token="
+ + token);
Log.d(TAG, "onIkeOpened called for obsolete token " + token);
return;
}
@@ -3081,7 +3106,12 @@
mMobikeEnabled =
ikeConfiguration.isIkeExtensionEnabled(
IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE);
- onIkeConnectionInfoChanged(token, ikeConfiguration.getIkeSessionConnectionInfo());
+ final IkeSessionConnectionInfo info = ikeConfiguration.getIkeSessionConnectionInfo();
+ mEventChanges.log("[IKEEvent-" + mSessionKey + "] onIkeOpened token=" + token
+ + ", localAddr=" + info.getLocalAddress()
+ + ", network=" + info.getNetwork()
+ + ", mobikeEnabled= " + mMobikeEnabled);
+ onIkeConnectionInfoChanged(token, info);
}
/**
@@ -3094,11 +3124,17 @@
*/
public void onIkeConnectionInfoChanged(
int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) {
+
if (!isActiveToken(token)) {
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onIkeConnectionInfoChanged obsolete token=" + token);
Log.d(TAG, "onIkeConnectionInfoChanged called for obsolete token " + token);
return;
}
-
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onIkeConnectionInfoChanged token=" + token
+ + ", localAddr=" + ikeConnectionInfo.getLocalAddress()
+ + ", network=" + ikeConnectionInfo.getNetwork());
// The update on VPN and the IPsec tunnel will be done when migration is fully complete
// in onChildMigrated
mIkeConnectionInfo = ikeConnectionInfo;
@@ -3112,6 +3148,8 @@
*/
public void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig) {
if (!isActiveToken(token)) {
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onChildOpened obsolete token=" + token);
Log.d(TAG, "onChildOpened called for obsolete token " + token);
// Do nothing; this signals that either: (1) a new/better Network was found,
@@ -3121,7 +3159,9 @@
// sessions are torn down via resetIkeState().
return;
}
-
+ mEventChanges.log("[IKEEvent-" + mSessionKey + "] onChildOpened token=" + token
+ + ", addr=" + TextUtils.join(", ", childConfig.getInternalAddresses())
+ + " dns=" + TextUtils.join(", ", childConfig.getInternalDnsServers()));
try {
final String interfaceName = mTunnelIface.getInterfaceName();
final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses();
@@ -3218,6 +3258,8 @@
public void onChildTransformCreated(
int token, @NonNull IpSecTransform transform, int direction) {
if (!isActiveToken(token)) {
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onChildTransformCreated obsolete token=" + token);
Log.d(TAG, "ChildTransformCreated for obsolete token " + token);
// Do nothing; this signals that either: (1) a new/better Network was found,
@@ -3227,7 +3269,9 @@
// sessions are torn down via resetIkeState().
return;
}
-
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onChildTransformCreated token=" + token + ", direction=" + direction
+ + ", transform=" + transform);
try {
mTunnelIface.setUnderlyingNetwork(mIkeConnectionInfo.getNetwork());
@@ -3252,10 +3296,14 @@
@NonNull IpSecTransform inTransform,
@NonNull IpSecTransform outTransform) {
if (!isActiveToken(token)) {
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onChildMigrated obsolete token=" + token);
Log.d(TAG, "onChildMigrated for obsolete token " + token);
return;
}
-
+ mEventChanges.log("[IKEEvent-" + mSessionKey
+ + "] onChildMigrated token=" + token
+ + ", in=" + inTransform + ", out=" + outTransform);
// The actual network of this IKE session has migrated to is
// mIkeConnectionInfo.getNetwork() instead of mActiveNetwork because mActiveNetwork
// might have been updated after the migration was triggered.
@@ -3442,7 +3490,7 @@
return;
}
- if (maybeMigrateIkeSession(underlyingNetwork)) return;
+ if (maybeMigrateIkeSessionAndUpdateVpnTransportInfo(underlyingNetwork)) return;
startIkeSession(underlyingNetwork);
}
@@ -3549,7 +3597,43 @@
return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion);
}
- boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
+ private int getOrGuessKeepaliveDelaySeconds() {
+ if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
+ return guessNattKeepaliveTimerForNetwork();
+ } else if (mProfile.getIkeTunnelConnectionParams() != null) {
+ return mProfile.getIkeTunnelConnectionParams()
+ .getIkeSessionParams().getNattKeepAliveDelaySeconds();
+ }
+ return DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+ }
+
+ boolean maybeMigrateIkeSessionAndUpdateVpnTransportInfo(
+ @NonNull Network underlyingNetwork) {
+ final int keepaliveDelaySec = getOrGuessKeepaliveDelaySeconds();
+ final boolean migrated = maybeMigrateIkeSession(underlyingNetwork, keepaliveDelaySec);
+ if (migrated) {
+ updateVpnTransportInfoAndNetCap(keepaliveDelaySec);
+ }
+ return migrated;
+ }
+
+ public void updateVpnTransportInfoAndNetCap(int keepaliveDelaySec) {
+ final VpnTransportInfo info = new VpnTransportInfo(
+ getActiveVpnType(),
+ mConfig.session,
+ mConfig.allowBypass,
+ areLongLivedTcpConnectionsExpensive(keepaliveDelaySec));
+ final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo());
+ if (ncUpdateRequired) {
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setTransportInfo(info)
+ .build();
+ doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities);
+ }
+ }
+
+ private boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork,
+ int keepaliveDelaySeconds) {
if (mSession == null || !mMobikeEnabled) return false;
// IKE session can schedule a migration event only when IKE AUTH is finished
@@ -3574,15 +3658,6 @@
encapType = ESP_ENCAP_TYPE_AUTO;
}
- final int keepaliveDelaySeconds;
- if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
- keepaliveDelaySeconds = guessNattKeepaliveTimerForNetwork();
- } else if (mProfile.getIkeTunnelConnectionParams() != null) {
- keepaliveDelaySeconds = mProfile.getIkeTunnelConnectionParams()
- .getIkeSessionParams().getNattKeepAliveDelaySeconds();
- } else {
- keepaliveDelaySeconds = DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
- }
mSession.setNetwork(underlyingNetwork, ipVersion, encapType, keepaliveDelaySeconds);
return true;
}
@@ -3656,6 +3731,8 @@
/** Called when the NetworkCapabilities of underlying network is changed */
public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
+ mEventChanges.log("[UnderlyingNW] Cap changed from "
+ + mUnderlyingNetworkCapabilities + " to " + nc);
final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities;
mUnderlyingNetworkCapabilities = nc;
if (oldNc == null) {
@@ -3663,12 +3740,14 @@
startOrMigrateIkeSession(mActiveNetwork);
} else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) {
// Renew carrierConfig values.
- maybeMigrateIkeSession(mActiveNetwork);
+ maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork);
}
}
/** Called when the LinkProperties of underlying network is changed */
public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) {
+ mEventChanges.log("[UnderlyingNW] Lp changed from "
+ + mUnderlyingLinkProperties + " to " + lp);
mUnderlyingLinkProperties = lp;
}
@@ -3691,7 +3770,7 @@
Log.d(TAG, "Data stall suspected");
// Trigger MOBIKE.
- maybeMigrateIkeSession(mActiveNetwork);
+ maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork);
mDataStallSuspected = true;
}
}
@@ -4673,7 +4752,7 @@
// TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
// ConnectivityServiceTest.
if (SdkLevel.isAtLeastT()) {
- mVpnManagerEvents.log(packageName + " stopped");
+ mEventChanges.log("[VMEvent] " + packageName + " stopped");
sendEventToVpnManagerApp(intent, packageName);
}
}
@@ -5007,23 +5086,21 @@
pw.println("NetworkCapabilities: " + mNetworkCapabilities);
if (isIkev2VpnRunner()) {
final IkeV2VpnRunner runner = ((IkeV2VpnRunner) mVpnRunner);
- pw.println("Token: " + runner.mSessionKey);
+ pw.println("SessionKey: " + runner.mSessionKey);
pw.println("MOBIKE " + (runner.mMobikeEnabled ? "enabled" : "disabled"));
+ pw.println("Profile: " + runner.mProfile);
+ pw.println("Token: " + runner.mCurrentToken);
if (mDataStallSuspected) pw.println("Data stall suspected");
if (runner.mScheduledHandleDataStallFuture != null) {
pw.println("Reset session scheduled");
}
}
+ pw.println();
pw.println("mCachedCarrierConfigInfoPerSubId=" + mCachedCarrierConfigInfoPerSubId);
- pw.println("mUnderlyNetworkChanges (most recent first):");
+ pw.println("mEventChanges (most recent first):");
pw.increaseIndent();
- mUnderlyNetworkChanges.reverseDump(pw);
- pw.decreaseIndent();
-
- pw.println("mVpnManagerEvent (most recent first):");
- pw.increaseIndent();
- mVpnManagerEvents.reverseDump(pw);
+ mEventChanges.reverseDump(pw);
pw.decreaseIndent();
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 8b579ac..6cc89b8 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -883,7 +883,7 @@
if (mLoggingEnabled) {
Slog.d(TAG, "updateAmbientLux: "
+ ((mFastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
- + "mBrighteningLuxThreshold=" + mAmbientBrighteningThreshold + ", "
+ + "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
+ "mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold + ", "
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
+ "mAmbientLux=" + mAmbientLux);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
index 01b2cb9..1e41886 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
+++ b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
index 428eaff..3ad24de 100644
--- a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
@@ -17,12 +17,17 @@
import com.android.server.audio.SpatializerHelper.SADeviceState;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
import android.media.AudioSystem;
import android.util.Log;
@@ -36,6 +41,7 @@
import org.mockito.Mock;
import org.mockito.Spy;
+import java.util.ArrayList;
import java.util.List;
@MediumTest
@@ -49,14 +55,35 @@
@Mock private AudioService mMockAudioService;
@Spy private AudioSystemAdapter mSpyAudioSystem;
+ @Mock private AudioSystemAdapter mMockAudioSystem;
@Before
public void setUp() throws Exception {
mMockAudioService = mock(AudioService.class);
- mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+ }
- mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
- false /*headTrackingEnabledByDefault*/);
+ /**
+ * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy
+ * AudioSystemAdapter
+ * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use
+ * the mock adapter, mMockAudioSystem.
+ */
+ private void setUpSpatHelper(boolean useSpyAudioSystem) {
+ final AudioSystemAdapter asAdapter;
+ if (useSpyAudioSystem) {
+ mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+ asAdapter = mSpyAudioSystem;
+ mMockAudioSystem = null;
+ } else {
+ mSpyAudioSystem = null;
+ mMockAudioSystem = mock(NoOpAudioSystemAdapter.class);
+ asAdapter = mMockAudioSystem;
+ }
+ mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter,
+ true /*binauralEnabledDefault*/,
+ true /*transauralEnabledDefault*/,
+ false /*headTrackingEnabledDefault*/);
+
}
/**
@@ -66,6 +93,7 @@
*/
@Test
public void testSADeviceStateNullAddressCtor() throws Exception {
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
try {
SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null);
@@ -76,6 +104,7 @@
@Test
public void testSADeviceStateStringSerialization() throws Exception {
Log.i(TAG, "starting testSADeviceStateStringSerialization");
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
final SADeviceState devState = new SADeviceState(
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla");
devState.mHasHeadTracker = false;
@@ -91,6 +120,7 @@
@Test
public void testSADeviceSettings() throws Exception {
Log.i(TAG, "starting testSADeviceSettings");
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
final AudioDeviceAttributes dev1 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
final AudioDeviceAttributes dev2 =
@@ -141,4 +171,34 @@
Log.i(TAG, "device settingsRestored: " + settingsRestored);
Assert.assertEquals(settings, settingsRestored);
}
+
+ /**
+ * Test that null devices for routing do not break canBeSpatialized
+ * @throws Exception
+ */
+ @Test
+ public void testNoRoutingCanBeSpatialized() throws Exception {
+ Log.i(TAG, "Starting testNoRoutingCanBeSpatialized");
+ setUpSpatHelper(false /*useSpyAudioSystem*/);
+ mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE);
+
+ final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0);
+ final ArrayList<AudioDeviceAttributes> listWithNull = new ArrayList<>(1);
+ listWithNull.add(null);
+ final AudioAttributes media = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA).build();
+ final AudioFormat spatialFormat = new AudioFormat.Builder()
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build();
+
+ when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ .thenReturn(emptyList);
+ Assert.assertFalse("can be spatialized on empty routing",
+ mSpatHelper.canBeSpatialized(media, spatialFormat));
+
+ when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ .thenReturn(listWithNull);
+ Assert.assertFalse("can be spatialized on null routing",
+ mSpatHelper.canBeSpatialized(media, spatialFormat));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
index 33385af..1e41886 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
@@ -1 +1 @@
-include /media/aidl/android/media/soundtrigger_middleware/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/services/voiceinteraction/OWNERS b/services/voiceinteraction/OWNERS
index ef1061b..40e8d26 100644
--- a/services/voiceinteraction/OWNERS
+++ b/services/voiceinteraction/OWNERS
@@ -1 +1,2 @@
include /core/java/android/service/voice/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
index 01b2cb9..1e41886 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index fdf69430..f90eabc 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
@@ -822,4 +823,35 @@
}
return Integer.MAX_VALUE;
}
+
+ /**
+ * Check if calling user is associated with the given subscription.
+ * @param context Context
+ * @param subId subscription ID
+ * @param callerUserHandle caller user handle
+ * @return false if user is not associated with the subscription.
+ */
+ public static boolean checkSubscriptionAssociatedWithUser(@NonNull Context context, int subId,
+ @NonNull UserHandle callerUserHandle) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ // No subscription on device, return true.
+ return true;
+ }
+
+ SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if ((subManager != null) &&
+ (!subManager.isSubscriptionAssociatedWithUser(subId, callerUserHandle))) {
+ // If subId is not associated with calling user, return false.
+ Log.e(LOG_TAG,"User[User ID:" + callerUserHandle.getIdentifier()
+ + "] is not associated with Subscription ID:" + subId);
+ return false;
+
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f570f87..17780af 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4478,6 +4478,57 @@
"data_stall_recovery_should_skip_bool_array";
/**
+ * String array containing the list of names for service numbers provided by carriers. This key
+ * should be used with {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY}. The names provided in
+ * this array will be mapped 1:1 with the numbers provided in the {@link
+ * #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} array.
+ *
+ * <p>The data would be considered valid if and only if:
+ *
+ * <ul>
+ * <li>The number of items in both the arrays are equal
+ * <li>The data added to the {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} array is valid.
+ * See {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} for more information.
+ * </ul>
+ *
+ * <p>Example:
+ *
+ * <pre><code>
+ * <string-array name="carrier_service_name_array" num="2">
+ * <item value="Police"/>
+ * <item value="Ambulance"/>
+ * </string-array>
+ * </code></pre>
+ */
+ public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
+
+ /**
+ * String array containing the list of service numbers provided by carriers. This key should be
+ * used with {@link #KEY_CARRIER_SERVICE_NAME_STRING_ARRAY}. The numbers provided in this array
+ * will be mapped 1:1 with the names provided in the {@link
+ * #KEY_CARRIER_SERVICE_NAME_STRING_ARRAY} array.
+ *
+ * <p>The data would be considered valid if and only if:
+ *
+ * <ul>
+ * <li>The number of items in both the arrays are equal
+ * <li>The item added in this key follows a specific format. Either it should be all numbers,
+ * or "+" followed by all numbers.
+ * </ul>
+ *
+ * <p>Example:
+ *
+ * <pre><code>
+ * <string-array name="carrier_service_number_array" num="2">
+ * <item value="123"/>
+ * <item value="+343"/>
+ * </string-array>
+ * </code></pre>
+ */
+ public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY =
+ "carrier_service_number_array";
+
+ /**
* Configs used by ImsServiceEntitlement.
*/
public static final class ImsServiceEntitlement {
@@ -9350,6 +9401,8 @@
new long[] {180000, 180000, 180000, 180000});
sDefaults.putBooleanArray(KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY,
new boolean[] {false, false, true, false, false});
+ sDefaults.putStringArray(KEY_CARRIER_SERVICE_NAME_STRING_ARRAY, new String[0]);
+ sDefaults.putStringArray(KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY, new String[0]);
}
/**
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 1d6798b..f1f13bc 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -184,10 +184,11 @@
private final int mTransportType;
/**
- * The initial registration state
+ * The true registration state of network, This is not affected by any carrier config or
+ * resource overlay.
*/
@RegistrationState
- private final int mInitialRegistrationState;
+ private final int mNetworkRegistrationState;
/**
* The registration state that might have been overridden by config
@@ -264,7 +265,7 @@
mDomain = domain;
mTransportType = transportType;
mRegistrationState = registrationState;
- mInitialRegistrationState = registrationState;
+ mNetworkRegistrationState = registrationState;
mRoamingType = (registrationState == REGISTRATION_STATE_ROAMING)
? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
setAccessNetworkTechnology(accessNetworkTechnology);
@@ -320,7 +321,7 @@
mDomain = source.readInt();
mTransportType = source.readInt();
mRegistrationState = source.readInt();
- mInitialRegistrationState = source.readInt();
+ mNetworkRegistrationState = source.readInt();
mRoamingType = source.readInt();
mAccessNetworkTechnology = source.readInt();
mRejectCause = source.readInt();
@@ -347,7 +348,7 @@
mDomain = nri.mDomain;
mTransportType = nri.mTransportType;
mRegistrationState = nri.mRegistrationState;
- mInitialRegistrationState = nri.mInitialRegistrationState;
+ mNetworkRegistrationState = nri.mNetworkRegistrationState;
mRoamingType = nri.mRoamingType;
mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
mIsUsingCarrierAggregation = nri.mIsUsingCarrierAggregation;
@@ -400,40 +401,72 @@
}
/**
- * @return The registration state.
+ * @return The registration state. Note this value can be affected by the carrier config
+ * override.
*
+ * @deprecated Use {@link #getNetworkRegistrationState}, which is not affected by any carrier
+ * config or resource overlay, instead.
* @hide
*/
+ @Deprecated
@SystemApi
public @RegistrationState int getRegistrationState() {
return mRegistrationState;
}
/**
- * @return The initial registration state.
+ * @return The true registration state of network. (This value is not affected by any carrier
+ * config or resource overlay override).
*
* @hide
*/
- public @RegistrationState int getInitialRegistrationState() {
- return mInitialRegistrationState;
+ @SystemApi
+ public @RegistrationState int getNetworkRegistrationState() {
+ return mNetworkRegistrationState;
}
/**
- * @return {@code true} if registered on roaming or home network, {@code false} otherwise.
+ * @return {@code true} if registered on roaming or home network. Note this value can be
+ * affected by the carrier config override.
+ *
+ * @deprecated Use {@link #isNetworkRegistered}, which is not affected by any carrier config or
+ * resource overlay, instead.
*/
+ @Deprecated
public boolean isRegistered() {
return mRegistrationState == REGISTRATION_STATE_HOME
|| mRegistrationState == REGISTRATION_STATE_ROAMING;
}
/**
- * @return {@code true} if searching for service, {@code false} otherwise.
+ * @return {@code true} if registered on roaming or home network, {@code false} otherwise. (This
+ * value is not affected by any carrier config or resource overlay override).
*/
+ public boolean isNetworkRegistered() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_HOME
+ || mNetworkRegistrationState == REGISTRATION_STATE_ROAMING;
+ }
+
+ /**
+ * @return {@code true} if searching for service, {@code false} otherwise.
+ *
+ * @deprecated Use {@link #isNetworkRegistered}, which is not affected by any carrier config or
+ * resource overlay, instead.
+ */
+ @Deprecated
public boolean isSearching() {
return mRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
}
/**
+ * @return {@code true} if searching for service, {@code false} otherwise. (This value is not
+ * affected by any carrier config or resource overlay override).
+ */
+ public boolean isNetworkSearching() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
+ }
+
+ /**
* Get the PLMN-ID for this Network Registration, also known as the RPLMN.
*
* <p>If the device is registered, this will return the registered PLMN-ID. If registration
@@ -450,13 +483,25 @@
}
/**
- * @return {@code true} if registered on roaming network, {@code false} otherwise.
+ * @return {@code true} if registered on roaming network overridden by config. Note this value
+ * can be affected by the carrier config override.
+ *
+ * @deprecated Use {@link TelephonyDisplayInfo#isRoaming} instead.
*/
+ @Deprecated
public boolean isRoaming() {
return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
}
/**
+ * @return {@code true} if registered on roaming network. (This value is not affected by any
+ * carrier config or resource overlay override).
+ */
+ public boolean isNetworkRoaming() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_ROAMING;
+ }
+
+ /**
* @hide
* @return {@code true} if in service.
*/
@@ -486,7 +531,8 @@
}
/**
- * @return the current network roaming type.
+ * @return the current network roaming type. Note that this value can be possibly overridden by
+ * the carrier config or resource overlay.
* @hide
*/
@SystemApi
@@ -666,8 +712,8 @@
.append(" transportType=").append(
AccessNetworkConstants.transportTypeToString(mTransportType))
.append(" registrationState=").append(registrationStateToString(mRegistrationState))
- .append(" mInitialRegistrationState=")
- .append(registrationStateToString(mInitialRegistrationState))
+ .append(" networkRegistrationState=")
+ .append(registrationStateToString(mNetworkRegistrationState))
.append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
.append(" accessNetworkTechnology=")
.append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
@@ -688,7 +734,7 @@
@Override
public int hashCode() {
- return Objects.hash(mDomain, mTransportType, mRegistrationState, mInitialRegistrationState,
+ return Objects.hash(mDomain, mTransportType, mRegistrationState, mNetworkRegistrationState,
mRoamingType, mAccessNetworkTechnology, mRejectCause, mEmergencyOnly,
mAvailableServices, mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState,
mRplmn, mIsUsingCarrierAggregation);
@@ -706,7 +752,7 @@
return mDomain == other.mDomain
&& mTransportType == other.mTransportType
&& mRegistrationState == other.mRegistrationState
- && mInitialRegistrationState == other.mInitialRegistrationState
+ && mNetworkRegistrationState == other.mNetworkRegistrationState
&& mRoamingType == other.mRoamingType
&& mAccessNetworkTechnology == other.mAccessNetworkTechnology
&& mRejectCause == other.mRejectCause
@@ -729,7 +775,7 @@
dest.writeInt(mDomain);
dest.writeInt(mTransportType);
dest.writeInt(mRegistrationState);
- dest.writeInt(mInitialRegistrationState);
+ dest.writeInt(mNetworkRegistrationState);
dest.writeInt(mRoamingType);
dest.writeInt(mAccessNetworkTechnology);
dest.writeInt(mRejectCause);
@@ -826,7 +872,7 @@
private int mTransportType;
@RegistrationState
- private int mInitialRegistrationState;
+ private int mNetworkRegistrationState;
@NetworkType
private int mAccessNetworkTechnology;
@@ -856,6 +902,31 @@
public Builder() {}
/**
+ * Builder from the existing {@link NetworkRegistrationInfo}.
+ *
+ * @param nri The network registration info object.
+ * @hide
+ */
+ public Builder(@NonNull NetworkRegistrationInfo nri) {
+ mDomain = nri.mDomain;
+ mTransportType = nri.mTransportType;
+ mNetworkRegistrationState = nri.mNetworkRegistrationState;
+ mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
+ mRejectCause = nri.mRejectCause;
+ mEmergencyOnly = nri.mEmergencyOnly;
+ mAvailableServices = new ArrayList<>(nri.mAvailableServices);
+ mCellIdentity = nri.mCellIdentity;
+ if (nri.mDataSpecificInfo != null) {
+ mDataSpecificRegistrationInfo = new DataSpecificRegistrationInfo(
+ nri.mDataSpecificInfo);
+ }
+ if (nri.mVoiceSpecificInfo != null) {
+ mVoiceSpecificRegistrationInfo = new VoiceSpecificRegistrationInfo(
+ nri.mVoiceSpecificInfo);
+ }
+ }
+
+ /**
* Set the network domain.
*
* @param domain Network domain.
@@ -887,7 +958,7 @@
* @return The same instance of the builder.
*/
public @NonNull Builder setRegistrationState(@RegistrationState int registrationState) {
- mInitialRegistrationState = registrationState;
+ mNetworkRegistrationState = registrationState;
return this;
}
@@ -1006,7 +1077,7 @@
*/
@SystemApi
public @NonNull NetworkRegistrationInfo build() {
- return new NetworkRegistrationInfo(mDomain, mTransportType, mInitialRegistrationState,
+ return new NetworkRegistrationInfo(mDomain, mTransportType, mNetworkRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
mCellIdentity, mRplmn, mVoiceSpecificRegistrationInfo,
mDataSpecificRegistrationInfo);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ac74016..03e019d 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -631,11 +631,17 @@
}
/**
- * Get current roaming indicator of phone
+ * Get current roaming indicator of phone. This roaming state could be overridden by the carrier
+ * config.
* (note: not just decoding from TS 27.007 7.2)
- *
+ * @see TelephonyDisplayInfo#isRoaming() for visualization purpose.
* @return true if TS 27.007 7.2 roaming is true
* and ONS is different from SPN
+ * @see CarrierConfigManager#KEY_FORCE_HOME_NETWORK_BOOL
+ * @see CarrierConfigManager#KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY
*/
public boolean getRoaming() {
return getVoiceRoaming() || getDataRoaming();
@@ -650,8 +656,9 @@
public boolean getVoiceRoaming() {
return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
+
/**
- * Get current voice network roaming type
+ * Get current voice roaming type. This roaming type could be overridden by the carrier config.
* @return roaming type
* @hide
*/
@@ -701,7 +708,7 @@
}
/**
- * Get current data network roaming type
+ * Get current data roaming type. This roaming type could be overridden by the carrier config.
* @return roaming type
* @hide
*/
@@ -1207,8 +1214,13 @@
/**
* Initialize the service state. Set everything to the default value.
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * {@link NetworkRegistrationInfo}.
*/
- private void init() {
+ private void init(boolean legacyMode) {
if (DBG) Rlog.d(LOG_TAG, "init");
mVoiceRegState = STATE_OUT_OF_SERVICE;
mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1240,11 +1252,13 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
- addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
- .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
- .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
- .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
- .build());
+ if (!legacyMode) {
+ addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+ .build());
+ }
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
@@ -1253,11 +1267,11 @@
}
public void setStateOutOfService() {
- init();
+ init(true);
}
public void setStateOff() {
- init();
+ init(true);
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
}
@@ -1265,11 +1279,14 @@
/**
* Set the service state to out-of-service
*
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
* @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
* @hide
*/
- public void setOutOfService(boolean powerOff) {
- init();
+ public void setOutOfService(boolean legacyMode, boolean powerOff) {
+ init(legacyMode);
if (powerOff) {
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index d670e55..1cf2969 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2245,6 +2245,7 @@
RESULT_SMS_SEND_RETRY_FAILED,
RESULT_REMOTE_EXCEPTION,
RESULT_NO_DEFAULT_SMS_APP,
+ RESULT_USER_NOT_ALLOWED,
RESULT_RIL_RADIO_NOT_AVAILABLE,
RESULT_RIL_SMS_SEND_FAIL_RETRY,
RESULT_RIL_NETWORK_REJECT,
@@ -2425,6 +2426,13 @@
*/
public static final int RESULT_NO_DEFAULT_SMS_APP = 32;
+ /**
+ * User is not associated with the subscription.
+ * TODO(b/263279115): Make this error code public.
+ * @hide
+ */
+ public static final int RESULT_USER_NOT_ALLOWED = 33;
+
// Radio Error results
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 37bfa72..b99f3d6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -4394,5 +4394,70 @@
}
return null;
}
+
+ /**
+ * Check if subscription and user are associated with each other.
+ *
+ * @param subscriptionId the subId of the subscription
+ * @param userHandle user handle of the user
+ * @return {@code true} if subscription is associated with user
+ * {code true} if there are no subscriptions on device
+ * else {@code false} if subscription is not associated with user.
+ *
+ * @throws IllegalArgumentException if subscription is invalid.
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @throws IllegalStateException if subscription service is not available.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
+ public boolean isSubscriptionAssociatedWithUser(int subscriptionId,
+ @NonNull UserHandle userHandle) {
+ if (!isValidSubscriptionId(subscriptionId)) {
+ throw new IllegalArgumentException("[isSubscriptionAssociatedWithUser]: "
+ + "Invalid subscriptionId: " + subscriptionId);
+ }
+
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ return iSub.isSubscriptionAssociatedWithUser(subscriptionId, userHandle);
+ } else {
+ throw new IllegalStateException("[isSubscriptionAssociatedWithUser]: "
+ + "subscription service unavailable");
+ }
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ return false;
+ }
+
+ /**
+ * Get list of subscriptions associated with user.
+ *
+ * @param userHandle user handle of the user
+ * @return list of subscriptionInfo associated with the user.
+ *
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @throws IllegalStateException if subscription service is not available.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
+ public @NonNull List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(
+ @NonNull UserHandle userHandle) {
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ return iSub.getSubscriptionInfoListAssociatedWithUser(userHandle);
+ } else {
+ throw new IllegalStateException("[getSubscriptionInfoListAssociatedWithUser]: "
+ + "subscription service unavailable");
+ }
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ return new ArrayList<>();
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java
index f4e2ade..e01b10e 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -87,10 +87,12 @@
public static final int OVERRIDE_NETWORK_TYPE_NR_ADVANCED = 5;
@NetworkType
- private final int mNetworkType;
+ private final int mNetworkType;
@OverrideNetworkType
- private final int mOverrideNetworkType;
+ private final int mOverrideNetworkType;
+
+ private final boolean mIsRoaming;
/**
* Constructor
@@ -98,18 +100,37 @@
* @param networkType Current packet-switching cellular network type
* @param overrideNetworkType The override network type
*
+ * @deprecated will not use this constructor anymore.
+ * @hide
+ */
+ @Deprecated
+ public TelephonyDisplayInfo(@NetworkType int networkType,
+ @OverrideNetworkType int overrideNetworkType) {
+ this(networkType, overrideNetworkType, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param networkType Current packet-switching cellular network type
+ * @param overrideNetworkType The override network type
+ * @param isRoaming True if the device is roaming after override.
+ *
* @hide
*/
public TelephonyDisplayInfo(@NetworkType int networkType,
- @OverrideNetworkType int overrideNetworkType) {
+ @OverrideNetworkType int overrideNetworkType,
+ boolean isRoaming) {
mNetworkType = networkType;
mOverrideNetworkType = overrideNetworkType;
+ mIsRoaming = isRoaming;
}
/** @hide */
public TelephonyDisplayInfo(Parcel p) {
mNetworkType = p.readInt();
mOverrideNetworkType = p.readInt();
+ mIsRoaming = p.readBoolean();
}
/**
@@ -135,10 +156,25 @@
return mOverrideNetworkType;
}
+ /**
+ * Get device is roaming or not. Note the isRoaming is for market branding or visualization
+ * purposes only. It cannot be treated as the actual roaming device is camped on.
+ *
+ * @return True if the device is registered on roaming network overridden by config.
+ * @see CarrierConfigManager#KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY
+ */
+ public boolean isRoaming() {
+ return mIsRoaming;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mNetworkType);
dest.writeInt(mOverrideNetworkType);
+ dest.writeBoolean(mIsRoaming);
}
public static final @NonNull Parcelable.Creator<TelephonyDisplayInfo> CREATOR =
@@ -165,12 +201,13 @@
if (o == null || getClass() != o.getClass()) return false;
TelephonyDisplayInfo that = (TelephonyDisplayInfo) o;
return mNetworkType == that.mNetworkType
- && mOverrideNetworkType == that.mOverrideNetworkType;
+ && mOverrideNetworkType == that.mOverrideNetworkType
+ && mIsRoaming == that.mIsRoaming;
}
@Override
public int hashCode() {
- return Objects.hash(mNetworkType, mOverrideNetworkType);
+ return Objects.hash(mNetworkType, mOverrideNetworkType, mIsRoaming);
}
/**
@@ -195,6 +232,7 @@
@Override
public String toString() {
return "TelephonyDisplayInfo {network=" + TelephonyManager.getNetworkTypeName(mNetworkType)
- + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType) + "}";
+ + ", overrideNetwork=" + overrideNetworkTypeToString(mOverrideNetworkType)
+ + ", isRoaming=" + mIsRoaming + "}";
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d23b75b..fd5ec25 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17027,4 +17027,44 @@
}
return TelephonyManager.SIM_STATE_UNKNOWN;
}
+
+ /**
+ * Convert SIM state into string.
+ *
+ * @param state SIM state.
+ * @return SIM state in string format.
+ *
+ * @hide
+ */
+ @NonNull
+ public static String simStateToString(@SimState int state) {
+ switch (state) {
+ case TelephonyManager.SIM_STATE_UNKNOWN:
+ return "UNKNOWN";
+ case TelephonyManager.SIM_STATE_ABSENT:
+ return "ABSENT";
+ case TelephonyManager.SIM_STATE_PIN_REQUIRED:
+ return "PIN_REQUIRED";
+ case TelephonyManager.SIM_STATE_PUK_REQUIRED:
+ return "PUK_REQUIRED";
+ case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
+ return "NETWORK_LOCKED";
+ case TelephonyManager.SIM_STATE_READY:
+ return "READY";
+ case TelephonyManager.SIM_STATE_NOT_READY:
+ return "NOT_READY";
+ case TelephonyManager.SIM_STATE_PERM_DISABLED:
+ return "PERM_DISABLED";
+ case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
+ return "CARD_IO_ERROR";
+ case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
+ return "CARD_RESTRICTED";
+ case TelephonyManager.SIM_STATE_LOADED:
+ return "LOADED";
+ case TelephonyManager.SIM_STATE_PRESENT:
+ return "PRESENT";
+ default:
+ return "UNKNOWN(" + state + ")";
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index c5f6902..25a714a 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -326,4 +326,34 @@
* @throws IllegalArgumentException if subId is invalid.
*/
UserHandle getSubscriptionUserHandle(int subId);
+
+ /**
+ * Check if subscription and user are associated with each other.
+ *
+ * @param subscriptionId the subId of the subscription
+ * @param userHandle user handle of the user
+ * @return {@code true} if subscription is associated with user
+ * {code true} if there are no subscriptions on device
+ * else {@code false} if subscription is not associated with user.
+ *
+ * @throws IllegalArgumentException if subscription is invalid.
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @throws IllegalStateException if subscription service is not available.
+ *
+ * @hide
+ */
+ boolean isSubscriptionAssociatedWithUser(int subscriptionId, in UserHandle userHandle);
+
+ /**
+ * Get list of subscriptions associated with user.
+ *
+ * @param userHandle user handle of the user
+ * @return list of subscriptionInfo associated with the user.
+ *
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @throws IllegalStateException if subscription service is not available.
+ *
+ * @hide
+ */
+ List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle);
}
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 9db19a3..a0fcfc5 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1,2 +1,2 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
mdooley@google.com
diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS
index 816bc6b..1e41886 100644
--- a/tests/SoundTriggerTests/OWNERS
+++ b/tests/SoundTriggerTests/OWNERS
@@ -1 +1 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
new file mode 100644
index 0000000..b94bb41
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
@@ -0,0 +1,64 @@
+/*
+ * 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.os.test;
+
+import static android.permission.PermissionManager.PERMISSION_GRANTED;
+import static android.permission.PermissionManager.PERMISSION_HARD_DENIED;
+
+import android.annotation.NonNull;
+import android.content.AttributionSource;
+import android.os.PermissionEnforcer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Fake for {@link PermissionEnforcer}. Useful for tests wanting to mock the
+ * permission checks of an AIDL service. FakePermissionEnforcer may be passed
+ * to the constructor of the AIDL-generated Stub class.
+ *
+ */
+public class FakePermissionEnforcer extends PermissionEnforcer {
+ private Set<String> mGranted;
+
+ public FakePermissionEnforcer() {
+ mGranted = new HashSet();
+ }
+
+ public void grant(String permission) {
+ mGranted.add(permission);
+ }
+
+ public void revoke(String permission) {
+ mGranted.remove(permission);
+ }
+
+ private boolean granted(String permission) {
+ return mGranted.contains(permission);
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission,
+ @NonNull AttributionSource source) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission, int pid, int uid) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+}
diff --git a/tests/utils/testutils/java/android/os/test/OWNERS b/tests/utils/testutils/java/android/os/test/OWNERS
new file mode 100644
index 0000000..3a9129e
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/OWNERS
@@ -0,0 +1 @@
+per-file FakePermissionEnforcer.java = file:/tests/EnforcePermission/OWNERS
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 075bc5e..4123f80 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -17,7 +17,9 @@
package com.android.server;
import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -67,7 +69,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -128,6 +129,15 @@
private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
+ private static final String TEST_IFACE_NAME = "TEST_IFACE";
+ private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2";
+ private static final LinkProperties TEST_LP_1 = new LinkProperties();
+ private static final LinkProperties TEST_LP_2 = new LinkProperties();
+
+ static {
+ TEST_LP_1.setInterfaceName(TEST_IFACE_NAME);
+ TEST_LP_2.setInterfaceName(TEST_IFACE_NAME_2);
+ }
static {
final Context mockConfigContext = mock(Context.class);
@@ -1034,8 +1044,7 @@
setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive);
return mVcnMgmtSvc.getUnderlyingNetworkPolicy(
- getNetworkCapabilitiesBuilderForTransport(subId, transport).build(),
- new LinkProperties());
+ getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), TEST_LP_1);
}
private void checkGetRestrictedTransportsFromCarrierConfig(
@@ -1260,7 +1269,7 @@
false /* expectRestricted */);
}
- private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
+ private void setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp) {
mVcnMgmtSvc.systemReady();
final ArgumentCaptor<NetworkCallback> captor =
@@ -1269,7 +1278,10 @@
.registerNetworkCallback(
eq(new NetworkRequest.Builder().clearCapabilities().build()),
captor.capture());
- captor.getValue().onCapabilitiesChanged(mock(Network.class, CALLS_REAL_METHODS), caps);
+
+ Network mockNetwork = mock(Network.class, CALLS_REAL_METHODS);
+ captor.getValue().onCapabilitiesChanged(mockNetwork, caps);
+ captor.getValue().onLinkPropertiesChanged(mockNetwork, lp);
}
@Test
@@ -1279,7 +1291,7 @@
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
// Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED
// immutable capability
@@ -1288,7 +1300,7 @@
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build(),
- new LinkProperties());
+ TEST_LP_1);
assertTrue(policy.isTeardownRequested());
}
@@ -1298,7 +1310,7 @@
final NetworkCapabilities existingNetworkCaps =
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
@@ -1315,7 +1327,7 @@
.addCapability(NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NET_CAPABILITY_IMS)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
final VcnUnderlyingNetworkPolicy policy =
mVcnMgmtSvc.getUnderlyingNetworkPolicy(
@@ -1336,7 +1348,7 @@
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
- .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID_2))
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
.build();
VcnUnderlyingNetworkPolicy policy =
@@ -1346,6 +1358,38 @@
assertEquals(nc, policy.getMergedNetworkCapabilities());
}
+ /**
+ * Checks that networks with similar capabilities do not clobber each other.
+ *
+ * <p>In previous iterations, the VcnMgmtSvc used capability-matching to check if a network
+ * undergoing policy checks were the same as an existing networks. However, this meant that if
+ * there were newly added capabilities that the VCN did not check, two networks differing only
+ * by that capability would restart each other constantly.
+ */
+ @Test
+ public void testGetUnderlyingNetworkPolicySimilarNetworks() throws Exception {
+ NetworkCapabilities nc1 =
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
+ .build();
+
+ NetworkCapabilities nc2 =
+ new NetworkCapabilities.Builder(nc1)
+ .addCapability(NET_CAPABILITY_ENTERPRISE)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+
+ setupTrackedNetwork(nc1, TEST_LP_1);
+
+ VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc2, TEST_LP_2);
+
+ assertFalse(policy.isTeardownRequested());
+ assertEquals(nc2, policy.getMergedNetworkCapabilities());
+ }
+
@Test(expected = SecurityException.class)
public void testGetUnderlyingNetworkPolicyInvalidPermission() {
doReturn(PackageManager.PERMISSION_DENIED)