diff options
31 files changed, 313 insertions, 154 deletions
diff --git a/Android.mk b/Android.mk index d8532489a786..46529eb64657 100644 --- a/Android.mk +++ b/Android.mk @@ -32,10 +32,6 @@ ifneq ($(ANDROID_BUILD_EMBEDDED),true) # ============================================================ include $(CLEAR_VARS) -# This is used by ide.mk as the list of source files that are -# always included. -INTERNAL_SDK_SOURCE_DIRS := $(addprefix $(LOCAL_PATH)/,$(dirs_to_document)) - # sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip. # So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to # $(OUT_DOCS)/offline-sdk. diff --git a/StubLibraries.bp b/StubLibraries.bp index b984cb0d0714..26478d3bad26 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -229,11 +229,6 @@ droidstubs { // namely @SystemApi(client=MODULE_LIBRARIES) APIs. ///////////////////////////////////////////////////////////////////// -// TODO(b/146727827) remove the *-api module when we can teach metalava -// about the relationship among the API surfaces. Currently, these modules are only to generate -// the API signature files and ensure that the APIs evolve in a backwards compatible manner. -// They however are NOT used for building the API stub. - droidstubs { name: "module-lib-api", defaults: ["metalava-full-api-stubs-default"], @@ -270,7 +265,7 @@ droidstubs { name: "module-lib-api-stubs-docs-non-updatable", defaults: ["metalava-non-updatable-api-stubs-default"], arg_files: ["core/res/AndroidManifest.xml"], - args: metalava_framework_docs_args + module_libs, + args: metalava_framework_docs_args + priv_apps + module_libs, check_api: { current: { api_file: "non-updatable-api/module-lib-current.txt", @@ -279,17 +274,6 @@ droidstubs { }, } -// The following droidstub module generates source files for the API stub library for -// modules. Note that it not only includes its own APIs but also other APIs that have -// narrower scope (all @SystemApis, not just the ones with 'client=MODULE_LIBRARIES'). - -droidstubs { - name: "module-lib-api-stubs-docs", - defaults: ["metalava-non-updatable-api-stubs-default"], - arg_files: ["core/res/AndroidManifest.xml"], - args: metalava_framework_docs_args + priv_apps + module_libs, -} - ///////////////////////////////////////////////////////////////////// // android_*_stubs_current modules are the stubs libraries compiled // from *-api-stubs-docs @@ -335,7 +319,7 @@ java_library_static { java_library_static { name: "android_module_lib_stubs_current", - srcs: [ ":module-lib-api-stubs-docs" ], + srcs: [ ":module-lib-api-stubs-docs-non-updatable" ], defaults: ["android_defaults_stubs_current"], libs: ["sdk_system_29_android"], } diff --git a/api/current.txt b/api/current.txt index f1338f07f294..8dd7af81315b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -41088,6 +41088,7 @@ package android.security { field public static final String EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS"; field public static final String EXTRA_NAME = "name"; field public static final String EXTRA_PKCS12 = "PKCS12"; + field public static final String KEY_ALIAS_SELECTION_DENIED = "android:alias-selection-denied"; } public interface KeyChainAliasCallback { diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java index f66de8d238ed..25b8eab452bf 100644 --- a/core/java/android/app/admin/DelegatedAdminReceiver.java +++ b/core/java/android/app/admin/DelegatedAdminReceiver.java @@ -63,6 +63,10 @@ public class DelegatedAdminReceiver extends BroadcastReceiver { * Allows this receiver to select the alias for a private key and certificate pair for * authentication. If this method returns null, the default {@link android.app.Activity} will * be shown that lets the user pick a private key and certificate pair. + * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED}, + * the default {@link android.app.Activity} will not be shown and the user will not be allowed + * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will + * receive {@code null} back. * * <p> This callback is only applicable if the delegated app has * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 4771fd8a00b6..e3a49f39bdc7 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -791,6 +791,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * Allows this receiver to select the alias for a private key and certificate pair for * authentication. If this method returns null, the default {@link android.app.Activity} will be * shown that lets the user pick a private key and certificate pair. + * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED}, + * the default {@link android.app.Activity} will not be shown and the user will not be allowed + * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will + * receive {@code null} back. * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cb9463a59d34..4b806e714ffe 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -84,6 +84,15 @@ public class NetworkTemplate implements Parcelable { * @hide */ public static final int NETWORK_TYPE_ALL = -1; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This should not be overlapped with any of the + * {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + public static final int NETWORK_TYPE_5G_NSA = -2; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -472,6 +481,9 @@ public class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + case NetworkTemplate.NETWORK_TYPE_5G_NSA: + return NetworkTemplate.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java index ffe9ae9521a8..a32b41f6be4b 100644 --- a/core/java/android/net/ProxyInfo.java +++ b/core/java/android/net/ProxyInfo.java @@ -127,18 +127,6 @@ public class ProxyInfo implements Parcelable { } /** - * Create a ProxyProperties that points at a PAC URL. - * @hide - */ - public ProxyInfo(String pacFileUrl) { - mHost = LOCAL_HOST; - mPort = LOCAL_PORT; - mExclusionList = LOCAL_EXCL_LIST; - mParsedExclusionList = parseExclusionList(mExclusionList); - mPacFileUrl = Uri.parse(pacFileUrl); - } - - /** * Only used in PacManager after Local Proxy is bound. * @hide */ diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index a95fe3c4043d..7946dda3170d 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -1331,8 +1331,7 @@ public final class Telephony { Object[] messages; try { messages = (Object[]) intent.getSerializableExtra("pdus"); - } - catch (ClassCastException e) { + } catch (ClassCastException e) { Rlog.e(TAG, "getMessagesFromIntent: " + e); return null; } @@ -1344,9 +1343,12 @@ public final class Telephony { String format = intent.getStringExtra("format"); int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, - SubscriptionManager.getDefaultSmsSubscriptionId()); - - Rlog.v(TAG, " getMessagesFromIntent sub_id : " + subId); + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + Rlog.v(TAG, "getMessagesFromIntent with valid subId : " + subId); + } else { + Rlog.v(TAG, "getMessagesFromIntent"); + } int pduCount = messages.length; SmsMessage[] msgs = new SmsMessage[pduCount]; diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java index 8ea5aa815a1c..b4727499d8ef 100644 --- a/core/java/com/android/internal/net/VpnProfile.java +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -21,6 +21,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.net.Ikev2VpnProfile; import android.net.PlatformVpnProfile; import android.net.ProxyInfo; +import android.net.Uri; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -287,7 +288,7 @@ public final class VpnProfile implements Cloneable, Parcelable { profile.proxy = new ProxyInfo(host, port.isEmpty() ? 0 : Integer.parseInt(port), exclList); } else if (!pacFileUrl.isEmpty()) { - profile.proxy = new ProxyInfo(pacFileUrl); + profile.proxy = new ProxyInfo(Uri.parse(pacFileUrl)); } } // else profile.proxy = null diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 18be3741e805..fbb35e055e16 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -95,6 +95,19 @@ #include "nativebridge/native_bridge.h" +/* Functions in the callchain during the fork shall not be protected with + Armv8.3-A Pointer Authentication, otherwise child will not be able to return. */ +#ifdef __ARM_FEATURE_PAC_DEFAULT +#ifdef __ARM_FEATURE_BTI_DEFAULT +#define NO_PAC_FUNC __attribute__((target("branch-protection=bti"))) +#else +#define NO_PAC_FUNC __attribute__((target("branch-protection=none"))) +#endif /* __ARM_FEATURE_BTI_DEFAULT */ +#else /* !__ARM_FEATURE_PAC_DEFAULT */ +#define NO_PAC_FUNC +#endif /* __ARM_FEATURE_PAC_DEFAULT */ + + namespace { // TODO (chriswailes): Add a function to initialize native Zygote data. @@ -985,7 +998,23 @@ static void ClearUsapTable() { gUsapPoolCount = 0; } +NO_PAC_FUNC +static void PAuthKeyChange(JNIEnv* env) { +#ifdef __aarch64__ + unsigned long int hwcaps = getauxval(AT_HWCAP); + if (hwcaps & HWCAP_PACA) { + const unsigned long key_mask = PR_PAC_APIAKEY | PR_PAC_APIBKEY | + PR_PAC_APDAKEY | PR_PAC_APDBKEY | PR_PAC_APGAKEY; + if (prctl(PR_PAC_RESET_KEYS, key_mask, 0, 0, 0) != 0) { + ALOGE("Failed to change the PAC keys: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "PAC key change failed."); + } + } +#endif +} + // Utility routine to fork a process from the zygote. +NO_PAC_FUNC static pid_t ForkCommon(JNIEnv* env, bool is_system_server, const std::vector<int>& fds_to_close, const std::vector<int>& fds_to_ignore, @@ -1036,6 +1065,7 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server, } // The child process. + PAuthKeyChange(env); PreApplicationInit(); // Clean up any descriptors which must be closed immediately @@ -1486,6 +1516,7 @@ static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jcl PreApplicationInit(); } +NO_PAC_FUNC static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, @@ -1533,6 +1564,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( return pid; } +NO_PAC_FUNC static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, @@ -1600,6 +1632,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( * @param is_priority_fork Controls the nice level assigned to the newly created process * @return */ +NO_PAC_FUNC static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, jclass, jint read_pipe_fd, diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 59797f7f4bf6..51266de83355 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2422,6 +2422,11 @@ enum PageId { // OS: Q SETTINGS_GESTURE_TAP = 1751; + // OPEN: Settings > Security & screen lock -> Encryption & credentials > Install a certificate + // CATEGORY: SETTINGS + // OS: R + INSTALL_CERTIFICATE_FROM_STORAGE = 1803; + // OPEN: Settings > Developer Options > Platform Compat // CATEGORY: SETTINGS // OS: R diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java index d00d052db590..0af8c728aba3 100644 --- a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java +++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java @@ -154,6 +154,29 @@ public class EuiccProfileInfoTest { } @Test + public void testBuilder_BasedOnAnotherProfileWithEmptyAccessRules() { + EuiccProfileInfo p = + new EuiccProfileInfo.Builder("21430000000000006587") + .setNickname("profile nickname") + .setProfileName("profile name") + .setServiceProviderName("service provider") + .setCarrierIdentifier( + new CarrierIdentifier( + new byte[] {0x23, 0x45, 0x67}, + "123", + "45")) + .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED) + .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL) + .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) + .setUiccAccessRule(null) + .build(); + + EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build(); + + assertEquals(null, copied.getUiccAccessRules()); + } + + @Test public void testEqualsHashCode() { EuiccProfileInfo p = new EuiccProfileInfo.Builder("21430000000000006587") diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index 7282bcfe4445..62194d84f4f5 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -74,6 +74,15 @@ public class Credentials { /** Key containing suffix of lockdown VPN profile. */ public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN"; + /** Name of CA certificate usage. */ + public static final String CERTIFICATE_USAGE_CA = "ca"; + + /** Name of User certificate usage. */ + public static final String CERTIFICATE_USAGE_USER = "user"; + + /** Name of WIFI certificate usage. */ + public static final String CERTIFICATE_USAGE_WIFI = "wifi"; + /** Data type for public keys. */ public static final String EXTRA_PUBLIC_KEY = "KEY"; @@ -94,19 +103,19 @@ public class Credentials { public static final String EXTRA_INSTALL_AS_UID = "install_as_uid"; /** - * Intent extra: name for the user's private key. + * Intent extra: type of the certificate to install */ - public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name"; + public static final String EXTRA_CERTIFICATE_USAGE = "certificate_install_usage"; /** - * Intent extra: data for the user's private key in PEM-encoded PKCS#8. + * Intent extra: name for the user's key pair. */ - public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data"; + public static final String EXTRA_USER_KEY_ALIAS = "user_key_pair_name"; /** - * Intent extra: name for the user's certificate. + * Intent extra: data for the user's private key in PEM-encoded PKCS#8. */ - public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name"; + public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data"; /** * Intent extra: data for the user's certificate in PEM-encoded X.509. @@ -114,11 +123,6 @@ public class Credentials { public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data"; /** - * Intent extra: name for CA certificate chain - */ - public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name"; - - /** * Intent extra: data for CA certificate chain in PEM-encoded X.509. */ public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data"; diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index b3cdff7eedf7..97da3cc6f80f 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -43,7 +43,8 @@ interface IKeyChainService { String installCaCertificate(in byte[] caCertificate); // APIs used by DevicePolicyManager - boolean installKeyPair(in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias); + boolean installKeyPair( + in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid); boolean removeKeyPair(String alias); // APIs used by Settings diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 1829d2f406b4..254456cea536 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -343,6 +343,16 @@ public final class KeyChain { public static final int KEY_ATTESTATION_FAILURE = 4; /** + * Used by DPC or delegated app in + * {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias} or + * {@link android.app.admin.DelegatedAdminReceiver#onChoosePrivateKeyAlias} to identify that + * the requesting app is not granted access to any key, and nor will the user be able to grant + * access manually. + */ + public static final String KEY_ALIAS_SELECTION_DENIED = + "android:alias-selection-denied"; + + /** * Returns an {@code Intent} that can be used for credential * installation. The intent may be used without any extras, in * which case the user will be able to install credentials from diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index a28569297832..c55eeeb50b26 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -40944,6 +40944,7 @@ package android.security { field public static final String EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS"; field public static final String EXTRA_NAME = "name"; field public static final String EXTRA_PKCS12 = "PKCS12"; + field public static final String KEY_ALIAS_SELECTION_DENIED = "android:alias-selection-denied"; } public interface KeyChainAliasCallback { diff --git a/packages/Tethering/tests/privileged/Android.bp b/packages/Tethering/tests/privileged/Android.bp new file mode 100644 index 000000000000..a0fb24603a93 --- /dev/null +++ b/packages/Tethering/tests/privileged/Android.bp @@ -0,0 +1,30 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "TetheringPrivilegedTests", + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], + certificate: "networkstack", + platform_apis: true, + test_suites: [ + "general-tests", + "mts", + ], + compile_multilib: "both", +} diff --git a/packages/Tethering/tests/privileged/AndroidManifest.xml b/packages/Tethering/tests/privileged/AndroidManifest.xml new file mode 100644 index 000000000000..49eba15d13d4 --- /dev/null +++ b/packages/Tethering/tests/privileged/AndroidManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.networkstack.tethering.tests.privileged" + android:sharedUserId="android.uid.networkstack"> + + <!-- Note: do not add any privileged or signature permissions that are granted + to the network stack and its shared uid apps. Otherwise, the test APK will + install, but when the device is rebooted, it will bootloop because this + test APK is not in the privileged permission allow list --> + + <application android:debuggable="true"> + <uses-library android:name="android.test.runner" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.networkstack.tethering.tests.privileged" + android:label="Tethering privileged tests"> + </instrumentation> +</manifest> diff --git a/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl b/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl index 4e54aba5c3bf..1bbc90d604f9 100644 --- a/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl +++ b/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl @@ -21,7 +21,4 @@ interface IProxyService String resolvePacFile(String host, String url); oneway void setPacFile(String scriptContents); - - oneway void startPacSystem(); - oneway void stopPacSystem(); } diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java index b006d6e1fa7b..3c25bfd380f2 100644 --- a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java +++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java @@ -83,15 +83,5 @@ public class PacService extends Service { } mPacNative.setCurrentProxyScript(script); } - - @Override - public void startPacSystem() throws RemoteException { - //TODO: remove - } - - @Override - public void stopPacSystem() throws RemoteException { - //TODO: remove - } } } diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index f6ce2dc68b99..de302fc01f2d 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -196,13 +196,7 @@ public class PacManager { mPacUrl = Uri.EMPTY; mCurrentPac = null; if (mProxyService != null) { - try { - mProxyService.stopPacSystem(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to stop PAC service", e); - } finally { - unbind(); - } + unbind(); } } return DO_SEND_BROADCAST; @@ -327,11 +321,6 @@ public class PacManager { if (mProxyService == null) { Log.e(TAG, "No proxy service"); } else { - try { - mProxyService.startPacSystem(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); - } mNetThreadHandler.post(mPacDownloader); } } diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java index f812a05fd06f..26cc3ee165f1 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java @@ -163,7 +163,7 @@ public class ProxyTracker { if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) { ProxyInfo proxyProperties; if (!TextUtils.isEmpty(pacFileUrl)) { - proxyProperties = new ProxyInfo(pacFileUrl); + proxyProperties = new ProxyInfo(Uri.parse(pacFileUrl)); } else { proxyProperties = new ProxyInfo(host, port, exclList); } diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index e3e02e32ad50..f0bf5c0975f2 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -24,6 +24,7 @@ import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; +import android.net.Uri; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; @@ -372,7 +373,7 @@ public class IpConfigStore { config.httpProxy = proxyInfo; break; case PAC: - ProxyInfo proxyPacProperties = new ProxyInfo(pacFileUrl); + ProxyInfo proxyPacProperties = new ProxyInfo(Uri.parse(pacFileUrl)); config.proxySettings = proxySettings; config.httpProxy = proxyPacProperties; break; diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 7711c6a21d20..5f2c4a38b42a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,12 +16,14 @@ package com.android.server.net; +import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -196,7 +198,18 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 03e71f976c5b..a363f9ba5264 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5672,7 +5672,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { KeyChain.bindAsUser(mContext, UserHandle.getUserHandleForUid(callingUid)); try { IKeyChainService keyChain = keyChainConnection.getService(); - if (!keyChain.installKeyPair(privKey, cert, chain, alias)) { + if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyStore.UID_SELF)) { return false; } if (requestAccess) { diff --git a/telephony/java/android/service/euicc/EuiccProfileInfo.java b/telephony/java/android/service/euicc/EuiccProfileInfo.java index 8450a9018634..92e419707970 100644 --- a/telephony/java/android/service/euicc/EuiccProfileInfo.java +++ b/telephony/java/android/service/euicc/EuiccProfileInfo.java @@ -29,6 +29,7 @@ import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -231,7 +232,9 @@ public final class EuiccProfileInfo implements Parcelable { mState = baseProfile.mState; mCarrierIdentifier = baseProfile.mCarrierIdentifier; mPolicyRules = baseProfile.mPolicyRules; - mAccessRules = Arrays.asList(baseProfile.mAccessRules); + mAccessRules = baseProfile.mAccessRules == null + ? Collections.emptyList() + : Arrays.asList(baseProfile.mAccessRules); } /** Builds the profile instance. */ diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index c667165e7a0e..e91d6fc9d801 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -72,28 +72,20 @@ public final class DataSpecificRegistrationInfo implements Parcelable { /** * Provides network support info for LTE VoPS and LTE Emergency bearer support */ + @Nullable private final LteVopsSupportInfo mLteVopsSupportInfo; /** - * Indicates if it's using carrier aggregation - * - * @hide - */ - public boolean mIsUsingCarrierAggregation; - - /** * @hide */ DataSpecificRegistrationInfo( int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, - boolean isEnDcAvailable, LteVopsSupportInfo lteVops, - boolean isUsingCarrierAggregation) { + boolean isEnDcAvailable, @Nullable LteVopsSupportInfo lteVops) { this.maxDataCalls = maxDataCalls; this.isDcNrRestricted = isDcNrRestricted; this.isNrAvailable = isNrAvailable; this.isEnDcAvailable = isEnDcAvailable; this.mLteVopsSupportInfo = lteVops; - this.mIsUsingCarrierAggregation = isUsingCarrierAggregation; } /** @@ -102,32 +94,29 @@ public final class DataSpecificRegistrationInfo implements Parcelable { * @param dsri another data specific registration info * @hide */ - DataSpecificRegistrationInfo(DataSpecificRegistrationInfo dsri) { + DataSpecificRegistrationInfo(@NonNull DataSpecificRegistrationInfo dsri) { maxDataCalls = dsri.maxDataCalls; isDcNrRestricted = dsri.isDcNrRestricted; isNrAvailable = dsri.isNrAvailable; isEnDcAvailable = dsri.isEnDcAvailable; mLteVopsSupportInfo = dsri.mLteVopsSupportInfo; - mIsUsingCarrierAggregation = dsri.mIsUsingCarrierAggregation; } - private DataSpecificRegistrationInfo(Parcel source) { + private DataSpecificRegistrationInfo(/* @NonNull */ Parcel source) { maxDataCalls = source.readInt(); isDcNrRestricted = source.readBoolean(); isNrAvailable = source.readBoolean(); isEnDcAvailable = source.readBoolean(); mLteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); - mIsUsingCarrierAggregation = source.readBoolean(); } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(/* @NonNull */ Parcel dest, int flags) { dest.writeInt(maxDataCalls); dest.writeBoolean(isDcNrRestricted); dest.writeBoolean(isNrAvailable); dest.writeBoolean(isEnDcAvailable); mLteVopsSupportInfo.writeToParcel(dest, flags); - dest.writeBoolean(mIsUsingCarrierAggregation); } @Override @@ -144,8 +133,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { .append(" isDcNrRestricted = " + isDcNrRestricted) .append(" isNrAvailable = " + isNrAvailable) .append(" isEnDcAvailable = " + isEnDcAvailable) - .append(" " + mLteVopsSupportInfo.toString()) - .append(" mIsUsingCarrierAggregation = " + mIsUsingCarrierAggregation) + .append(" " + mLteVopsSupportInfo) .append(" }") .toString(); } @@ -153,7 +141,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { @Override public int hashCode() { return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable, - mLteVopsSupportInfo, mIsUsingCarrierAggregation); + mLteVopsSupportInfo); } @Override @@ -167,8 +155,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { && this.isDcNrRestricted == other.isDcNrRestricted && this.isNrAvailable == other.isNrAvailable && this.isEnDcAvailable == other.isEnDcAvailable - && this.mLteVopsSupportInfo.equals(other.mLteVopsSupportInfo) - && this.mIsUsingCarrierAggregation == other.mIsUsingCarrierAggregation; + && Objects.equals(mLteVopsSupportInfo, other.mLteVopsSupportInfo); } public static final @NonNull Parcelable.Creator<DataSpecificRegistrationInfo> CREATOR = @@ -192,23 +179,4 @@ public final class DataSpecificRegistrationInfo implements Parcelable { return mLteVopsSupportInfo; } - /** - * Set the flag indicating if using carrier aggregation. - * - * @param isUsingCarrierAggregation {@code true} if using carrier aggregation. - * @hide - */ - public void setIsUsingCarrierAggregation(boolean isUsingCarrierAggregation) { - mIsUsingCarrierAggregation = isUsingCarrierAggregation; - } - - /** - * Get whether network has configured carrier aggregation or not. - * - * @return {@code true} if using carrier aggregation. - * @hide - */ - public boolean isUsingCarrierAggregation() { - return mIsUsingCarrierAggregation; - } } diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 31a83c9334d5..68753e11d395 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -218,6 +218,9 @@ public final class NetworkRegistrationInfo implements Parcelable { @NonNull private String mRplmn; + // Updated based on the accessNetworkTechnology + private boolean mIsUsingCarrierAggregation; + /** * @param domain Network domain. Must be a {@link Domain}. For transport type * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}. @@ -251,7 +254,7 @@ public final class NetworkRegistrationInfo implements Parcelable { mRegistrationState = registrationState; mRoamingType = (registrationState == REGISTRATION_STATE_ROAMING) ? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING; - mAccessNetworkTechnology = accessNetworkTechnology; + setAccessNetworkTechnology(accessNetworkTechnology); mRejectCause = rejectCause; mAvailableServices = (availableServices != null) ? new ArrayList<>(availableServices) : new ArrayList<>(); @@ -290,13 +293,11 @@ public final class NetworkRegistrationInfo implements Parcelable { @Nullable CellIdentity cellIdentity, @Nullable String rplmn, int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable, - LteVopsSupportInfo lteVopsSupportInfo, - boolean isUsingCarrierAggregation) { + LteVopsSupportInfo lteVopsSupportInfo) { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity, rplmn); mDataSpecificInfo = new DataSpecificRegistrationInfo( - maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo, - isUsingCarrierAggregation); + maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo); updateNrState(); } @@ -317,6 +318,7 @@ public final class NetworkRegistrationInfo implements Parcelable { DataSpecificRegistrationInfo.class.getClassLoader()); mNrState = source.readInt(); mRplmn = source.readString(); + mIsUsingCarrierAggregation = source.readBoolean(); } /** @@ -331,6 +333,7 @@ public final class NetworkRegistrationInfo implements Parcelable { mRegistrationState = nri.mRegistrationState; mRoamingType = nri.mRoamingType; mAccessNetworkTechnology = nri.mAccessNetworkTechnology; + mIsUsingCarrierAggregation = nri.mIsUsingCarrierAggregation; mRejectCause = nri.mRejectCause; mEmergencyOnly = nri.mEmergencyOnly; mAvailableServices = new ArrayList<>(nri.mAvailableServices); @@ -484,9 +487,7 @@ public final class NetworkRegistrationInfo implements Parcelable { if (tech == TelephonyManager.NETWORK_TYPE_LTE_CA) { // For old device backward compatibility support tech = TelephonyManager.NETWORK_TYPE_LTE; - if (mDataSpecificInfo != null) { - mDataSpecificInfo.setIsUsingCarrierAggregation(true); - } + mIsUsingCarrierAggregation = true; } mAccessNetworkTechnology = tech; } @@ -511,6 +512,27 @@ public final class NetworkRegistrationInfo implements Parcelable { } /** + * Set whether network has configured carrier aggregation or not. + * + * @param isUsingCarrierAggregation set whether or not carrier aggregation is used. + * + * @hide + */ + public void setIsUsingCarrierAggregation(boolean isUsingCarrierAggregation) { + mIsUsingCarrierAggregation = isUsingCarrierAggregation; + } + + /** + * Get whether network has configured carrier aggregation or not. + * + * @return {@code true} if using carrier aggregation. + * @hide + */ + public boolean isUsingCarrierAggregation() { + return mIsUsingCarrierAggregation; + } + + /** * @hide */ @Nullable @@ -616,6 +638,7 @@ public final class NetworkRegistrationInfo implements Parcelable { .append(" dataSpecificInfo=").append(mDataSpecificInfo) .append(" nrState=").append(nrStateToString(mNrState)) .append(" rRplmn=").append(mRplmn) + .append(" isUsingCarrierAggregation=").append(mIsUsingCarrierAggregation) .append("}").toString(); } @@ -623,7 +646,8 @@ public final class NetworkRegistrationInfo implements Parcelable { public int hashCode() { return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType, mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices, - mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState, mRplmn); + mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState, mRplmn, + mIsUsingCarrierAggregation); } @Override @@ -643,6 +667,7 @@ public final class NetworkRegistrationInfo implements Parcelable { && mRejectCause == other.mRejectCause && mEmergencyOnly == other.mEmergencyOnly && mAvailableServices.equals(other.mAvailableServices) + && mIsUsingCarrierAggregation == other.mIsUsingCarrierAggregation && Objects.equals(mCellIdentity, other.mCellIdentity) && Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo) && Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo) @@ -669,6 +694,7 @@ public final class NetworkRegistrationInfo implements Parcelable { dest.writeParcelable(mDataSpecificInfo, 0); dest.writeInt(mNrState); dest.writeString(mRplmn); + dest.writeBoolean(mIsUsingCarrierAggregation); } /** diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 5c84297d3b86..243b24b667c7 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1392,29 +1392,14 @@ public class ServiceState implements Parcelable { /** @hide */ public boolean isUsingCarrierAggregation() { - boolean isUsingCa = false; - NetworkRegistrationInfo nri = getNetworkRegistrationInfo( - NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (nri != null) { - DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo(); - if (dsri != null) { - isUsingCa = dsri.isUsingCarrierAggregation(); - } - } - return isUsingCa || getCellBandwidths().length > 1; - } + if (getCellBandwidths().length > 1) return true; - /** @hide */ - public void setIsUsingCarrierAggregation(boolean ca) { - NetworkRegistrationInfo nri = getNetworkRegistrationInfo( - NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (nri != null) { - DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo(); - if (dsri != null) { - dsri.setIsUsingCarrierAggregation(ca); - addNetworkRegistrationInfo(nri); + synchronized (mNetworkRegistrationInfos) { + for (NetworkRegistrationInfo nri : mNetworkRegistrationInfos) { + if (nri.isUsingCarrierAggregation()) return true; } } + return false; } /** diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt index 5dd0fda4da28..9ba56e44fe88 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -26,6 +26,7 @@ import android.net.NetworkStats.METERED_ALL import android.net.NetworkStats.ROAMING_ALL import android.net.NetworkTemplate.MATCH_MOBILE import android.net.NetworkTemplate.MATCH_WIFI +import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA import android.net.NetworkTemplate.NETWORK_TYPE_ALL import android.net.NetworkTemplate.buildTemplateMobileWithRatType import android.telephony.TelephonyManager @@ -145,11 +146,13 @@ class NetworkTemplateTest { assertParcelSane(templateWifi, 8) } - // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants. + // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with + // TelephonyManager#NETWORK_TYPE_* constants. @Test - fun testNetworkTypeAll() { + fun testNetworkTypeConstants() { for (ratType in TelephonyManager.getAllNetworkTypes()) { assertNotEquals(NETWORK_TYPE_ALL, ratType) + assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) } } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java index c813269744ef..9531b0a5bb66 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java @@ -17,6 +17,7 @@ package com.android.server.net; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; @@ -30,7 +31,9 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.Context; +import android.net.NetworkTemplate; import android.os.test.TestLooper; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -61,7 +64,6 @@ public final class NetworkStatsSubscriptionsMonitorTest { private static final String TEST_IMSI3 = "466929999999999"; @Mock private Context mContext; - @Mock private PhoneStateListener mPhoneStateListener; @Mock private SubscriptionManager mSubscriptionManager; @Mock private TelephonyManager mTelephonyManager; @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate; @@ -215,4 +217,55 @@ public final class NetworkStatsSubscriptionsMonitorTest { verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); } + + + @Test + public void test5g() { + mMonitor.start(); + // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback + // before changing RAT type. Also capture listener for later use. + addTestSub(TEST_SUBID1, TEST_IMSI1); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor = + ArgumentCaptor.forClass(RatTypeListener.class); + verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), + eq(PhoneStateListener.LISTEN_SERVICE_STATE)); + final RatTypeListener listener = CollectionUtils + .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1); + assertNotNull(listener); + + // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs + // NETWORK_TYPE_5G_NSA. + final ServiceState serviceState = mock(ServiceState.class); + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA); + reset(mDelegate); + + // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE. + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE); + reset(mDelegate); + + // Verify NR connected with other RAT type does not take effect. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + reset(mDelegate); + + // Set RAT type to 5G standalone mode, the RAT type should be NR. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, + TelephonyManager.NETWORK_TYPE_NR); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + reset(mDelegate); + + // Set NR state to none in standalone mode does not change anything. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + } } |