summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TEST_MAPPING8
-rw-r--r--core/api/current.txt16
-rw-r--r--core/api/system-current.txt3
-rw-r--r--core/api/test-current.txt3
-rw-r--r--core/java/android/app/ActivityManager.java12
-rw-r--r--core/java/android/app/ActivityThread.java23
-rw-r--r--core/java/android/hardware/usb/UsbDeviceConnection.java4
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java13
-rw-r--r--core/java/android/os/RemoteException.java6
-rw-r--r--core/java/android/view/OWNERS3
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--keystore/java/android/security/KeyStore2.java16
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java66
-rw-r--r--keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java177
-rw-r--r--libs/hwui/Properties.cpp2
-rw-r--r--packages/CtsShim/Android.bp6
-rw-r--r--packages/PackageInstaller/AndroidManifest.xml4
-rw-r--r--packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/OWNERS5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt4
-rw-r--r--services/core/java/com/android/server/MmsServiceBroker.java9
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java3
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java36
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java5
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java9
-rw-r--r--services/core/java/com/android/server/audio/SpatializerHelper.java128
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java153
-rw-r--r--services/core/java/com/android/server/vcn/TEST_MAPPING10
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java66
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java32
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java53
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationInfo.java111
-rw-r--r--telephony/java/android/telephony/ServiceState.java15
-rw-r--r--telephony/java/android/telephony/SmsManager.java8
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java65
-rw-r--r--telephony/java/android/telephony/TelephonyDisplayInfo.java48
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java40
-rw-r--r--telephony/java/com/android/internal/telephony/ISub.aidl30
-rw-r--r--tests/vcn/java/com/android/server/VcnManagementServiceTest.java64
42 files changed, 1078 insertions, 192 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a48ce0ce1b6c..0ba24d112b63 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 b243374878fc..4c1594b19409 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -18727,8 +18727,8 @@ package android.hardware.usb {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 398b596e2621..821944f406cd 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12828,7 +12828,8 @@ package android.telephony {
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 7cfb66a3dcc6..6a5ef3a67488 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -141,8 +141,9 @@ package android.app {
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 eadf758e2b99..d328b34a2a8f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -643,9 +643,17 @@ public class ActivityManager {
@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 559989368a9f..5ba7a4cb4f54 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -238,6 +238,7 @@ import java.io.PrintWriter;
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 @@ public final class ActivityThread extends ClientTransactionHandler
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/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 7c2e518b8544..44144d92f56a 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -238,7 +238,7 @@ public class UsbDeviceConnection {
* 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 @@ public class UsbDeviceConnection {
* 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 a20191cab774..74775a820620 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -769,6 +769,19 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
}
}
+ @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 878e1413a8c9..970f4192c36c 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -21,6 +21,12 @@ import android.util.AndroidException;
/**
* 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 0c881567c6da..a3c278f487fc 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -60,6 +60,9 @@ per-file SurfaceView.java = file:/services/core/java/com/android/server/wm/OWNER
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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a5e96176ec4c..277bdf388188 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 c2cd6ffc622c..74597c5cd874 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -161,6 +161,15 @@ public class KeyStore2 {
}
/**
+ * 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 @@ public class KeyStore2 {
});
}
+ /**
+ * 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 91f216f1320a..045e318ff513 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -79,13 +79,11 @@ import java.security.spec.NamedParameterSpec;
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 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
}
}
- 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 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
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 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
+ "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 f96c39c879fd..1e1f68aaefc1 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.junit.Test;
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 @@ public class AndroidKeyStoreSpiTest {
@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 5a67eb9935dd..738f1ab0c18f 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -98,7 +98,7 @@ bool Properties::load() {
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/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp
index 31cd76079131..baafe7ba570c 100644
--- a/packages/CtsShim/Android.bp
+++ b/packages/CtsShim/Android.bp
@@ -44,6 +44,9 @@ android_app_import {
arm64: {
apk: "apk/arm/CtsShimPriv.apk",
},
+ riscv64: {
+ apk: "apk/riscv64/CtsShimPriv.apk",
+ },
x86: {
apk: "apk/x86/CtsShimPriv.apk",
},
@@ -82,6 +85,9 @@ android_app_import {
arm64: {
apk: "apk/arm/CtsShim.apk",
},
+ riscv64: {
+ apk: "apk/riscv64/CtsShim.apk",
+ },
x86: {
apk: "apk/x86/CtsShim.apk",
},
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 6669d6ba3085..868867de7b42 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 f305fd35b7d9..e92157e7c867 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 @@ import javax.tools.Diagnostic.Kind;
* 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 39b4b8e16708..35e3dd3379f0 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 class MobileStatusTracker {
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 ab9b5dc3ff7a..c01528fb4f18 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 ab9b5dc3ff7a..c01528fb4f18 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 2e6ea0e28d86..54946ee4e662 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 @@ public class InternetDialogController implements AccessPointController.AccessPoi
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 1fb6a982fdf3..c37b01fff578 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 @@ internal class MobileState(
) : 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 @@ internal class MobileState(
}
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 59db68691223..f149fda7a043 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.telephony.TelephonyManager;
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 @@ public class MmsServiceBroker extends SystemService {
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 a69d3f0276f3..77a54a568859 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1957,7 +1957,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
&& 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 f652cb050cbd..78d4708e70a2 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -1104,7 +1104,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
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 @@ public class VcnManagementService extends IVcnManagementService.Stub {
* 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 @@ public class VcnManagementService extends IVcnManagementService.Stub {
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/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index abddc4366460..256df98ae760 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 @@ public final class ProcessList {
+ ", " + 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 5ca03b8e6f8b..46ab3304c46e 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 @@ public class AudioService extends IAudioService.Stub
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();
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 2b566668a7c7..c9cdba970ccb 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 @@ public class SpatializerHelper {
};
// 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 @@ public class SpatializerHelper {
.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 @@ public class SpatializerHelper {
// 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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
}
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
}
/*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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
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 @@ public class SpatializerHelper {
/*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 1e9352d10956..b25206d3b621 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 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
}
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 @@ public class Vpn {
@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 class Vpn {
*/
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 @@ public class Vpn {
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 class Vpn {
*/
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 class Vpn {
*/
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 @@ public class Vpn {
// 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 class Vpn {
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 @@ public class Vpn {
// 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 @@ public class Vpn {
@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 @@ public class Vpn {
return;
}
- if (maybeMigrateIkeSession(underlyingNetwork)) return;
+ if (maybeMigrateIkeSessionAndUpdateVpnTransportInfo(underlyingNetwork)) return;
startIkeSession(underlyingNetwork);
}
@@ -3549,7 +3597,43 @@ public class Vpn {
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 @@ public class Vpn {
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 @@ public class Vpn {
/** 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 @@ public class Vpn {
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 @@ public class Vpn {
Log.d(TAG, "Data stall suspected");
// Trigger MOBIKE.
- maybeMigrateIkeSession(mActiveNetwork);
+ maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork);
mDataStallSuspected = true;
}
}
@@ -4673,7 +4752,7 @@ public class Vpn {
// 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 @@ public class Vpn {
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.increaseIndent();
- mUnderlyNetworkChanges.reverseDump(pw);
- pw.decreaseIndent();
-
- pw.println("mVpnManagerEvent (most recent first):");
+ pw.println("mEventChanges (most recent first):");
pw.increaseIndent();
- mVpnManagerEvents.reverseDump(pw);
+ mEventChanges.reverseDump(pw);
pw.decreaseIndent();
}
}
diff --git a/services/core/java/com/android/server/vcn/TEST_MAPPING b/services/core/java/com/android/server/vcn/TEST_MAPPING
new file mode 100644
index 000000000000..5b04d884fc1a
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksVcnTests"
+ },
+ {
+ "name": "CtsVcnTestCases"
+ }
+ ]
+} \ No newline at end of file
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 428eaff9e5bc..3ad24de4cdca 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 @@ package com.android.server.audio;
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.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
+import java.util.ArrayList;
import java.util.List;
@MediumTest
@@ -49,14 +55,35 @@ public class SpatializerHelperTest {
@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());
+ }
+
+ /**
+ * 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*/);
- mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
- false /*headTrackingEnabledByDefault*/);
}
/**
@@ -66,6 +93,7 @@ public class SpatializerHelperTest {
*/
@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 @@ public class SpatializerHelperTest {
@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 @@ public class SpatializerHelperTest {
@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 @@ public class SpatializerHelperTest {
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/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index fdf694303dbc..f90eabc7175e 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -18,6 +18,7 @@ package com.android.internal.telephony;
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 @@ public final class TelephonyPermissions {
}
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 f570f87f631c..17780af8061c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4478,6 +4478,57 @@ public class CarrierConfigManager {
"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 @@ public class CarrierConfigManager {
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 1d6798b7fc6e..f1f13bc6bb55 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -184,10 +184,11 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
}
/**
- * @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 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 @@ public final class NetworkRegistrationInfo implements Parcelable {
}
/**
- * @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 @@ public final class NetworkRegistrationInfo implements Parcelable {
}
/**
- * @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 @@ public final class NetworkRegistrationInfo implements Parcelable {
.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 @@ public final class NetworkRegistrationInfo implements Parcelable {
@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 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
private int mTransportType;
@RegistrationState
- private int mInitialRegistrationState;
+ private int mNetworkRegistrationState;
@NetworkType
private int mAccessNetworkTechnology;
@@ -856,6 +902,31 @@ public final class NetworkRegistrationInfo implements Parcelable {
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 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return The same instance of the builder.
*/
public @NonNull Builder setRegistrationState(@RegistrationState int registrationState) {
- mInitialRegistrationState = registrationState;
+ mNetworkRegistrationState = registrationState;
return this;
}
@@ -1006,7 +1077,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
*/
@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 ac740166a024..33e6fa70ffd1 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -631,11 +631,17 @@ public class ServiceState implements Parcelable {
}
/**
- * 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 class ServiceState implements Parcelable {
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 @@ public class ServiceState implements Parcelable {
}
/**
- * 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
*/
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index d670e5592c42..1cf2969ea9b5 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2245,6 +2245,7 @@ public final class SmsManager {
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 final class SmsManager {
*/
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 37bfa72f9394..b99f3d681585 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -4394,5 +4394,70 @@ public class SubscriptionManager {
}
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 f4e2ade643c7..e01b10eed4db 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -87,10 +87,12 @@ public final class TelephonyDisplayInfo implements Parcelable {
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 @@ public final class TelephonyDisplayInfo implements Parcelable {
* @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,
+ 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 @@ public final class TelephonyDisplayInfo implements Parcelable {
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 @@ public final class TelephonyDisplayInfo implements Parcelable {
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 @@ public final class TelephonyDisplayInfo implements Parcelable {
@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 d23b75bd8c45..fd5ec258d697 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17027,4 +17027,44 @@ public class TelephonyManager {
}
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 c5f6902062ff..25a714a4bb81 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -326,4 +326,34 @@ interface ISub {
* @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/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 075bc5e5214e..4123f8070e36 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.LinkProperties;
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 @@ public class VcnManagementServiceTest {
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 @@ public class VcnManagementServiceTest {
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 @@ public class VcnManagementServiceTest {
false /* expectRestricted */);
}
- private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
+ private void setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp) {
mVcnMgmtSvc.systemReady();
final ArgumentCaptor<NetworkCallback> captor =
@@ -1269,7 +1278,10 @@ public class VcnManagementServiceTest {
.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 @@ public class VcnManagementServiceTest {
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 @@ public class VcnManagementServiceTest {
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build(),
- new LinkProperties());
+ TEST_LP_1);
assertTrue(policy.isTeardownRequested());
}
@@ -1298,7 +1310,7 @@ public class VcnManagementServiceTest {
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 @@ public class VcnManagementServiceTest {
.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 @@ public class VcnManagementServiceTest {
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 @@ public class VcnManagementServiceTest {
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)