summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt68
-rwxr-xr-xapi/system-current.txt28
-rw-r--r--api/test-current.txt10
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java34
-rw-r--r--core/java/android/content/Intent.java4
-rw-r--r--core/java/android/net/ConnectivityManager.java97
-rw-r--r--core/java/android/net/LinkProperties.java36
-rw-r--r--core/java/android/net/NetworkStats.java2
-rw-r--r--core/java/android/net/RouteInfo.java20
-rw-r--r--core/java/android/os/ConfigUpdate.java3
-rw-r--r--core/java/android/telephony/PhoneStateListener.java33
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java17
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl2
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl2
-rw-r--r--media/java/android/media/audiofx/Visualizer.java180
-rw-r--r--media/java/android/media/tv/OWNERS4
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java35
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java21
-rw-r--r--packages/Tethering/res/values-mcc204-mnc04/strings.xml26
-rw-r--r--packages/Tethering/res/values-mcc310-mnc004/strings.xml26
-rw-r--r--packages/Tethering/res/values-mcc311-mnc480/strings.xml26
-rw-r--r--packages/Tethering/res/values/strings.xml10
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java2
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java24
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java87
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java67
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java108
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java253
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java45
-rw-r--r--telephony/common/com/android/internal/telephony/SmsApplication.java17
-rw-r--r--telephony/java/android/service/euicc/EuiccService.java60
-rw-r--r--telephony/java/android/telephony/Annotation.java13
-rw-r--r--telephony/java/android/telephony/BarringInfo.aidl20
-rw-r--r--telephony/java/android/telephony/BarringInfo.java398
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationInfo.java62
-rw-r--r--telephony/java/android/telephony/PreciseDataConnectionState.java4
-rw-r--r--telephony/java/android/telephony/SmsManager.java7
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java9
-rw-r--r--telephony/java/android/telephony/euicc/EuiccManager.java313
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java19
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java2
-rw-r--r--tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java257
-rw-r--r--tests/net/common/java/android/net/NetworkCapabilitiesTest.java30
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java171
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java4
48 files changed, 2053 insertions, 615 deletions
diff --git a/api/current.txt b/api/current.txt
index acec83bcfbd4..f17eae1eb077 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44680,6 +44680,38 @@ package android.telephony {
field public static final int PRIORITY_MED = 2; // 0x2
}
+ public final class BarringInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.telephony.BarringInfo.BarringServiceInfo getBarringServiceInfo(int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BARRING_SERVICE_TYPE_CS_FALLBACK = 5; // 0x5
+ field public static final int BARRING_SERVICE_TYPE_CS_SERVICE = 0; // 0x0
+ field public static final int BARRING_SERVICE_TYPE_CS_VOICE = 2; // 0x2
+ field public static final int BARRING_SERVICE_TYPE_EMERGENCY = 8; // 0x8
+ field public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO = 7; // 0x7
+ field public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE = 6; // 0x6
+ field public static final int BARRING_SERVICE_TYPE_MO_DATA = 4; // 0x4
+ field public static final int BARRING_SERVICE_TYPE_MO_SIGNALLING = 3; // 0x3
+ field public static final int BARRING_SERVICE_TYPE_PS_SERVICE = 1; // 0x1
+ field public static final int BARRING_SERVICE_TYPE_SMS = 9; // 0x9
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.BarringInfo> CREATOR;
+ }
+
+ public static final class BarringInfo.BarringServiceInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBarringType();
+ method public int getConditionalBarringFactor();
+ method public int getConditionalBarringTimeSeconds();
+ method public boolean isBarred();
+ method public boolean isConditionallyBarred();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BARRING_TYPE_CONDITIONAL = 1; // 0x1
+ field public static final int BARRING_TYPE_NONE = 0; // 0x0
+ field public static final int BARRING_TYPE_UNCONDITIONAL = 2; // 0x2
+ field public static final int BARRING_TYPE_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.BarringInfo.BarringServiceInfo> CREATOR;
+ }
+
public class CarrierConfigManager {
method @Nullable public android.os.PersistableBundle getConfig();
method @Nullable public android.os.PersistableBundle getConfigByComponentForSubId(@NonNull String, int);
@@ -45316,6 +45348,7 @@ package android.telephony {
method @Nullable public android.telephony.CellIdentity getCellIdentity();
method public int getDomain();
method public int getNrState();
+ method @Nullable public String getRegisteredPlmn();
method public int getTransportType();
method public boolean isRegistered();
method public boolean isRoaming();
@@ -45442,6 +45475,7 @@ package android.telephony {
ctor public PhoneStateListener();
ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
method public void onActiveDataSubscriptionIdChanged(int);
+ method public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, String);
@@ -45460,6 +45494,7 @@ package android.telephony {
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
method public void onUserMobileDataStateChanged(boolean);
field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+ field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
field public static final int LISTEN_CALL_STATE = 32; // 0x20
@@ -45482,6 +45517,7 @@ package android.telephony {
public final class PreciseDataConnectionState implements android.os.Parcelable {
method public int describeContents();
+ method @Nullable public android.telephony.data.ApnSetting getApnSetting();
method public int getLastCauseCode();
method @Nullable public android.net.LinkProperties getLinkProperties();
method public int getNetworkType();
@@ -46352,10 +46388,42 @@ package android.telephony.euicc {
field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2
field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0
field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1
+ field public static final int ERROR_ADDRESS_MISSING = 10011; // 0x271b
+ field public static final int ERROR_CARRIER_LOCKED = 10000; // 0x2710
+ field public static final int ERROR_CERTIFICATE_ERROR = 10012; // 0x271c
+ field public static final int ERROR_CONNECTION_ERROR = 10014; // 0x271e
+ field public static final int ERROR_DISALLOWED_BY_PPR = 10010; // 0x271a
+ field public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004; // 0x2714
+ field public static final int ERROR_EUICC_MISSING = 10006; // 0x2716
+ field public static final int ERROR_INCOMPATIBLE_CARRIER = 10003; // 0x2713
+ field public static final int ERROR_INSTALL_PROFILE = 10009; // 0x2719
+ field public static final int ERROR_INVALID_ACTIVATION_CODE = 10001; // 0x2711
+ field public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002; // 0x2712
+ field public static final int ERROR_INVALID_RESPONSE = 10015; // 0x271f
+ field public static final int ERROR_NO_PROFILES_AVAILABLE = 10013; // 0x271d
+ field public static final int ERROR_OPERATION_BUSY = 10016; // 0x2720
+ field public static final int ERROR_SIM_MISSING = 10008; // 0x2718
+ field public static final int ERROR_TIME_OUT = 10005; // 0x2715
+ field public static final int ERROR_UNSUPPORTED_VERSION = 10007; // 0x2717
field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
+ field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_ERROR_CODE";
+ field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_OPERATION_CODE";
+ field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE";
+ field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE";
field public static final String EXTRA_USE_QR_SCANNER = "android.telephony.euicc.extra.USE_QR_SCANNER";
field public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
+ field public static final int OPERATION_APDU = 8; // 0x8
+ field public static final int OPERATION_DOWNLOAD = 5; // 0x5
+ field public static final int OPERATION_EUICC_CARD = 3; // 0x3
+ field public static final int OPERATION_EUICC_GSMA = 7; // 0x7
+ field public static final int OPERATION_HTTP = 11; // 0xb
+ field public static final int OPERATION_METADATA = 6; // 0x6
+ field public static final int OPERATION_SIM_SLOT = 2; // 0x2
+ field public static final int OPERATION_SMDX = 9; // 0x9
+ field public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10; // 0xa
+ field public static final int OPERATION_SWITCH = 4; // 0x4
+ field public static final int OPERATION_SYSTEM = 1; // 0x1
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 7bdd0a51934a..1eb70f0ca48b 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1292,16 +1292,16 @@ package android.app.usage {
package android.bluetooth {
public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@NonNull android.bluetooth.BluetoothDevice);
method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice();
- method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice);
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@NonNull android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int isOptionalCodecsEnabled(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int isOptionalCodecsSupported(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothCodecConfig);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@NonNull android.bluetooth.BluetoothDevice, int);
field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
@@ -1671,7 +1671,6 @@ package android.content {
field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
- field @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED";
field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
@@ -4746,7 +4745,7 @@ package android.net {
public final class NetworkStats implements android.os.Parcelable {
ctor public NetworkStats(long, int);
method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
- method @NonNull public android.net.NetworkStats addValues(@NonNull android.net.NetworkStats.Entry);
+ method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
method public int describeContents();
method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -7469,6 +7468,7 @@ package android.service.euicc {
public abstract class EuiccService extends android.app.Service {
ctor public EuiccService();
method public void dump(@NonNull java.io.PrintWriter);
+ method public int encodeSmdxSubjectAndReasonCode(@NonNull String, @NonNull String);
method @CallSuper public android.os.IBinder onBind(android.content.Intent);
method public abstract int onDeleteSubscription(int, String);
method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
@@ -8169,6 +8169,11 @@ package android.telephony {
field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
}
+ public final class BarringInfo implements android.os.Parcelable {
+ ctor public BarringInfo();
+ method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy();
+ }
+
public final class CallAttributes implements android.os.Parcelable {
ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
method public int describeContents();
@@ -8844,6 +8849,7 @@ package android.telephony {
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
@@ -9273,7 +9279,6 @@ package android.telephony {
public class TelephonyManager {
method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int changeIccLockPassword(@NonNull String, @NonNull String);
method public int checkCarrierPrivilegesForPackage(String);
method public int checkCarrierPrivilegesForPackageAnyPhone(String);
method public void dial(String);
@@ -9339,7 +9344,6 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isGlobalModeEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isManualNetworkSelectionAllowed();
@@ -9377,7 +9381,6 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setIccLockEnabled(boolean, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
@@ -9424,7 +9427,6 @@ package android.telephony {
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
- field public static final int CHANGE_ICC_LOCK_SUCCESS = 2147483647; // 0x7fffffff
field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION";
field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
field @Deprecated public static final String EXTRA_APN_PROTOCOL = "apnProto";
diff --git a/api/test-current.txt b/api/test-current.txt
index d46f36885c56..c9725710daf8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3098,6 +3098,15 @@ package android.telephony {
field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
}
+ public final class BarringInfo implements android.os.Parcelable {
+ ctor public BarringInfo();
+ ctor public BarringInfo(@Nullable android.telephony.CellIdentity, @NonNull android.util.SparseArray<android.telephony.BarringInfo.BarringServiceInfo>);
+ }
+
+ public static final class BarringInfo.BarringServiceInfo implements android.os.Parcelable {
+ ctor public BarringInfo.BarringServiceInfo(int, boolean, int, int);
+ }
+
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -3184,6 +3193,7 @@ package android.telephony {
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d8c653c6d0d5..b672a0857cca 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -643,8 +643,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
@SystemApi
@Nullable
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) {
+ public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
+ verifyDeviceNotNull(device, "getCodecStatus");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
@@ -670,9 +671,14 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void setCodecConfigPreference(@Nullable BluetoothDevice device,
- @Nullable BluetoothCodecConfig codecConfig) {
+ public void setCodecConfigPreference(@NonNull BluetoothDevice device,
+ @NonNull BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
+ verifyDeviceNotNull(device, "setCodecConfigPreference");
+ if (codecConfig == null) {
+ Log.e(TAG, "setCodecConfigPreference: Codec config can't be null");
+ throw new IllegalArgumentException("codecConfig cannot be null");
+ }
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
@@ -695,8 +701,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void enableOptionalCodecs(@Nullable BluetoothDevice device) {
+ public void enableOptionalCodecs(@NonNull BluetoothDevice device) {
if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
+ verifyDeviceNotNull(device, "enableOptionalCodecs");
enableDisableOptionalCodecs(device, true);
}
@@ -709,8 +716,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void disableOptionalCodecs(@Nullable BluetoothDevice device) {
+ public void disableOptionalCodecs(@NonNull BluetoothDevice device) {
if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
+ verifyDeviceNotNull(device, "disableOptionalCodecs");
enableDisableOptionalCodecs(device, false);
}
@@ -750,7 +758,8 @@ public final class BluetoothA2dp implements BluetoothProfile {
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@OptionalCodecsSupportStatus
- public int supportsOptionalCodecs(@Nullable BluetoothDevice device) {
+ public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) {
+ verifyDeviceNotNull(device, "isOptionalCodecsSupported");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -775,7 +784,8 @@ public final class BluetoothA2dp implements BluetoothProfile {
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@OptionalCodecsPreferenceStatus
- public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) {
+ public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) {
+ verifyDeviceNotNull(device, "isOptionalCodecsEnabled");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -800,8 +810,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device,
+ public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device,
@OptionalCodecsPreferenceStatus int value) {
+ verifyDeviceNotNull(device, "setOptionalCodecsEnabled");
try {
if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
&& value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
@@ -854,6 +865,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
return false;
}
+ private void verifyDeviceNotNull(BluetoothDevice device, String methodName) {
+ if (device == null) {
+ Log.e(TAG, methodName + ": device param is null");
+ throw new IllegalArgumentException("Device cannot be null");
+ }
+ }
+
private boolean isValidDevice(BluetoothDevice device) {
if (device == null) return false;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ba91014a8756..467aa15ea242 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3622,9 +3622,7 @@ public class Intent implements Parcelable, Cloneable {
* {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @SystemApi
+ @UnsupportedAppUsage
public static final String ACTION_USER_SWITCHED =
"android.intent.action.USER_SWITCHED";
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d8a97de0b7df..629de1dfde4e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -145,16 +145,6 @@ public class ConnectivityManager {
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
- * A temporary hack until SUPL system can get off the legacy APIS.
- * They do too many network requests and the long list of apps listening
- * and waking due to the CONNECTIVITY_ACTION broadcast makes it expensive.
- * Use this broadcast intent instead for SUPL requests.
- * @hide
- */
- public static final String CONNECTIVITY_ACTION_SUPL =
- "android.net.conn.CONNECTIVITY_CHANGE_SUPL";
-
- /**
* The device has connected to a network that has presented a captive
* portal, which is blocking Internet connectivity. The user was presented
* with a notification that network sign in is required,
@@ -1517,84 +1507,6 @@ public class ConnectivityManager {
return null;
}
- /**
- * Guess what the network request was trying to say so that the resulting
- * network is accessible via the legacy (deprecated) API such as
- * requestRouteToHost.
- *
- * This means we should try to be fairly precise about transport and
- * capability but ignore things such as networkSpecifier.
- * If the request has more than one transport or capability it doesn't
- * match the old legacy requests (they selected only single transport/capability)
- * so this function cannot map the request to a single legacy type and
- * the resulting network will not be available to the legacy APIs.
- *
- * This code is only called from the requestNetwork API (L and above).
- *
- * Setting a legacy type causes CONNECTIVITY_ACTION broadcasts, which are expensive
- * because they wake up lots of apps - see http://b/23350688 . So we currently only
- * do this for SUPL requests, which are the only ones that we know need it. If
- * omitting these broadcasts causes unacceptable app breakage, then for backwards
- * compatibility we can send them:
- *
- * if (targetSdkVersion < Build.VERSION_CODES.M) && // legacy API unsupported >= M
- * targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP)) // requestNetwork not present < L
- *
- * TODO - This should be removed when the legacy APIs are removed.
- */
- private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
- if (netCap == null) {
- return TYPE_NONE;
- }
-
- if (!netCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return TYPE_NONE;
- }
-
- // Do this only for SUPL, until GnssLocationProvider is fixed. http://b/25876485 .
- if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- // NOTE: if this causes app breakage, we should not just comment out this early return;
- // instead, we should make this early return conditional on the requesting app's target
- // SDK version, as described in the comment above.
- return TYPE_NONE;
- }
-
- String type = null;
- int result = TYPE_NONE;
-
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
- type = "enableCBS";
- result = TYPE_MOBILE_CBS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
- type = "enableIMS";
- result = TYPE_MOBILE_IMS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
- type = "enableFOTA";
- result = TYPE_MOBILE_FOTA;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
- type = "enableDUN";
- result = TYPE_MOBILE_DUN;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- type = "enableSUPL";
- result = TYPE_MOBILE_SUPL;
- // back out this hack for mms as they no longer need this and it's causing
- // device slowdowns - b/23350688 (note, supl still needs this)
- //} else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
- // type = "enableMMS";
- // result = TYPE_MOBILE_MMS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
- type = "enableHIPRI";
- result = TYPE_MOBILE_HIPRI;
- }
- if (type != null) {
- NetworkCapabilities testCap = networkCapabilitiesForFeature(TYPE_MOBILE, type);
- if (testCap.equalsNetCapabilities(netCap) && testCap.equalsTransportTypes(netCap)) {
- return result;
- }
- }
- return TYPE_NONE;
- }
-
private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
if (netCap == null) return TYPE_NONE;
if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
@@ -3894,9 +3806,8 @@ public class ConnectivityManager {
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
- requestNetwork(request, networkCallback, 0, legacyType, cbHandler);
+ requestNetwork(request, networkCallback, 0, TYPE_NONE, cbHandler);
}
/**
@@ -3929,8 +3840,7 @@ public class ConnectivityManager {
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, int timeoutMs) {
checkTimeout(timeoutMs);
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
- requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
+ requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, getDefaultHandler());
}
/**
@@ -3955,9 +3865,8 @@ public class ConnectivityManager {
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) {
checkTimeout(timeoutMs);
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
- requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
+ requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, cbHandler);
}
/**
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index fe3f91940e2b..2c356e43d9fe 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -686,17 +686,29 @@ public final class LinkProperties implements Parcelable {
route.getDestination(),
route.getGateway(),
mIfaceName,
- route.getType());
+ route.getType(),
+ route.getMtu());
+ }
+
+ private int findRouteIndexByDestination(RouteInfo route) {
+ for (int i = 0; i < mRoutes.size(); i++) {
+ if (mRoutes.get(i).isSameDestinationAs(route)) {
+ return i;
+ }
+ }
+ return -1;
}
/**
- * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the
- * {@link RouteInfo} had an interface name set and that differs from the interface set for this
- * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. The proper
+ * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo}
+ * with the same destination exists with different properties (e.g., different MTU),
+ * it will be updated. If the {@link RouteInfo} had an interface name set and
+ * that differs from the interface set for this {@code LinkProperties} an
+ * {@link IllegalArgumentException} will be thrown. The proper
* course is to add either un-named or properly named {@link RouteInfo}.
*
* @param route A {@link RouteInfo} to add to this object.
- * @return {@code false} if the route was already present, {@code true} if it was added.
+ * @return {@code true} was added or updated, false otherwise.
*/
public boolean addRoute(@NonNull RouteInfo route) {
String routeIface = route.getInterface();
@@ -706,11 +718,20 @@ public final class LinkProperties implements Parcelable {
+ " vs. " + mIfaceName);
}
route = routeWithInterface(route);
- if (!mRoutes.contains(route)) {
+
+ int i = findRouteIndexByDestination(route);
+ if (i == -1) {
+ // Route was not present. Add it.
mRoutes.add(route);
return true;
+ } else if (mRoutes.get(i).equals(route)) {
+ // Route was present and has same properties. Do nothing.
+ return false;
+ } else {
+ // Route was present and has different properties. Update it.
+ mRoutes.set(i, route);
+ return true;
}
- return false;
}
/**
@@ -718,6 +739,7 @@ public final class LinkProperties implements Parcelable {
* specify an interface and the interface must match the interface of this
* {@code LinkProperties}, or it will not be removed.
*
+ * @param route A {@link RouteInfo} specifying the route to remove.
* @return {@code true} if the route was removed, {@code false} if it was not present.
*
* @hide
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 0fc74b089409..9c1fb41ecc96 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -721,7 +721,7 @@ public final class NetworkStats implements Parcelable {
* @param entry the {@link Entry} to add.
* @return a new constructed {@link NetworkStats} object that contains the result.
*/
- public @NonNull NetworkStats addValues(@NonNull Entry entry) {
+ public @NonNull NetworkStats addEntry(@NonNull Entry entry) {
return this.clone().combineValues(entry);
}
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 2b9e9fe81b1b..fec2df412adb 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -527,6 +527,26 @@ public final class RouteInfo implements Parcelable {
}
/**
+ * Compares this RouteInfo object against the specified object and indicates if the
+ * destinations of both routes are equal.
+ * @return {@code true} if the route destinations are equal, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean isSameDestinationAs(@Nullable Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof RouteInfo)) return false;
+
+ RouteInfo target = (RouteInfo) obj;
+
+ if (Objects.equals(mDestination, target.getDestination())) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Returns a hashcode for this <code>RouteInfo</code> object.
*/
public int hashCode() {
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index 590fbb36a0e8..a28f5fbaba0b 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -17,6 +17,8 @@
package android.os;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
/**
@@ -125,6 +127,7 @@ public final class ConfigUpdate {
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.UPDATE_CONFIG)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
"android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 1dca7fd0e444..ab31d247bb73 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -427,6 +427,17 @@ public class PhoneStateListener {
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
+ /**
+ * Listen for Barring Information for the current registered / camped cell.
+ *
+ * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
+ * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @see #onBarringInfoChanged()
+ */
+ @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ public static final int LISTEN_BARRING_INFO = 0x80000000;
+
/*
* Subscription used to listen to the phone state changes
* @hide
@@ -1036,6 +1047,20 @@ public class PhoneStateListener {
}
/**
+ * Report updated barring information for the current camped/registered cell.
+ *
+ * <p>Barring info is provided for all services applicable to the current camped/registered
+ * cell, for the registered PLMN and current access class/access category.
+ *
+ * @param barringInfo for all services on the current cell.
+ *
+ * @see android.telephony.BarringInfo
+ */
+ public void onBarringInfoChanged(@NonNull BarringInfo barringInfo) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*
@@ -1328,6 +1353,14 @@ public class PhoneStateListener {
cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
// default implementation empty
}
+
+ public void onBarringInfoChanged(BarringInfo barringInfo) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo)));
+ }
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index c4b4c43056b1..73cd708f43f7 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -729,4 +729,21 @@ public class TelephonyRegistryManager {
} catch (RemoteException ex) {
}
}
+
+ /**
+ * Notify {@link BarringInfo} has changed for a specific subscription.
+ *
+ * @param slotIndex for the phone object that got updated barring info.
+ * @param subId for which the BarringInfo changed.
+ * @param barringInfo updated BarringInfo.
+ */
+ public void notifyBarringInfoChanged(
+ int slotIndex, int subId, @NonNull BarringInfo barringInfo) {
+ try {
+ sRegistry.notifyBarringInfoChanged(slotIndex, subId, barringInfo);
+ } catch (RemoteException ex) {
+ // system server crash
+ }
+ }
+
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5d50582517a3..401933aa4b1f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5421,7 +5421,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (mVideoOnNesting > 0) {
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
- mAudioOnNesting = 0;
+ mVideoOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
+ Integer.toHexString(mHistoryCur.states));
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index d15f48054e9d..3d5dfbbb871a 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.telephony.BarringInfo;
import android.telephony.CallAttributes;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
@@ -66,4 +67,5 @@ oneway interface IPhoneStateListener {
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
void onRegistrationFailed(in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
+ void onBarringInfoChanged(in BarringInfo barringInfo);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 3176f96ef9ce..866715551a41 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,6 +19,7 @@ package com.android.internal.telephony;
import android.content.Intent;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
+import android.telephony.BarringInfo;
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
@@ -102,4 +103,5 @@ interface ITelephonyRegistry {
void notifyImsDisconnectCause(int subId, in ImsReasonInfo imsReasonInfo);
void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
+ void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
}
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 392e8fe7543f..a5da648cf14a 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -20,9 +20,10 @@ import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
-import android.os.Message;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.ref.WeakReference;
/**
@@ -158,6 +159,7 @@ public class Visualizer {
/**
* Indicates the state of the Visualizer instance
*/
+ @GuardedBy("mStateLock")
private int mState = STATE_UNINITIALIZED;
/**
* Lock to synchronize access to mState
@@ -166,6 +168,7 @@ public class Visualizer {
/**
* System wide unique Identifier of the visualizer engine used by this Visualizer instance
*/
+ @GuardedBy("mStateLock")
@UnsupportedAppUsage
private int mId;
@@ -176,19 +179,24 @@ public class Visualizer {
/**
* Handler for events coming from the native code
*/
- private NativeEventHandler mNativeEventHandler = null;
+ @GuardedBy("mListenerLock")
+ private Handler mNativeEventHandler = null;
/**
* PCM and FFT capture listener registered by client
*/
+ @GuardedBy("mListenerLock")
private OnDataCaptureListener mCaptureListener = null;
/**
* Server Died listener registered by client
*/
+ @GuardedBy("mListenerLock")
private OnServerDiedListener mServerDiedListener = null;
// accessed by native methods
- private long mNativeVisualizer;
- private long mJniData;
+ private long mNativeVisualizer; // guarded by a static lock in native code
+ private long mJniData; // set in native_setup, _release;
+ // get in native_release, _setEnabled, _setPeriodicCapture
+ // thus, effectively guarded by mStateLock
//--------------------------------------------------------------------------
// Constructor, Finalize
@@ -244,7 +252,9 @@ public class Visualizer {
@Override
protected void finalize() {
- native_finalize();
+ synchronized (mStateLock) {
+ native_finalize();
+ }
}
/**
@@ -601,25 +611,28 @@ public class Visualizer {
*/
public int setDataCaptureListener(OnDataCaptureListener listener,
int rate, boolean waveform, boolean fft) {
- synchronized (mListenerLock) {
- mCaptureListener = listener;
- }
if (listener == null) {
// make sure capture callback is stopped in native code
waveform = false;
fft = false;
}
- int status = native_setPeriodicCapture(rate, waveform, fft);
+ int status;
+ synchronized (mStateLock) {
+ status = native_setPeriodicCapture(rate, waveform, fft);
+ }
if (status == SUCCESS) {
- if ((listener != null) && (mNativeEventHandler == null)) {
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mNativeEventHandler = new NativeEventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mNativeEventHandler = new NativeEventHandler(this, looper);
- } else {
- mNativeEventHandler = null;
- status = ERROR_NO_INIT;
+ synchronized (mListenerLock) {
+ mCaptureListener = listener;
+ if ((listener != null) && (mNativeEventHandler == null)) {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mNativeEventHandler = new Handler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mNativeEventHandler = new Handler(looper);
+ } else {
+ mNativeEventHandler = null;
+ status = ERROR_NO_INIT;
+ }
}
}
}
@@ -663,112 +676,61 @@ public class Visualizer {
return SUCCESS;
}
- /**
- * Helper class to handle the forwarding of native events to the appropriate listeners
- */
- private class NativeEventHandler extends Handler
- {
- private Visualizer mVisualizer;
-
- public NativeEventHandler(Visualizer v, Looper looper) {
- super(looper);
- mVisualizer = v;
- }
-
- private void handleCaptureMessage(Message msg) {
- OnDataCaptureListener l = null;
- synchronized (mListenerLock) {
- l = mVisualizer.mCaptureListener;
- }
-
- if (l != null) {
- byte[] data = (byte[])msg.obj;
- int samplingRate = msg.arg1;
-
- switch(msg.what) {
- case NATIVE_EVENT_PCM_CAPTURE:
- l.onWaveFormDataCapture(mVisualizer, data, samplingRate);
- break;
- case NATIVE_EVENT_FFT_CAPTURE:
- l.onFftDataCapture(mVisualizer, data, samplingRate);
- break;
- default:
- Log.e(TAG,"Unknown native event in handleCaptureMessge: "+msg.what);
- break;
- }
- }
- }
-
- private void handleServerDiedMessage(Message msg) {
- OnServerDiedListener l = null;
- synchronized (mListenerLock) {
- l = mVisualizer.mServerDiedListener;
- }
-
- if (l != null)
- l.onServerDied();
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (mVisualizer == null) {
- return;
- }
-
- switch(msg.what) {
- case NATIVE_EVENT_PCM_CAPTURE:
- case NATIVE_EVENT_FFT_CAPTURE:
- handleCaptureMessage(msg);
- break;
- case NATIVE_EVENT_SERVER_DIED:
- handleServerDiedMessage(msg);
- break;
- default:
- Log.e(TAG,"Unknown native event: "+msg.what);
- break;
- }
- }
- }
-
//---------------------------------------------------------
// Interface definitions
//--------------------
private static native final void native_init();
+ @GuardedBy("mStateLock")
private native final int native_setup(Object audioeffect_this,
int audioSession,
int[] id,
String opPackageName);
+ @GuardedBy("mStateLock")
private native final void native_finalize();
+ @GuardedBy("mStateLock")
private native final void native_release();
+ @GuardedBy("mStateLock")
private native final int native_setEnabled(boolean enabled);
+ @GuardedBy("mStateLock")
private native final boolean native_getEnabled();
+ @GuardedBy("mStateLock")
private native final int native_setCaptureSize(int size);
+ @GuardedBy("mStateLock")
private native final int native_getCaptureSize();
+ @GuardedBy("mStateLock")
private native final int native_setScalingMode(int mode);
+ @GuardedBy("mStateLock")
private native final int native_getScalingMode();
+ @GuardedBy("mStateLock")
private native final int native_setMeasurementMode(int mode);
+ @GuardedBy("mStateLock")
private native final int native_getMeasurementMode();
+ @GuardedBy("mStateLock")
private native final int native_getSamplingRate();
+ @GuardedBy("mStateLock")
private native final int native_getWaveForm(byte[] waveform);
+ @GuardedBy("mStateLock")
private native final int native_getFft(byte[] fft);
+ @GuardedBy("mStateLock")
private native final int native_getPeakRms(MeasurementPeakRms measurement);
+ @GuardedBy("mStateLock")
private native final int native_setPeriodicCapture(int rate, boolean waveForm, boolean fft);
//---------------------------------------------------------
@@ -776,17 +738,47 @@ public class Visualizer {
//--------------------
@SuppressWarnings("unused")
private static void postEventFromNative(Object effect_ref,
- int what, int arg1, int arg2, Object obj) {
- Visualizer visu = (Visualizer)((WeakReference)effect_ref).get();
- if (visu == null) {
- return;
- }
+ int what, int samplingRate, byte[] data) {
+ final Visualizer visualizer = (Visualizer) ((WeakReference) effect_ref).get();
+ if (visualizer == null) return;
- if (visu.mNativeEventHandler != null) {
- Message m = visu.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
- visu.mNativeEventHandler.sendMessage(m);
+ final Handler handler;
+ synchronized (visualizer.mListenerLock) {
+ handler = visualizer.mNativeEventHandler;
}
+ if (handler == null) return;
+ switch (what) {
+ case NATIVE_EVENT_PCM_CAPTURE:
+ case NATIVE_EVENT_FFT_CAPTURE:
+ handler.post(() -> {
+ final OnDataCaptureListener l;
+ synchronized (visualizer.mListenerLock) {
+ l = visualizer.mCaptureListener;
+ }
+ if (l != null) {
+ if (what == NATIVE_EVENT_PCM_CAPTURE) {
+ l.onWaveFormDataCapture(visualizer, data, samplingRate);
+ } else { // what == NATIVE_EVENT_FFT_CAPTURE
+ l.onFftDataCapture(visualizer, data, samplingRate);
+ }
+ }
+ });
+ break;
+ case NATIVE_EVENT_SERVER_DIED:
+ handler.post(() -> {
+ final OnServerDiedListener l;
+ synchronized (visualizer.mListenerLock) {
+ l = visualizer.mServerDiedListener;
+ }
+ if (l != null) {
+ l.onServerDied();
+ }
+ });
+ break;
+ default:
+ Log.e(TAG, "Unknown native event in postEventFromNative: " + what);
+ break;
+ }
}
}
-
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index 64c0bb53e894..a891154301ed 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -3,3 +3,7 @@ nchalko@google.com
shubang@google.com
quxiangfang@google.com
+# For android remote service
+per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS
+per-file ITvRemoteProvider.aidl = file:/media/lib/tvremote/OWNERS
+
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 1362433bb26e..f9a77f474c50 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -196,7 +196,6 @@ static void captureCallback(void* user,
callbackInfo->visualizer_ref,
NATIVE_EVENT_PCM_CAPTURE,
samplingrate,
- 0,
jArray);
}
}
@@ -217,7 +216,6 @@ static void captureCallback(void* user,
callbackInfo->visualizer_ref,
NATIVE_EVENT_FFT_CAPTURE,
samplingrate,
- 0,
jArray);
}
}
@@ -286,7 +284,7 @@ android_media_visualizer_native_init(JNIEnv *env)
// Get the postEvent method
fields.midPostNativeEvent = env->GetStaticMethodID(
fields.clazzEffect,
- "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+ "postEventFromNative", "(Ljava/lang/Object;II[B)V");
if (fields.midPostNativeEvent == NULL) {
ALOGE("Can't find Visualizer.%s", "postEventFromNative");
return;
@@ -343,7 +341,7 @@ static void android_media_visualizer_effect_callback(int32_t event,
fields.midPostNativeEvent,
callbackInfo->visualizer_ref,
NATIVE_EVENT_SERVER_DIED,
- 0, 0, NULL);
+ 0, NULL);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index c9c847ff7194..3c7856048860 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -218,24 +218,32 @@ public class A2dpProfile implements LocalBluetoothProfile {
}
public boolean supportsHighQualityAudio(BluetoothDevice device) {
- int support = mService.supportsOptionalCodecs(device);
+ BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ if (bluetoothDevice == null) {
+ return false;
+ }
+ int support = mService.isOptionalCodecsSupported(bluetoothDevice);
return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
}
public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
- int enabled = mService.getOptionalCodecsEnabled(device);
+ BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ if (bluetoothDevice == null) {
+ return false;
+ }
+ int enabled = mService.isOptionalCodecsEnabled(bluetoothDevice);
if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) {
return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED;
- } else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED &&
- supportsHighQualityAudio(device)) {
+ } else if (getConnectionStatus(bluetoothDevice) != BluetoothProfile.STATE_CONNECTED
+ && supportsHighQualityAudio(bluetoothDevice)) {
// Since we don't have a stored preference and the device isn't connected, just return
// true since the default behavior when the device gets connected in the future would be
// to have optional codecs enabled.
return true;
}
BluetoothCodecConfig codecConfig = null;
- if (mService.getCodecStatus(device) != null) {
- codecConfig = mService.getCodecStatus(device).getCodecConfig();
+ if (mService.getCodecStatus(bluetoothDevice) != null) {
+ codecConfig = mService.getCodecStatus(bluetoothDevice).getCodecConfig();
}
if (codecConfig != null) {
return !codecConfig.isMandatoryCodec();
@@ -245,23 +253,28 @@ public class A2dpProfile implements LocalBluetoothProfile {
}
public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
+ BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ if (bluetoothDevice == null) {
+ return;
+ }
int prefValue = enabled
? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
: BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
- mService.setOptionalCodecsEnabled(device, prefValue);
- if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+ mService.setOptionalCodecsEnabled(bluetoothDevice, prefValue);
+ if (getConnectionStatus(bluetoothDevice) != BluetoothProfile.STATE_CONNECTED) {
return;
}
if (enabled) {
- mService.enableOptionalCodecs(device);
+ mService.enableOptionalCodecs(bluetoothDevice);
} else {
- mService.disableOptionalCodecs(device);
+ mService.disableOptionalCodecs(bluetoothDevice);
}
}
public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
+ BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
- if (!supportsHighQualityAudio(device)
+ if (bluetoothDevice == null || !supportsHighQualityAudio(device)
|| getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
return mContext.getString(unknownCodecId);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index bb9d42ecd77c..994a9b32550d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -611,8 +611,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
* If a connect was attempted earlier without any UUID, we will do the connect now.
* Otherwise, allow the connect on UUID change.
*/
- if (!mProfiles.isEmpty()
- && ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime())) {
+ if ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime()) {
+ Log.d(TAG, "onUuidChanged: triggering connectAllEnabledProfiles");
connectAllEnabledProfiles();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index 414c39bc0ce9..9afdd43ce73c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -69,30 +69,31 @@ public class A2dpProfileTest {
mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager);
mServiceListener = mShadowBluetoothAdapter.getServiceListener();
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
+ when(mBluetoothA2dp.getActiveDevice()).thenReturn(mDevice);
}
@Test
public void supportsHighQualityAudio() {
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue();
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
}
@Test
public void isHighQualityAudioEnabled() {
- when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsEnabled(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
- when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsEnabled(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
@@ -100,16 +101,16 @@ public class A2dpProfileTest {
// then isHighQualityAudioEnabled() should return true or false based on whether optional
// codecs are supported. If the device is connected then we should ask it directly, but if
// the device isn't connected then rely on the stored pref about such support.
- when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsEnabled(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
BluetoothProfile.STATE_DISCONNECTED);
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(mDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
@@ -151,14 +152,14 @@ public class A2dpProfileTest {
// Most tests want to simulate optional codecs being supported by the device, so do that
// by default here.
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
}
@Test
public void getLableCodecsNotSupported() {
setupLabelTest();
- when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
}
diff --git a/packages/Tethering/res/values-mcc204-mnc04/strings.xml b/packages/Tethering/res/values-mcc204-mnc04/strings.xml
new file mode 100644
index 000000000000..6bc2e2aa9205
--- /dev/null
+++ b/packages/Tethering/res/values-mcc204-mnc04/strings.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering &amp; Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc310-mnc004/strings.xml b/packages/Tethering/res/values-mcc310-mnc004/strings.xml
new file mode 100644
index 000000000000..6bc2e2aa9205
--- /dev/null
+++ b/packages/Tethering/res/values-mcc310-mnc004/strings.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering &amp; Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc311-mnc480/strings.xml b/packages/Tethering/res/values-mcc311-mnc480/strings.xml
new file mode 100644
index 000000000000..6bc2e2aa9205
--- /dev/null
+++ b/packages/Tethering/res/values-mcc311-mnc480/strings.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering &amp; Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
index ba98a66ff7e0..d50884b2a7b0 100644
--- a/packages/Tethering/res/values/strings.xml
+++ b/packages/Tethering/res/values/strings.xml
@@ -32,4 +32,14 @@
Internet" settings page. That is currently the tether_settings_title_all string. -->
<!-- String for tether notification channel name [CHAR LIMIT=200] -->
<string name="notification_channel_tethering_status">Hotspot &amp; tethering status</string>
+
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title"></string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title"></string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message"></string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button"></string>
</resources> \ No newline at end of file
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index d43c5c682f67..15cdb6ad7a8e 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -284,7 +284,7 @@ public class OffloadController {
final ForwardedStats value = kv.getValue();
final Entry entry = new Entry(kv.getKey(), uid, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, value.rxBytes, 0L, value.txBytes, 0L, 0L);
- stats = stats.addValues(entry);
+ stats = stats.addEntry(entry);
}
return stats;
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 1d100e63215b..fe840864fb99 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -446,12 +446,12 @@ public class OffloadControllerTest {
final NetworkStats ifaceStats = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
final NetworkStats uidStats = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
final NetworkStats expectedUidStats = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStats));
assertTrue(orderInsensitiveEquals(expectedUidStats, uidStats));
@@ -485,12 +485,12 @@ public class OffloadControllerTest {
final NetworkStats ifaceStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
final NetworkStats uidStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
final NetworkStats expectedIfaceStatsAccu = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
final NetworkStats expectedUidStatsAccu = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
assertTrue(orderInsensitiveEquals(expectedIfaceStatsAccu, ifaceStatsAccu));
assertTrue(orderInsensitiveEquals(expectedUidStatsAccu, uidStatsAccu));
@@ -499,12 +499,12 @@ public class OffloadControllerTest {
reset(mTetherStatsProviderCb);
mTetherStatsProvider.pushTetherStats();
final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
verify(mTetherStatsProviderCb, times(1))
.notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
assertTrue(orderInsensitiveEquals(expectedIfaceStatsDiff, ifaceStatsCaptor.getValue()));
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d14d98c914c4..c7ad3e4ed55a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -112,6 +112,7 @@ import android.net.NetworkWatchlistManager;
import android.net.PrivateDnsConfigParcel;
import android.net.ProxyInfo;
import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.TetheringManager;
import android.net.UidRange;
@@ -122,6 +123,7 @@ import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
@@ -234,6 +236,7 @@ import java.util.SortedSet;
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
/**
* @hide
@@ -2230,14 +2233,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
final NetworkInfo ni = intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO);
- if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
- intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- } else {
- BroadcastOptions opts = BroadcastOptions.makeBasic();
- opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
- options = opts.toBundle();
- }
+ final BroadcastOptions opts = BroadcastOptions.makeBasic();
+ opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
+ options = opts.toBundle();
final IBatteryStats bs = mDeps.getBatteryStatsService();
try {
bs.noteConnectivityChanged(intent.getIntExtra(
@@ -5944,15 +5942,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ // TODO: move to frameworks/libs/net.
+ private RouteInfoParcel convertRouteInfo(RouteInfo route) {
+ final String nextHop;
+
+ switch (route.getType()) {
+ case RouteInfo.RTN_UNICAST:
+ if (route.hasGateway()) {
+ nextHop = route.getGateway().getHostAddress();
+ } else {
+ nextHop = INetd.NEXTHOP_NONE;
+ }
+ break;
+ case RouteInfo.RTN_UNREACHABLE:
+ nextHop = INetd.NEXTHOP_UNREACHABLE;
+ break;
+ case RouteInfo.RTN_THROW:
+ nextHop = INetd.NEXTHOP_THROW;
+ break;
+ default:
+ nextHop = INetd.NEXTHOP_NONE;
+ break;
+ }
+
+ final RouteInfoParcel rip = new RouteInfoParcel();
+ rip.ifName = route.getInterface();
+ rip.destination = route.getDestination().toString();
+ rip.nextHop = nextHop;
+ rip.mtu = route.getMtu();
+
+ return rip;
+ }
+
/**
* Have netd update routes from oldLp to newLp.
* @return true if routes changed between oldLp and newLp
*/
private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
- // Compare the route diff to determine which routes should be added and removed.
- CompareResult<RouteInfo> routeDiff = new CompareResult<>(
+ Function<RouteInfo, IpPrefix> getDestination = (r) -> r.getDestination();
+ // compare the route diff to determine which routes have been updated
+ CompareOrUpdateResult<IpPrefix, RouteInfo> routeDiff = new CompareOrUpdateResult<>(
oldLp != null ? oldLp.getAllRoutes() : null,
- newLp != null ? newLp.getAllRoutes() : null);
+ newLp != null ? newLp.getAllRoutes() : null,
+ getDestination);
// add routes before removing old in case it helps with continuous connectivity
@@ -5961,10 +5993,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNMS.addRoute(netId, route);
+ mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
- loge("Exception in addRoute for non-gateway: " + e);
+ loge("Exception in networkAddRouteParcel for non-gateway: " + e);
}
}
}
@@ -5972,10 +6004,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNMS.addRoute(netId, route);
+ mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
if ((route.getGateway() instanceof Inet4Address) || VDBG) {
- loge("Exception in addRoute for gateway: " + e);
+ loge("Exception in networkAddRouteParcel for gateway: " + e);
}
}
}
@@ -5983,12 +6015,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (RouteInfo route : routeDiff.removed) {
if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
try {
- mNMS.removeRoute(netId, route);
+ mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
- loge("Exception in removeRoute: " + e);
+ loge("Exception in networkRemoveRouteParcel: " + e);
}
}
- return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
+
+ for (RouteInfo route : routeDiff.updated) {
+ if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
+ try {
+ mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route));
+ } catch (Exception e) {
+ loge("Exception in networkUpdateRouteParcel: " + e);
+ }
+ }
+ return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty()
+ || !routeDiff.updated.isEmpty();
}
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
@@ -7897,10 +7939,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
+ final Network[] underlyingNetworks;
synchronized (mVpns) {
- if (getVpnIfOwner(callbackUid) != null) {
- return true;
- }
+ final Vpn vpn = getVpnIfOwner(callbackUid);
+ underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks();
+ }
+ if (underlyingNetworks != null) {
+ if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true;
}
// Administrator UIDs also contains the Owner UID
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index f45d54dda620..45868932be2b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -45,6 +45,7 @@ import android.telephony.Annotation;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
+import android.telephony.BarringInfo;
import android.telephony.CallAttributes;
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
@@ -258,6 +259,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private int[] mCallPreciseDisconnectCause;
+ private List<BarringInfo> mBarringInfo = null;
+
private boolean mCarrierNetworkChangeState = false;
private PhoneCapability mPhoneCapability = null;
@@ -451,6 +454,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mCellInfo, mNumPhones);
cutListToSize(mImsReasonInfo, mNumPhones);
cutListToSize(mPreciseDataConnectionStates, mNumPhones);
+ cutListToSize(mBarringInfo, mNumPhones);
return;
}
@@ -483,6 +487,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
mDisplayInfos[i] = null;
+ mBarringInfo.add(i, new BarringInfo());
}
}
@@ -541,6 +546,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mOutgoingCallEmergencyNumber = new EmergencyNumber[numPhones];
mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
mDisplayInfos = new DisplayInfo[numPhones];
+ mBarringInfo = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -569,6 +575,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
mDisplayInfos[i] = null;
+ mBarringInfo.add(i, new BarringInfo());
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1031,6 +1038,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
+ BarringInfo barringInfo = mBarringInfo.get(phoneId);
+ BarringInfo biNoLocation = barringInfo != null
+ ? barringInfo.createLocationInfoSanitizedCopy() : null;
+ if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
+ try {
+ r.callback.onBarringInfoChanged(
+ checkFineLocationAccess(r, Build.VERSION_CODES.R)
+ ? barringInfo : biNoLocation);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -2207,6 +2227,52 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /**
+ * Send a notification of changes to barring status to PhoneStateListener registrants.
+ *
+ * @param phoneId the phoneId
+ * @param subId the subId
+ * @param barringInfo a structure containing the complete updated barring info.
+ */
+ public void notifyBarringInfoChanged(int phoneId, int subId, @NonNull BarringInfo barringInfo) {
+ if (!checkNotifyPermission("notifyBarringInfo()")) {
+ return;
+ }
+ if (barringInfo == null) {
+ log("Received null BarringInfo for subId=" + subId + ", phoneId=" + phoneId);
+ mBarringInfo.set(phoneId, new BarringInfo());
+ return;
+ }
+
+ synchronized (mRecords) {
+ if (validatePhoneId(phoneId)) {
+ mBarringInfo.set(phoneId, barringInfo);
+ // Barring info is non-null
+ BarringInfo biNoLocation = barringInfo.createLocationInfoSanitizedCopy();
+ if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_BARRING_INFO)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ if (DBG_LOC) {
+ log("notifyBarringInfo: mBarringInfo="
+ + barringInfo + " r=" + r);
+ }
+ r.callback.onBarringInfoChanged(
+ checkFineLocationAccess(r, Build.VERSION_CODES.R)
+ ? barringInfo : biNoLocation);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2247,6 +2313,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mPreciseDataConnectionStates=" + mPreciseDataConnectionStates.get(i));
pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
+ pw.println("mBarringInfo=" + mBarringInfo.get(i));
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index fd8db4b99be8..b217dce885d9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -26,7 +26,6 @@ import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PackageDeleteObserver;
-import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
@@ -994,74 +993,57 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
- static class PackageInstallObserverAdapter extends PackageInstallObserver {
- private final Context mContext;
- private final IntentSender mTarget;
- private final int mSessionId;
- private final boolean mShowNotification;
- private final int mUserId;
-
- public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
- boolean showNotification, int userId) {
- mContext = context;
- mTarget = target;
- mSessionId = sessionId;
- mShowNotification = showNotification;
- mUserId = userId;
+ static void sendOnUserActionRequired(Context context, IntentSender target, int sessionId,
+ Intent intent) {
+ final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_PENDING_USER_ACTION);
+ fillIn.putExtra(Intent.EXTRA_INTENT, intent);
+ try {
+ target.sendIntent(context, 0, fillIn, null, null);
+ } catch (SendIntentException ignored) {
}
+ }
- @Override
- public void onUserActionRequired(Intent intent) {
- final Intent fillIn = new Intent();
- fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_PENDING_USER_ACTION);
- fillIn.putExtra(Intent.EXTRA_INTENT, intent);
- try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
- } catch (SendIntentException ignored) {
+ static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
+ boolean showNotification, int userId, String basePackageName, int returnCode,
+ String msg, Bundle extras) {
+ if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
+ boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
+ Notification notification = buildSuccessNotification(context,
+ context.getResources()
+ .getString(update ? R.string.package_updated_device_owner :
+ R.string.package_installed_device_owner),
+ basePackageName,
+ userId);
+ if (notification != null) {
+ NotificationManager notificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(basePackageName,
+ SystemMessage.NOTE_PACKAGE_STATE,
+ notification);
}
}
-
- @Override
- public void onPackageInstalled(String basePackageName, int returnCode, String msg,
- Bundle extras) {
- if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) {
- boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
- Notification notification = buildSuccessNotification(mContext,
- mContext.getResources()
- .getString(update ? R.string.package_updated_device_owner :
- R.string.package_installed_device_owner),
- basePackageName,
- mUserId);
- if (notification != null) {
- NotificationManager notificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.notify(basePackageName,
- SystemMessage.NOTE_PACKAGE_STATE,
- notification);
- }
- }
- final Intent fillIn = new Intent();
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
- fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
- PackageManager.installStatusToPublicStatus(returnCode));
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
- PackageManager.installStatusToString(returnCode, msg));
- fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
- if (extras != null) {
- final String existing = extras.getString(
- PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
- if (!TextUtils.isEmpty(existing)) {
- fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
- }
- }
- try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
- } catch (SendIntentException ignored) {
+ final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
+ PackageManager.installStatusToPublicStatus(returnCode));
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
+ PackageManager.installStatusToString(returnCode, msg));
+ fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
+ if (extras != null) {
+ final String existing = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
+ if (!TextUtils.isEmpty(existing)) {
+ fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
}
}
+ try {
+ target.sendIntent(context, 0, fillIn, null, null);
+ } catch (SendIntentException ignored) {
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7091c7ca7316..d0167c58df9f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -18,7 +18,6 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
-import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
@@ -79,7 +78,6 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.Process;
-import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -107,7 +105,6 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
-import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
import com.android.server.pm.dex.DexManager;
import com.android.server.security.VerityUtils;
@@ -131,7 +128,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String TAG = "PackageInstallerSession";
private static final boolean LOGD = true;
- private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
+ private static final String REMOVE_MARKER_EXTENSION = ".removed";
private static final int MSG_COMMIT = 1;
private static final int MSG_ON_PACKAGE_INSTALLED = 2;
@@ -257,7 +254,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private final ArrayList<FileBridge> mBridges = new ArrayList<>();
@GuardedBy("mLock")
- private IPackageInstallObserver2 mRemoteObserver;
+ private IntentSender mRemoteStatusReceiver;
/** Fields derived from commit parsing */
@GuardedBy("mLock")
@@ -294,9 +291,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private File mResolvedBaseFile;
@GuardedBy("mLock")
- private File mResolvedStageDir;
-
- @GuardedBy("mLock")
private final List<File> mResolvedStagedFiles = new ArrayList<>();
@GuardedBy("mLock")
private final List<File> mResolvedInheritedFiles = new ArrayList<>();
@@ -315,7 +309,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// Installers can't stage directories, so it's fine to ignore
// entries like "lost+found".
if (file.isDirectory()) return false;
- if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+ if (file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
if (DexMetadataHelper.isDexMetadataFile(file)) return false;
if (VerityUtils.isFsveritySignatureFile(file)) return false;
return true;
@@ -325,7 +319,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public boolean accept(File file) {
if (file.isDirectory()) return false;
- if (!file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+ if (!file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
return true;
}
};
@@ -342,14 +336,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final String packageName = (String) args.arg1;
final String message = (String) args.arg2;
final Bundle extras = (Bundle) args.arg3;
- final IPackageInstallObserver2 observer = (IPackageInstallObserver2) args.arg4;
+ final IntentSender statusReceiver = (IntentSender) args.arg4;
final int returnCode = args.argi1;
args.recycle();
- try {
- observer.onPackageInstalled(packageName, returnCode, message, extras);
- } catch (RemoteException ignored) {
- }
+ PackageInstallerService.sendOnPackageInstalled(mContext,
+ statusReceiver, sessionId,
+ isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId,
+ packageName, returnCode, message, extras);
break;
}
@@ -559,23 +553,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- /**
- * Resolve the actual location where staged data should be written. This
- * might point at an ASEC mount point, which is why we delay path resolution
- * until someone actively works with the session.
- */
- @GuardedBy("mLock")
- private File resolveStageDirLocked() throws IOException {
- if (mResolvedStageDir == null) {
- if (stageDir != null) {
- mResolvedStageDir = stageDir;
- } else {
- throw new IOException("Missing stageDir");
- }
- }
- return mResolvedStageDir;
- }
-
@Override
public void setClientProgress(float progress) {
synchronized (mLock) {
@@ -615,14 +592,32 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotCommittedOrDestroyedLocked("getNames");
- try {
- return resolveStageDirLocked().list();
- } catch (IOException e) {
- throw ExceptionUtils.wrap(e);
- }
+ return getNamesLocked();
}
}
+ @GuardedBy("mLock")
+ private String[] getNamesLocked() {
+ return stageDir.list();
+ }
+
+ private static File[] filterFiles(File parent, String[] names, FileFilter filter) {
+ return Arrays.stream(names).map(name -> new File(parent, name)).filter(
+ file -> filter.accept(file)).toArray(File[]::new);
+ }
+
+ @GuardedBy("mLock")
+ private File[] getAddedFilesLocked() {
+ String[] names = getNamesLocked();
+ return filterFiles(stageDir, names, sAddedFilter);
+ }
+
+ @GuardedBy("mLock")
+ private File[] getRemovedFilesLocked() {
+ String[] names = getNamesLocked();
+ return filterFiles(stageDir, names, sRemovedFilter);
+ }
+
@Override
public void removeSplit(String splitName) {
if (TextUtils.isEmpty(params.appPackageName)) {
@@ -641,13 +636,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ private static String getRemoveMarkerName(String name) {
+ final String markerName = name + REMOVE_MARKER_EXTENSION;
+ if (!FileUtils.isValidExtFilename(markerName)) {
+ throw new IllegalArgumentException("Invalid marker: " + markerName);
+ }
+ return markerName;
+ }
+
private void createRemoveSplitMarkerLocked(String splitName) throws IOException {
try {
- final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION;
- if (!FileUtils.isValidExtFilename(markerName)) {
- throw new IllegalArgumentException("Invalid marker: " + markerName);
- }
- final File target = new File(resolveStageDirLocked(), markerName);
+ final File target = new File(stageDir, getRemoveMarkerName(splitName));
target.createNewFile();
Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
} catch (ErrnoException e) {
@@ -681,7 +680,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// will block any attempted install transitions.
final RevocableFileDescriptor fd;
final FileBridge bridge;
- final File stageDir;
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("openWrite");
@@ -695,8 +693,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
bridge = new FileBridge();
mBridges.add(bridge);
}
-
- stageDir = resolveStageDirLocked();
}
try {
@@ -802,7 +798,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid name: " + name);
}
- final File target = new File(resolveStageDirLocked(), name);
+ final File target = new File(stageDir, name);
final FileDescriptor targetFd = Os.open(target.getAbsolutePath(), O_RDONLY, 0);
return new ParcelFileDescriptor(targetFd);
} catch (ErrnoException e) {
@@ -948,7 +944,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* This method may be called multiple times to update the status receiver validate caller
* permissions.
*/
- public boolean markAsCommitted(
+ private boolean markAsCommitted(
@NonNull IntentSender statusReceiver, boolean forTransfer) {
Preconditions.checkNotNull(statusReceiver);
@@ -959,10 +955,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotDestroyedLocked("commit");
- final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
- mContext, statusReceiver, sessionId,
- isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
- mRemoteObserver = adapter.getBinder();
+ mRemoteStatusReceiver = statusReceiver;
if (forTransfer) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
@@ -986,12 +979,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (!mSealed) {
try {
sealAndValidateLocked(childSessions);
- } catch (IOException e) {
- throw new IllegalArgumentException(e);
} catch (PackageManagerException e) {
- // Do now throw an exception here to stay compatible with O and older
- destroyInternal();
- dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
return false;
}
}
@@ -1091,52 +1079,59 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
*/
@GuardedBy("mLock")
private void sealAndValidateLocked(List<PackageInstallerSession> childSessions)
- throws PackageManagerException, IOException {
- assertNoWriteFileTransfersOpenLocked();
- assertPreparedAndNotDestroyedLocked("sealing of session");
-
- mSealed = true;
+ throws PackageManagerException {
+ try {
+ assertNoWriteFileTransfersOpenLocked();
+ assertPreparedAndNotDestroyedLocked("sealing of session");
- if (childSessions != null) {
- assertMultiPackageConsistencyLocked(childSessions);
- }
+ mSealed = true;
- if (params.isStaged) {
- final PackageInstallerSession activeSession = mStagingManager.getActiveSession();
- final boolean anotherSessionAlreadyInProgress =
- activeSession != null && sessionId != activeSession.sessionId
- && mParentSessionId != activeSession.sessionId;
- if (anotherSessionAlreadyInProgress) {
- throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
- "There is already in-progress committed staged session "
- + activeSession.sessionId, null);
+ if (childSessions != null) {
+ assertMultiPackageConsistencyLocked(childSessions);
}
- }
- // Read transfers from the original owner stay open, but as the session's data
- // cannot be modified anymore, there is no leak of information. For staged sessions,
- // further validation is performed by the staging manager.
- if (!params.isMultiPackage) {
- final PackageInfo pkgInfo = mPm.getPackageInfo(
- params.appPackageName, PackageManager.GET_SIGNATURES
- | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+ if (params.isStaged) {
+ final PackageInstallerSession activeSession = mStagingManager.getActiveSession();
+ final boolean anotherSessionAlreadyInProgress =
+ activeSession != null && sessionId != activeSession.sessionId
+ && mParentSessionId != activeSession.sessionId;
+ if (anotherSessionAlreadyInProgress) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ "There is already in-progress committed staged session "
+ + activeSession.sessionId, null);
+ }
+ }
- resolveStageDirLocked();
+ // Read transfers from the original owner stay open, but as the session's data
+ // cannot be modified anymore, there is no leak of information. For staged sessions,
+ // further validation is performed by the staging manager.
+ if (!params.isMultiPackage) {
+ final PackageInfo pkgInfo = mPm.getPackageInfo(
+ params.appPackageName, PackageManager.GET_SIGNATURES
+ | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
- try {
- if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
- validateApexInstallLocked();
- } else {
- validateApkInstallLocked(pkgInfo);
+ try {
+ if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+ validateApexInstallLocked();
+ } else {
+ validateApkInstallLocked(pkgInfo);
+ }
+ } catch (PackageManagerException e) {
+ throw e;
+ } catch (Throwable e) {
+ // Convert all exceptions into package manager exceptions as only those are
+ // handled in the code above.
+ throw new PackageManagerException(e);
}
- } catch (PackageManagerException e) {
- throw e;
- } catch (Throwable e) {
- // Convert all exceptions into package manager exceptions as only those are handled
- // in the code above
- throw new PackageManagerException(e);
}
+ } catch (PackageManagerException e) {
+ // Session is sealed but could not be verified, we need to destroy it.
+ destroyInternal();
+ // Dispatch message to remove session from PackageInstallerService
+ dispatchSessionFinished(
+ e.error, ExceptionUtils.getCompleteMessage(e), null);
+ throw e;
}
}
@@ -1159,15 +1154,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
synchronized (mLock) {
try {
sealAndValidateLocked(childSessions);
- } catch (IOException e) {
- throw new IllegalStateException(e);
} catch (PackageManagerException e) {
Slog.e(TAG, "Package not valid", e);
- // Session is sealed but could not be verified, we need to destroy it.
- destroyInternal();
- // Dispatch message to remove session from PackageInstallerService
- dispatchSessionFinished(
- e.error, ExceptionUtils.getCompleteMessage(e), null);
}
}
}
@@ -1208,13 +1196,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
try {
sealAndValidateLocked(childSessions);
- } catch (IOException e) {
- throw new IllegalStateException(e);
} catch (PackageManagerException e) {
- // Session is sealed but could not be verified, we need to destroy it
- destroyInternal();
- dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
-
throw new IllegalArgumentException("Package is not valid", e);
}
@@ -1299,11 +1281,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
if (!success) {
- try {
- mRemoteObserver.onPackageInstalled(
- null, failure.error, failure.getLocalizedMessage(), null);
- } catch (RemoteException ignored) {
- }
+ PackageInstallerService.sendOnPackageInstalled(mContext,
+ mRemoteStatusReceiver, sessionId,
+ isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
+ failure.error, failure.getLocalizedMessage(), null);
return;
}
mPm.installStage(activeChildSessions);
@@ -1347,10 +1328,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
intent.setPackage(mPm.getPackageInstallerPackageName());
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- try {
- mRemoteObserver.onUserActionRequired(intent);
- } catch (RemoteException ignored) {
- }
+
+ PackageInstallerService.sendOnUserActionRequired(mContext,
+ mRemoteStatusReceiver, sessionId, intent);
// Commit was keeping session marked as active until now; release
// that extra refcount so session appears idle.
@@ -1363,7 +1343,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
try {
final List<File> fromFiles = mResolvedInheritedFiles;
- final File toDir = resolveStageDirLocked();
+ final File toDir = stageDir;
if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
@@ -1413,8 +1393,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
computeProgressLocked(true);
// Unpack native libraries
- extractNativeLibraries(mResolvedStageDir, params.abiOverride,
- mayInheritNativeLibs());
+ extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
}
// We've reached point of no return; call into PMS to install the stage.
@@ -1475,7 +1454,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private void validateApexInstallLocked()
throws PackageManagerException {
- final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
+ final File[] addedFiles = getAddedFilesLocked();
if (ArrayUtils.isEmpty(addedFiles)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
}
@@ -1485,13 +1464,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"Too many files for apex install");
}
- try {
- resolveStageDirLocked();
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
- "Failed to resolve stage location", e);
- }
-
File addedFile = addedFiles[0]; // there is only one file
// Ensure file name has proper suffix
@@ -1504,7 +1476,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"Invalid filename: " + targetName);
}
- final File targetFile = new File(mResolvedStageDir, targetName);
+ final File targetFile = new File(stageDir, targetName);
resolveAndStageFile(addedFile, targetFile);
mResolvedBaseFile = targetFile;
@@ -1545,25 +1517,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
&& params.mode == SessionParams.MODE_INHERIT_EXISTING
&& VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath());
- try {
- resolveStageDirLocked();
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
- "Failed to resolve stage location", e);
- }
-
- final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
+ final File[] removedFiles = getRemovedFilesLocked();
final List<String> removeSplitList = new ArrayList<>();
if (!ArrayUtils.isEmpty(removedFiles)) {
for (File removedFile : removedFiles) {
final String fileName = removedFile.getName();
final String splitName = fileName.substring(
- 0, fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length());
+ 0, fileName.length() - REMOVE_MARKER_EXTENSION.length());
removeSplitList.add(splitName);
}
}
- final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
+ final File[] addedFiles = getAddedFilesLocked();
if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
}
@@ -1607,7 +1572,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"Invalid filename: " + targetName);
}
- final File targetFile = new File(mResolvedStageDir, targetName);
+ final File targetFile = new File(stageDir, targetName);
resolveAndStageFile(addedFile, targetFile);
// Base is coming from session
@@ -1622,7 +1587,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Invalid filename: " + dexMetadataFile);
}
- final File targetDexMetadataFile = new File(mResolvedStageDir,
+ final File targetDexMetadataFile = new File(stageDir,
DexMetadataHelper.buildDexMetadataPathForApk(targetName));
resolveAndStageFile(dexMetadataFile, targetDexMetadataFile);
}
@@ -2182,17 +2147,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
- final IPackageInstallObserver2 observer;
+ final IntentSender statusReceiver;
final String packageName;
synchronized (mLock) {
mFinalStatus = returnCode;
mFinalMessage = msg;
- observer = mRemoteObserver;
+ statusReceiver = mRemoteStatusReceiver;
packageName = mPackageName;
}
- if (observer != null) {
+ if (statusReceiver != null) {
// Execute observer.onPackageInstalled on different tread as we don't want callers
// inside the system server have to worry about catching the callbacks while they are
// calling into the session
@@ -2200,7 +2165,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
args.arg1 = packageName;
args.arg2 = msg;
args.arg3 = extras;
- args.arg4 = observer;
+ args.arg4 = statusReceiver;
args.argi1 = returnCode;
mHandler.obtainMessage(MSG_ON_PACKAGE_INSTALLED, args).sendToTarget();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 54ab906e9924..ba4e11a3d8c5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -343,7 +343,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
- /** @see #computeCompatSmallestWidth(boolean, int, int, int, DisplayCutout) */
+ /** @see #computeCompatSmallestWidth(boolean, int, int, int) */
private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
/**
@@ -1715,7 +1715,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
- dh, displayInfo.displayCutout);
+ dh);
config.densityDpi = displayInfo.logicalDensityDpi;
config.colorMode =
@@ -1800,8 +1800,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
- private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
- DisplayCutout displayCutout) {
+ private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh) {
mTmpDisplayMetrics.setTo(mDisplayMetrics);
final DisplayMetrics tmpDm = mTmpDisplayMetrics;
final int unrotDw, unrotDh;
@@ -1812,19 +1811,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
unrotDw = dw;
unrotDh = dh;
}
- int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
- displayCutout);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
- displayCutout);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
- displayCutout);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
- displayCutout);
+ int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw,
+ unrotDh);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh,
+ unrotDw);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw,
+ unrotDh);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh,
+ unrotDw);
return sw;
}
private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
- DisplayMetrics dm, int dw, int dh, DisplayCutout displayCutout) {
+ DisplayMetrics dm, int dw, int dh) {
+ final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
+ rotation).getDisplayCutout();
dm.noncompatWidthPixels = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
displayCutout);
dm.noncompatHeightPixels = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
@@ -1865,20 +1866,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return;
}
int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
- displayInfo.displayCutout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
- displayInfo.displayCutout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
- displayInfo.displayCutout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
- displayInfo.displayCutout);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
outConfig.screenLayout = sl;
}
private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
- int uiMode, DisplayCutout displayCutout) {
+ int uiMode) {
+ // Get the display cutout at this rotation.
+ final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
+ rotation).getDisplayCutout();
+
// Get the app screen size at this rotation.
int w = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout);
int h = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout);
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 98a649fb0fc3..1a049e6c517e 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -1051,8 +1051,7 @@ public final class SmsApplication {
}
/**
- * Check if a package is default sms app (or equivalent, like bluetooth), and verify that
- * packageName belongs to the caller.
+ * Check if a package is default sms app (or equivalent, like bluetooth)
*
* @param context context from the calling app
* @param packageName the name of the package to be checked
@@ -1061,22 +1060,8 @@ public final class SmsApplication {
@UnsupportedAppUsage
public static boolean isDefaultSmsApplication(Context context, String packageName) {
if (packageName == null) {
- Log.e(LOG_TAG, "isDefaultSmsApplication: packageName is null");
return false;
}
- try {
- if (Binder.getCallingUid()
- == context.getPackageManager().getPackageUid(packageName, 0)) {
- Log.e(LOG_TAG, "isDefaultSmsApplication: " + packageName + " calling uid "
- + context.getPackageManager().getPackageUid(packageName, 0)
- + " does not match calling uid " + Binder.getCallingUid());
- return false;
- }
- } catch (NameNotFoundException ex) {
- Log.e(LOG_TAG, "isDefaultSmsApplication: packageName " + packageName + " not found");
- return false;
- }
-
final String defaultSmsPackage = getDefaultSmsApplicationPackageName(context);
if ((defaultSmsPackage != null && defaultSmsPackage.equals(packageName))
|| BLUETOOTH_PACKAGE_NAME.equals(packageName)) {
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index ef11f469d9a0..ae2652e6c229 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -31,7 +31,9 @@ import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
+import android.telephony.euicc.EuiccManager;
import android.telephony.euicc.EuiccManager.OtaStatus;
+import android.text.TextUtils;
import android.util.Log;
import java.io.PrintWriter;
@@ -311,6 +313,64 @@ public abstract class EuiccService extends Service {
mStubWrapper = new IEuiccServiceWrapper();
}
+ /**
+ * Given a SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2), encode it to
+ * the format described in
+ * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}
+ *
+ * @param subjectCode SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2)
+ * @param reasonCode ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2)
+ * @return encoded error code described in
+ * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}
+ * @throws NumberFormatException when the Subject/Reason code contains non digits
+ * @throws IllegalArgumentException when Subject/Reason code is null/empty
+ * @throws UnsupportedOperationException when sections has more than four layers (e.g 5.8.1.2)
+ * or when an number is bigger than 15
+ */
+ public int encodeSmdxSubjectAndReasonCode(@NonNull String subjectCode,
+ @NonNull String reasonCode) {
+ final int maxSupportedSection = 3;
+ final int maxSupportedDigit = 15;
+ final int bitsPerSection = 4;
+
+ if (TextUtils.isEmpty(subjectCode) || TextUtils.isEmpty(reasonCode)) {
+ throw new IllegalArgumentException("SubjectCode/ReasonCode is empty");
+ }
+
+ final String[] subjectCodeToken = subjectCode.split("\\.");
+ final String[] reasonCodeToken = reasonCode.split("\\.");
+
+ if (subjectCodeToken.length > maxSupportedSection
+ || reasonCodeToken.length > maxSupportedSection) {
+ throw new UnsupportedOperationException("Only three nested layer is supported.");
+ }
+
+ int result = EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE;
+
+ // Pad the 0s needed for subject code
+ result = result << (maxSupportedSection - subjectCodeToken.length) * bitsPerSection;
+
+ for (String digitString : subjectCodeToken) {
+ int num = Integer.parseInt(digitString);
+ if (num > maxSupportedDigit) {
+ throw new UnsupportedOperationException("SubjectCode exceeds " + maxSupportedDigit);
+ }
+ result = (result << bitsPerSection) + num;
+ }
+
+ // Pad the 0s needed for reason code
+ result = result << (maxSupportedSection - reasonCodeToken.length) * bitsPerSection;
+ for (String digitString : reasonCodeToken) {
+ int num = Integer.parseInt(digitString);
+ if (num > maxSupportedDigit) {
+ throw new UnsupportedOperationException("ReasonCode exceeds " + maxSupportedDigit);
+ }
+ result = (result << bitsPerSection) + num;
+ }
+
+ return result;
+ }
+
@Override
@CallSuper
public void onCreate() {
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 0325c36e227e..85db35d1ca08 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -571,6 +571,19 @@ public class Annotation {
public @interface PreciseDisconnectCauses {
}
+ /**
+ * Carrier Privilege Status.
+ */
+ @IntDef(prefix = { "CARRIER_PRIVILEGE_STATUS_" }, value = {
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CarrierPrivilegeStatus {
+ }
+
@IntDef({
Connection.AUDIO_CODEC_NONE,
Connection.AUDIO_CODEC_AMR,
diff --git a/telephony/java/android/telephony/BarringInfo.aidl b/telephony/java/android/telephony/BarringInfo.aidl
new file mode 100644
index 000000000000..50ddf6b31919
--- /dev/null
+++ b/telephony/java/android/telephony/BarringInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable BarringInfo;
diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java
new file mode 100644
index 000000000000..92423a2f2218
--- /dev/null
+++ b/telephony/java/android/telephony/BarringInfo.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides the barring configuration for a particular service type.
+ *
+ * Provides indication about the barring of a particular service for use. Certain barring types
+ * are only valid for certain technology families. Any service that does not have a barring
+ * configuration is unbarred by default.
+ */
+public final class BarringInfo implements Parcelable {
+
+ /**
+ * Barring Service Type
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "BARRING_SERVICE_TYPE_", value = {
+ BARRING_SERVICE_TYPE_CS_SERVICE,
+ BARRING_SERVICE_TYPE_PS_SERVICE,
+ BARRING_SERVICE_TYPE_CS_VOICE,
+ BARRING_SERVICE_TYPE_MO_SIGNALLING,
+ BARRING_SERVICE_TYPE_MO_DATA,
+ BARRING_SERVICE_TYPE_CS_FALLBACK,
+ BARRING_SERVICE_TYPE_MMTEL_VOICE,
+ BARRING_SERVICE_TYPE_MMTEL_VIDEO,
+ BARRING_SERVICE_TYPE_EMERGENCY,
+ BARRING_SERVICE_TYPE_SMS})
+ public @interface BarringServiceType {}
+
+ /* Applicabe to UTRAN */
+ /** Barring indicator for circuit-switched service; applicable to UTRAN */
+ public static final int BARRING_SERVICE_TYPE_CS_SERVICE =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_SERVICE;
+ /** Barring indicator for packet-switched service; applicable to UTRAN */
+ public static final int BARRING_SERVICE_TYPE_PS_SERVICE =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.PS_SERVICE;
+ /** Barring indicator for circuit-switched voice service; applicable to UTRAN */
+ public static final int BARRING_SERVICE_TYPE_CS_VOICE =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_VOICE;
+
+ /* Applicable to EUTRAN, NGRAN */
+ /** Barring indicator for mobile-originated signalling; applicable to EUTRAN and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_MO_SIGNALLING =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_SIGNALLING;
+ /** Barring indicator for mobile-originated data traffic; applicable to EUTRAN and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_MO_DATA =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_DATA;
+ /** Barring indicator for circuit-switched fallback for voice; applicable to EUTRAN and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_CS_FALLBACK =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_FALLBACK;
+ /** Barring indicator for MMTEL (IMS) voice; applicable to EUTRAN and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VOICE;
+ /** Barring indicator for MMTEL (IMS) video; applicable to EUTRAN and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VIDEO;
+
+ /* Applicable to UTRAN, EUTRAN, NGRAN */
+ /** Barring indicator for emergency services; applicable to UTRAN, EUTRAN, and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_EMERGENCY =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.EMERGENCY;
+ /** Barring indicator for SMS sending; applicable to UTRAN, EUTRAN, and NGRAN */
+ public static final int BARRING_SERVICE_TYPE_SMS =
+ android.hardware.radio.V1_5.BarringInfo.ServiceType.SMS;
+
+ //TODO: add barring constants for Operator-Specific barring codes
+
+ /** Describe the current barring configuration of a cell */
+ public static final class BarringServiceInfo implements Parcelable {
+ /**
+ * Barring Type
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "BARRING_TYPE_", value =
+ {BARRING_TYPE_NONE,
+ BARRING_TYPE_UNCONDITIONAL,
+ BARRING_TYPE_CONDITIONAL,
+ BARRING_TYPE_UNKNOWN})
+ public @interface BarringType {}
+
+ /** Barring is inactive */
+ public static final int BARRING_TYPE_NONE =
+ android.hardware.radio.V1_5.BarringInfo.BarringType.NONE;
+ /** The service is barred */
+ public static final int BARRING_TYPE_UNCONDITIONAL =
+ android.hardware.radio.V1_5.BarringInfo.BarringType.UNCONDITIONAL;
+ /** The service may be barred based on additional factors */
+ public static final int BARRING_TYPE_CONDITIONAL =
+ android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL;
+
+ /** If a modem does not report barring info, then the barring type will be UNKNOWN */
+ public static final int BARRING_TYPE_UNKNOWN = -1;
+
+ private final @BarringType int mBarringType;
+
+ private final boolean mIsConditionallyBarred;
+ private final int mConditionalBarringFactor;
+ private final int mConditionalBarringTimeSeconds;
+
+ /** @hide */
+ public BarringServiceInfo(@BarringType int type) {
+ this(type, false, 0, 0);
+ }
+
+ /** @hide */
+ @TestApi
+ public BarringServiceInfo(@BarringType int barringType, boolean isConditionallyBarred,
+ int conditionalBarringFactor, int conditionalBarringTimeSeconds) {
+ mBarringType = barringType;
+ mIsConditionallyBarred = isConditionallyBarred;
+ mConditionalBarringFactor = conditionalBarringFactor;
+ mConditionalBarringTimeSeconds = conditionalBarringTimeSeconds;
+ }
+
+ public @BarringType int getBarringType() {
+ return mBarringType;
+ }
+
+ /**
+ * @return true if the conditional barring parameters have resulted in the service being
+ * barred; false if the service has either not been evaluated for conditional
+ * barring or has been evaluated and isn't barred.
+ */
+ public boolean isConditionallyBarred() {
+ return mIsConditionallyBarred;
+ }
+
+ /**
+ * @return the conditional barring factor as a percentage 0-100, which is the probability of
+ * a random device being barred for the service type.
+ */
+ public int getConditionalBarringFactor() {
+ return mConditionalBarringFactor;
+ }
+
+ /**
+ * @return the conditional barring time seconds, which is the interval between successive
+ * evaluations for conditional barring based on the barring factor.
+ */
+ @SuppressLint("MethodNameUnits")
+ public int getConditionalBarringTimeSeconds() {
+ return mConditionalBarringTimeSeconds;
+ }
+
+ /**
+ * Return whether a service is currently barred based on the BarringInfo
+ *
+ * @return true if the service is currently being barred, otherwise false
+ */
+ public boolean isBarred() {
+ return mBarringType == BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL
+ || (mBarringType == BarringServiceInfo.BARRING_TYPE_CONDITIONAL
+ && mIsConditionallyBarred);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mBarringType, mIsConditionallyBarred,
+ mConditionalBarringFactor, mConditionalBarringTimeSeconds);
+ }
+
+ @Override
+ public boolean equals(Object rhs) {
+ if (!(rhs instanceof BarringServiceInfo)) return false;
+
+ BarringServiceInfo other = (BarringServiceInfo) rhs;
+ return mBarringType == other.mBarringType
+ && mIsConditionallyBarred == other.mIsConditionallyBarred
+ && mConditionalBarringFactor == other.mConditionalBarringFactor
+ && mConditionalBarringTimeSeconds == other.mConditionalBarringTimeSeconds;
+ }
+
+ /** @hide */
+ public BarringServiceInfo(Parcel p) {
+ mBarringType = p.readInt();
+ mIsConditionallyBarred = p.readBoolean();
+ mConditionalBarringFactor = p.readInt();
+ mConditionalBarringTimeSeconds = p.readInt();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mBarringType);
+ dest.writeBoolean(mIsConditionallyBarred);
+ dest.writeInt(mConditionalBarringFactor);
+ dest.writeInt(mConditionalBarringTimeSeconds);
+ }
+
+ /* @inheritDoc */
+ public static final @NonNull Parcelable.Creator<BarringServiceInfo> CREATOR =
+ new Parcelable.Creator<BarringServiceInfo>() {
+ @Override
+ public BarringServiceInfo createFromParcel(Parcel source) {
+ return new BarringServiceInfo(source);
+ }
+
+ @Override
+ public BarringServiceInfo[] newArray(int size) {
+ return new BarringServiceInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+ }
+
+ private static final BarringServiceInfo BARRING_SERVICE_INFO_UNKNOWN =
+ new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_UNKNOWN);
+
+ private static final BarringServiceInfo BARRING_SERVICE_INFO_UNBARRED =
+ new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_NONE);
+
+ private CellIdentity mCellIdentity;
+
+ // A SparseArray potentially mapping each BarringService type to a BarringServiceInfo config
+ // that describes the current barring status of that particular service.
+ private SparseArray<BarringServiceInfo> mBarringServiceInfos;
+
+ /** @hide */
+ @TestApi
+ @SystemApi
+ public BarringInfo() {
+ mBarringServiceInfos = new SparseArray<>();
+ }
+
+ /**
+ * Constructor for new BarringInfo instances.
+ *
+ * @hide
+ */
+ @TestApi
+ public BarringInfo(@Nullable CellIdentity barringCellId,
+ @NonNull SparseArray<BarringServiceInfo> barringServiceInfos) {
+ mCellIdentity = barringCellId;
+ mBarringServiceInfos = barringServiceInfos;
+ }
+
+ /** @hide */
+ public static BarringInfo create(
+ @NonNull android.hardware.radio.V1_5.CellIdentity halBarringCellId,
+ @NonNull List<android.hardware.radio.V1_5.BarringInfo> halBarringInfos) {
+ CellIdentity ci = CellIdentity.create(halBarringCellId);
+ SparseArray<BarringServiceInfo> serviceInfos = new SparseArray<>();
+
+ for (android.hardware.radio.V1_5.BarringInfo halBarringInfo : halBarringInfos) {
+ if (halBarringInfo.barringType
+ == android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL) {
+ if (halBarringInfo.barringTypeSpecificInfo.getDiscriminator()
+ != android.hardware.radio.V1_5.BarringInfo.BarringTypeSpecificInfo
+ .hidl_discriminator.conditional) {
+ // this is an error case where the barring info is conditional but the
+ // conditional barring fields weren't included
+ continue;
+ }
+ android.hardware.radio.V1_5.BarringInfo.BarringTypeSpecificInfo
+ .Conditional conditionalInfo =
+ halBarringInfo.barringTypeSpecificInfo.conditional();
+ serviceInfos.put(
+ halBarringInfo.serviceType, new BarringServiceInfo(
+ halBarringInfo.barringType, // will always be CONDITIONAL here
+ conditionalInfo.isBarred,
+ conditionalInfo.factor,
+ conditionalInfo.timeSeconds));
+ } else {
+ // Barring type is either NONE or UNCONDITIONAL
+ serviceInfos.put(
+ halBarringInfo.serviceType, new BarringServiceInfo(
+ halBarringInfo.barringType, false, 0, 0));
+ }
+ }
+ return new BarringInfo(ci, serviceInfos);
+ }
+
+ /**
+ * Get the BarringServiceInfo for a specified service.
+ *
+ * @return a BarringServiceInfo struct describing the current barring status for a service
+ */
+ public @NonNull BarringServiceInfo getBarringServiceInfo(@BarringServiceType int service) {
+ BarringServiceInfo bsi = mBarringServiceInfos.get(service);
+ // If barring is reported but not for a particular service, then we report the barring
+ // type as UNKNOWN; if the modem reports barring info but doesn't report for a particular
+ // service then we can safely assume that the service isn't barred (for instance because
+ // that particular service isn't applicable to the current RAN).
+ return (bsi != null) ? bsi : mBarringServiceInfos.size() > 0
+ ? BARRING_SERVICE_INFO_UNBARRED : BARRING_SERVICE_INFO_UNKNOWN;
+ }
+
+ /** @hide */
+ @SystemApi
+ public @NonNull BarringInfo createLocationInfoSanitizedCopy() {
+ // The only thing that would need sanitizing is the CellIdentity
+ if (mCellIdentity == null) return this;
+
+ return new BarringInfo(mCellIdentity.sanitizeLocationInfo(), mBarringServiceInfos);
+ }
+
+ /** @hide */
+ public BarringInfo(Parcel p) {
+ mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader());
+ mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader());
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mCellIdentity, flags);
+ dest.writeSparseArray(mBarringServiceInfos);
+ }
+
+ public static final @NonNull Parcelable.Creator<BarringInfo> CREATOR =
+ new Parcelable.Creator<BarringInfo>() {
+ @Override
+ public BarringInfo createFromParcel(Parcel source) {
+ return new BarringInfo(source);
+ }
+
+ @Override
+ public BarringInfo[] newArray(int size) {
+ return new BarringInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = mCellIdentity != null ? mCellIdentity.hashCode() : 7;
+ for (int i = 0; i < mBarringServiceInfos.size(); i++) {
+ hash = hash + 15 * mBarringServiceInfos.keyAt(i);
+ hash = hash + 31 * mBarringServiceInfos.valueAt(i).hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object rhs) {
+ if (!(rhs instanceof BarringInfo)) return false;
+
+ BarringInfo bi = (BarringInfo) rhs;
+
+ if (hashCode() != bi.hashCode()) return false;
+
+ if (mBarringServiceInfos.size() != bi.mBarringServiceInfos.size()) return false;
+
+ for (int i = 0; i < mBarringServiceInfos.size(); i++) {
+ if (mBarringServiceInfos.keyAt(i) != bi.mBarringServiceInfos.keyAt(i)) return false;
+ if (!Objects.equals(mBarringServiceInfos.valueAt(i),
+ bi.mBarringServiceInfos.valueAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "BarringInfo {mCellIdentity=" + mCellIdentity
+ + ", mBarringServiceInfos=" + mBarringServiceInfos + "}";
+ }
+}
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index d8a65517c90f..3e901e241e01 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -25,6 +25,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.NetworkType;
+import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -214,6 +215,9 @@ public final class NetworkRegistrationInfo implements Parcelable {
@Nullable
private DataSpecificRegistrationInfo mDataSpecificInfo;
+ @NonNull
+ private String mRplmn;
+
/**
* @param domain Network domain. Must be a {@link Domain}. For transport type
* {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}.
@@ -234,13 +238,14 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @param availableServices The list of the supported services.
* @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
* information is not available.
+ * @param rplmn the registered plmn or the last plmn for attempted registration if reg failed.
*/
private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
@RegistrationState int registrationState,
@NetworkType int accessNetworkTechnology, int rejectCause,
boolean emergencyOnly,
@Nullable @ServiceType List<Integer> availableServices,
- @Nullable CellIdentity cellIdentity) {
+ @Nullable CellIdentity cellIdentity, @Nullable String rplmn) {
mDomain = domain;
mTransportType = transportType;
mRegistrationState = registrationState;
@@ -253,6 +258,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
mCellIdentity = cellIdentity;
mEmergencyOnly = emergencyOnly;
mNrState = NR_STATE_NONE;
+ mRplmn = rplmn;
}
/**
@@ -263,11 +269,11 @@ public final class NetworkRegistrationInfo implements Parcelable {
int registrationState, int accessNetworkTechnology,
int rejectCause, boolean emergencyOnly,
@Nullable List<Integer> availableServices,
- @Nullable CellIdentity cellIdentity, boolean cssSupported,
- int roamingIndicator, int systemIsInPrl,
+ @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
+ boolean cssSupported, int roamingIndicator, int systemIsInPrl,
int defaultRoamingIndicator) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity);
+ emergencyOnly, availableServices, cellIdentity, rplmn);
mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
systemIsInPrl, defaultRoamingIndicator);
@@ -281,13 +287,13 @@ public final class NetworkRegistrationInfo implements Parcelable {
int registrationState, int accessNetworkTechnology,
int rejectCause, boolean emergencyOnly,
@Nullable List<Integer> availableServices,
- @Nullable CellIdentity cellIdentity, int maxDataCalls,
- boolean isDcNrRestricted, boolean isNrAvailable,
- boolean isEndcAvailable,
+ @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
+ int maxDataCalls, boolean isDcNrRestricted,
+ boolean isNrAvailable, boolean isEndcAvailable,
LteVopsSupportInfo lteVopsSupportInfo,
boolean isUsingCarrierAggregation) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity);
+ emergencyOnly, availableServices, cellIdentity, rplmn);
mDataSpecificInfo = new DataSpecificRegistrationInfo(
maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo,
isUsingCarrierAggregation);
@@ -310,6 +316,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
mDataSpecificInfo = source.readParcelable(
DataSpecificRegistrationInfo.class.getClassLoader());
mNrState = source.readInt();
+ mRplmn = source.readString();
}
/**
@@ -343,6 +350,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
mDataSpecificInfo = new DataSpecificRegistrationInfo(nri.mDataSpecificInfo);
}
mNrState = nri.mNrState;
+ mRplmn = nri.mRplmn;
}
/**
@@ -395,6 +403,22 @@ public final class NetworkRegistrationInfo implements Parcelable {
}
/**
+ * 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
+ * has failed, then this will return the PLMN ID of the last attempted registration. If the
+ * device is not registered, or if is registered to a non-3GPP radio technology, then this
+ * will return null.
+ *
+ * <p>See 3GPP TS 23.122 for further information about the Registered PLMN.
+ *
+ * @return the registered PLMN-ID or null.
+ */
+ @Nullable public String getRegisteredPlmn() {
+ return mRplmn;
+ }
+
+ /**
* @return {@code true} if registered on roaming network, {@code false} otherwise.
*/
public boolean isRoaming() {
@@ -590,6 +614,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
.append(" voiceSpecificInfo=").append(mVoiceSpecificInfo)
.append(" dataSpecificInfo=").append(mDataSpecificInfo)
.append(" nrState=").append(nrStateToString(mNrState))
+ .append(" rRplmn=").append(mRplmn)
.append("}").toString();
}
@@ -597,7 +622,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
public int hashCode() {
return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
- mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState);
+ mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState, mRplmn);
}
@Override
@@ -620,6 +645,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
&& Objects.equals(mCellIdentity, other.mCellIdentity)
&& Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo)
&& Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo)
+ && TextUtils.equals(mRplmn, other.mRplmn)
&& mNrState == other.mNrState;
}
@@ -641,6 +667,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
dest.writeParcelable(mVoiceSpecificInfo, 0);
dest.writeParcelable(mDataSpecificInfo, 0);
dest.writeInt(mNrState);
+ dest.writeString(mRplmn);
}
/**
@@ -741,6 +768,9 @@ public final class NetworkRegistrationInfo implements Parcelable {
@Nullable
private CellIdentity mCellIdentity;
+ @NonNull
+ private String mRplmn = "";
+
/**
* Default constructor for Builder.
*/
@@ -855,6 +885,18 @@ public final class NetworkRegistrationInfo implements Parcelable {
}
/**
+ * Set the registered PLMN.
+ *
+ * @param rplmn the registered plmn.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setRegisteredPlmn(@Nullable String rplmn) {
+ mRplmn = rplmn;
+ return this;
+ }
+
+ /**
* Build the NetworkRegistrationInfo.
* @return the NetworkRegistrationInfo object.
* @hide
@@ -863,7 +905,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
public @NonNull NetworkRegistrationInfo build() {
return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
- mCellIdentity);
+ mCellIdentity, mRplmn);
}
}
}
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 54c22ae282fb..708adebb6db3 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -265,10 +265,10 @@ public final class PreciseDataConnectionState implements Parcelable {
/**
* Return the APN Settings for this data connection.
*
- * Returns the ApnSetting that was used to configure this data connection.
+ * @return the ApnSetting that was used to configure this data connection.
*/
// FIXME: This shouldn't be nullable; update once the ApnSetting is supplied correctly
- @Nullable ApnSetting getApnSetting() {
+ public @Nullable ApnSetting getApnSetting() {
return mApnSetting;
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index fe78588121c6..2714facc7a7f 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2751,7 +2751,7 @@ public final class SmsManager {
getSubscriptionId(), null);
}
} catch (RemoteException ex) {
- throw new RuntimeException(ex);
+ // ignore it
}
return smsc;
}
@@ -2773,8 +2773,7 @@ public final class SmsManager {
* </p>
*
* @param smsc the SMSC address string.
- * @return true for success, false otherwise. Failure can be due to caller not having the
- * appropriate permission, or modem returning an error.
+ * @return true for success, false otherwise.
*/
@SuppressAutoDoc // for carrier privileges and default SMS application.
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -2786,7 +2785,7 @@ public final class SmsManager {
smsc, getSubscriptionId(), null);
}
} catch (RemoteException ex) {
- throw new RuntimeException(ex);
+ // ignore it
}
return false;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 86b061512f1f..5584d983e7cd 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -73,6 +73,7 @@ import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.CallForwardingReason;
import android.telephony.Annotation.CallState;
import android.telephony.Annotation.CallWaitingStatus;
+import android.telephony.Annotation.CarrierPrivilegeStatus;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
@@ -11115,8 +11116,6 @@ public class TelephonyManager {
retVal = telephony.isDataEnabled(subId);
} catch (RemoteException e) {
Log.e(TAG, "Error isDataConnectionAllowed", e);
- } catch (NullPointerException e) {
- return false;
}
return retVal;
}
@@ -12351,7 +12350,7 @@ public class TelephonyManager {
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public int getCarrierPrivilegeStatus(int uid) {
+ public @CarrierPrivilegeStatus int getCarrierPrivilegeStatus(int uid) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
@@ -12870,7 +12869,6 @@ public class TelephonyManager {
* The IccLock state or password was changed successfully.
* @hide
*/
- @SystemApi
public static final int CHANGE_ICC_LOCK_SUCCESS = Integer.MAX_VALUE;
/**
@@ -12883,7 +12881,6 @@ public class TelephonyManager {
*
* @hide
*/
- @SystemApi
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isIccLockEnabled() {
@@ -12920,7 +12917,6 @@ public class TelephonyManager {
*
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int setIccLockEnabled(boolean enabled, @NonNull String password) {
checkNotNull(password, "setIccLockEnabled password can't be null.");
@@ -12954,7 +12950,6 @@ public class TelephonyManager {
*
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int changeIccLockPassword(@NonNull String oldPassword, @NonNull String newPassword) {
checkNotNull(oldPassword, "changeIccLockPassword oldPassword can't be null.");
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index ccd28f433e40..44b0968eaa90 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -249,13 +249,69 @@ public class EuiccManager {
* Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
* code.
*
- * <p>This code is an implementation detail of the embedded subscription manager and is only
- * intended for logging or debugging purposes.
+ * <p>The value of this key is an integer and contains two portions. The first byte is
+ * OperationCode and the reaming three bytes is the ErrorCode.
+ *
+ * OperationCode is the first byte of the result code and is a categorization which defines what
+ * type of operation took place when an error occurred. e.g {@link #OPERATION_DOWNLOAD} means
+ * the error is related to download.Since the OperationCode only uses at most one byte, the
+ * maximum allowed quantity is 255(0xFF).
+ *
+ * ErrorCode is the remaining three bytes of the result code, and it denotes what happened.
+ * e.g a combination of {@link #OPERATION_DOWNLOAD} and {@link #ERROR_TIME_OUT} will suggest the
+ * download operation has timed out. The only exception here is
+ * {@link #OPERATION_SMDX_SUBJECT_REASON_CODE}, where instead of ErrorCode, SubjectCode[5.2.6.1
+ * from GSMA (SGP.22 v2.2) and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) are encoded. @see
+ * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} and
+ * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE}
+ *
+ * In the case where ErrorCode contains a value of 0, it means it's an unknown error. E.g Intent
+ * only contains {@link #OPERATION_DOWNLOAD} and ErrorCode is 0 implies this is an unknown
+ * Download error.
+ *
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE}
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE}
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE}
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE}
*/
public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE =
"android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
/**
+ * Key for an extra set on {@link PendingIntent} result callbacks providing a
+ * OperationCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE},
+ * value will be an int.
+ */
+ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE =
+ "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_OPERATION_CODE";
+
+ /**
+ * Key for an extra set on {@link PendingIntent} result callbacks providing a
+ * ErrorCode of {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE},
+ * value will be an int.
+ */
+ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE =
+ "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_ERROR_CODE";
+
+ /**
+ * Key for an extra set on {@link PendingIntent} result callbacks providing a
+ * SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2) decoded from
+ * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+ * The value of this extra will be a String.
+ */
+ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE =
+ "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE";
+
+ /**
+ * Key for an extra set on {@link PendingIntent} result callbacks providing a
+ * ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) decoded from
+ * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}.
+ * The value of this extra will be a String.
+ */
+ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE =
+ "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE";
+
+ /**
* Key for an extra set on {@code #getDownloadableSubscriptionMetadata} PendingIntent result
* callbacks providing the downloadable subscription metadata.
*/
@@ -494,6 +550,259 @@ public class EuiccManager {
@SystemApi
public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
+ /**
+ * List of OperationCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}'s
+ * value, an integer. @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"OPERATION_"}, value = {
+ OPERATION_SYSTEM,
+ OPERATION_SIM_SLOT,
+ OPERATION_EUICC_CARD,
+ OPERATION_SWITCH,
+ OPERATION_DOWNLOAD,
+ OPERATION_METADATA,
+ OPERATION_EUICC_GSMA,
+ OPERATION_APDU,
+ OPERATION_SMDX,
+ OPERATION_HTTP,
+ OPERATION_SMDX_SUBJECT_REASON_CODE,
+ })
+ public @interface OperationCode {
+ }
+
+ /**
+ * Internal system error.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_SYSTEM = 1;
+
+ /**
+ * SIM slot error. Failed to switch slot, failed to access the physical slot etc.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_SIM_SLOT = 2;
+
+ /**
+ * eUICC card error.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_EUICC_CARD = 3;
+
+ /**
+ * Generic switching profile error
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_SWITCH = 4;
+
+ /**
+ * Download profile error.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_DOWNLOAD = 5;
+
+ /**
+ * Subscription's metadata error
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_METADATA = 6;
+
+ /**
+ * eUICC returned an error defined in GSMA (SGP.22 v2.2) while running one of the ES10x
+ * functions.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_EUICC_GSMA = 7;
+
+ /**
+ * The exception of failing to execute an APDU command. It can be caused by an error
+ * happening on opening the basic or logical channel, or the response of the APDU command is
+ * not success (0x9000).
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_APDU = 8;
+
+ /**
+ * SMDX(SMDP/SMDS) error
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_SMDX = 9;
+
+ /**
+ * SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] error from GSMA (SGP.22 v2.2)
+ * When {@link #OPERATION_SMDX_SUBJECT_REASON_CODE} is used as the
+ * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}, the remaining three bytes of the integer
+ * result from {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} will be used to stored the
+ * SubjectCode and ReasonCode from the GSMA spec and NOT ErrorCode.
+ *
+ * The encoding will follow the format of:
+ * 1. The first byte of the result will be 255(0xFF).
+ * 2. Remaining three bytes(24 bits) will be split into six sections, 4 bits in each section.
+ * 3. A SubjectCode/ReasonCode will take 12 bits each.
+ * 4. The maximum number can be represented per section is 15, as that is the maximum number
+ * allowed to be stored into 4 bits
+ * 5. Maximum supported nested category from GSMA is three layers. E.g 8.11.1.2 is not
+ * supported.
+ *
+ * E.g given SubjectCode(8.11.1) and ReasonCode(5.1)
+ *
+ * Base10: 0 10 8 11 1 0 5 1
+ * Base2: 0000 1010 1000 1011 0001 0000 0101 0001
+ * Base16: 0 A 8 B 1 0 5 1
+ *
+ * Thus the integer stored in {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} is
+ * 0xA8B1051(176885841)
+ *
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10;
+
+ /**
+ * HTTP error
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int OPERATION_HTTP = 11;
+
+ /**
+ * List of ErrorCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ERROR_"}, value = {
+ ERROR_CARRIER_LOCKED,
+ ERROR_INVALID_ACTIVATION_CODE,
+ ERROR_INVALID_CONFIRMATION_CODE,
+ ERROR_INCOMPATIBLE_CARRIER,
+ ERROR_EUICC_INSUFFICIENT_MEMORY,
+ ERROR_TIME_OUT,
+ ERROR_EUICC_MISSING,
+ ERROR_UNSUPPORTED_VERSION,
+ ERROR_SIM_MISSING,
+ ERROR_INSTALL_PROFILE,
+ ERROR_DISALLOWED_BY_PPR,
+ ERROR_ADDRESS_MISSING,
+ ERROR_CERTIFICATE_ERROR,
+ ERROR_NO_PROFILES_AVAILABLE,
+ ERROR_CONNECTION_ERROR,
+ ERROR_INVALID_RESPONSE,
+ ERROR_OPERATION_BUSY,
+ })
+ public @interface ErrorCode{}
+
+ /**
+ * Operation such as downloading/switching to another profile failed due to device being
+ * carrier locked.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_CARRIER_LOCKED = 10000;
+
+ /**
+ * The activation code(SGP.22 v2.2 section[4.1]) is invalid.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_INVALID_ACTIVATION_CODE = 10001;
+
+ /**
+ * The confirmation code(SGP.22 v2.2 section[4.7]) is invalid.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002;
+
+ /**
+ * The profile's carrier is incompatible with the LPA.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_INCOMPATIBLE_CARRIER = 10003;
+
+ /**
+ * There is no more space available on the eUICC for new profiles.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004;
+
+ /**
+ * Timed out while waiting for an operation to complete. i.e restart, disable,
+ * switch reset etc.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_TIME_OUT = 10005;
+
+ /**
+ * eUICC is missing or defective on the device.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_EUICC_MISSING = 10006;
+
+ /**
+ * The eUICC card(hardware) version is incompatible with the software
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_UNSUPPORTED_VERSION = 10007;
+
+ /**
+ * No SIM card is available in the device.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_SIM_MISSING = 10008;
+
+ /**
+ * Failure to load the profile onto the eUICC card. e.g
+ * 1. iccid of the profile already exists on the eUICC.
+ * 2. GSMA(.22 v2.2) Profile Install Result - installFailedDueToDataMismatch
+ * 3. operation was interrupted
+ * 4. SIMalliance error in PEStatus(SGP.22 v2.2 section 2.5.6.1)
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_INSTALL_PROFILE = 10009;
+
+ /**
+ * Failed to load profile onto eUICC due to Profile Poicly Rules.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_DISALLOWED_BY_PPR = 10010;
+
+
+ /**
+ * Address is missing e.g SMDS/SMDP address is missing.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_ADDRESS_MISSING = 10011;
+
+ /**
+ * Certificate needed for authentication is not valid or missing. E.g SMDP/SMDS authentication
+ * failed.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_CERTIFICATE_ERROR = 10012;
+
+
+ /**
+ * No profiles available.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_NO_PROFILES_AVAILABLE = 10013;
+
+ /**
+ * Failure to create a connection.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_CONNECTION_ERROR = 10014;
+
+ /**
+ * Response format is invalid. e.g SMDP/SMDS response contains invalid json, header or/and ASN1.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_INVALID_RESPONSE = 10015;
+
+ /**
+ * The operation is currently busy, try again later.
+ * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+ */
+ public static final int ERROR_OPERATION_BUSY = 10016;
+
private final Context mContext;
private int mCardId;
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index a7d553b60abf..9e466aea9776 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -182,6 +182,25 @@ public final class ImsCallProfile implements Parcelable {
* {@link ImsCallProfile#DIALSTRING_USSD}
*/
public static final String EXTRA_DIALSTRING = "dialstring";
+ /**
+ * This extra holds call fail cause because of which redial is attempted.
+ * see {@link android.telephony.ims.ImsReasonInfo} {@code CODE_*}
+ * for possible values this extra can hold.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RETRY_CALL_FAIL_REASON =
+ "android.telephony.ims.extra.RETRY_CALL_FAIL_REASON";
+ /**
+ * This extra holds call network type on which lower layers
+ * may try attempting redial.
+ * See {@link TelephonyManager} {@code NETWORK_TYPE_*}
+ * for possible values this extra can hold.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RETRY_CALL_FAIL_NETWORKTYPE =
+ "android.telephony.ims.extra.RETRY_CALL_FAIL_NETWORKTYPE";
/**
* Values for EXTRA_OIR / EXTRA_CNAP
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 53ad70a07563..6fdc13e6a31b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -492,6 +492,7 @@ public interface RILConstants {
int RIL_REQUEST_ENABLE_UICC_APPLICATIONS = 208;
int RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT = 209;
int RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS = 210;
+ int RIL_REQUEST_GET_BARRING_INFO = 211;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -557,4 +558,5 @@ public interface RILConstants {
int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
int RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED = 1103;
int RIL_UNSOL_REGISTRATION_FAILED = 1104;
+ int RIL_UNSOL_BARRING_INFO_CHANGED = 1105;
}
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 95b8f6700c76..8b182b7f8780 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -71,6 +71,7 @@ public class AppLaunch extends InstrumentationTestCase {
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
private static final String KEY_APPS = "apps";
+ private static final String KEY_IORAP_TRIAL_LAUNCH = "iorap_trial_launch";
private static final String KEY_TRIAL_LAUNCH = "trial_launch";
private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
private static final String KEY_LAUNCH_ORDER = "launch_order";
@@ -98,6 +99,9 @@ public class AppLaunch extends InstrumentationTestCase {
private static final int BEFORE_KILL_APP_SLEEP_TIMEOUT = 1000; // 1s before killing
private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 3000; // 3s between launching apps
private static final int PROFILE_SAVE_SLEEP_TIMEOUT = 1000; // Allow 1s for the profile to save
+ private static final int IORAP_TRACE_DURATION_TIMEOUT = 7000; // Allow 7s for trace to complete.
+ private static final int IORAP_TRIAL_LAUNCH_ITERATIONS = 3; // min 3 launches to merge traces.
+ private static final int IORAP_COMPILE_CMD_TIMEOUT = 600; // in seconds: 10 minutes
private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
private static final String LAUNCH_FILE = "applaunch.txt";
private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
@@ -106,6 +110,9 @@ public class AppLaunch extends InstrumentationTestCase {
private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
+ private static final String IORAP_TRIAL_LAUNCH = "IORAP_TRIAL_LAUNCH";
+ private static final String IORAP_TRIAL_LAUNCH_FIRST = "IORAP_TRIAL_LAUNCH_FIRST";
+ private static final String IORAP_TRIAL_LAUNCH_LAST = "IORAP_TRIAL_LAUNCH_LAST";
private static final String DELIMITER = ",";
private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
private static final String APP_LAUNCH_CMD = "am start -W -n";
@@ -119,6 +126,10 @@ public class AppLaunch extends InstrumentationTestCase {
private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
+ private static final String IORAP_COMPILE_CMD = "cmd jobscheduler run -f android 283673059";
+ private static final String IORAP_MAINTENANCE_CMD =
+ "iorap.cmd.maintenance --purge-package %s /data/misc/iorapd/sqlite.db";
+ private static final String IORAP_DUMPSYS_CMD = "dumpsys iorapd";
private static final String SPEED_PROFILE_FILTER = "speed-profile";
private static final String VERIFY_FILTER = "verify";
private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
@@ -138,6 +149,7 @@ public class AppLaunch extends InstrumentationTestCase {
private Bundle mResult = new Bundle();
private Set<String> mRequiredAccounts;
private boolean mTrialLaunch = false;
+ private boolean mIorapTrialLaunch = false;
private BufferedWriter mBufferedWriter = null;
private boolean mSimplePerfAppOnly = false;
private String[] mCompilerFilters = null;
@@ -145,6 +157,13 @@ public class AppLaunch extends InstrumentationTestCase {
private boolean mCycleCleanUp = false;
private boolean mTraceAll = false;
private boolean mIterationCycle = false;
+
+ enum IorapStatus {
+ UNDEFINED,
+ ENABLED,
+ DISABLED
+ }
+ private IorapStatus mIorapStatus = IorapStatus.UNDEFINED;
private long mCycleTime = 0;
private StringBuilder mCycleTimes = new StringBuilder();
@@ -243,7 +262,10 @@ public class AppLaunch extends InstrumentationTestCase {
setLaunchOrder();
for (LaunchOrder launch : mLaunchOrderList) {
- dropCache();
+ toggleIorapStatus(launch.getIorapEnabled());
+ dropCache(/*override*/false);
+
+ Log.v(TAG, "Launch reason: " + launch.getLaunchReason());
// App launch times for trial launch will not be used for final
// launch time calculations.
@@ -289,6 +311,43 @@ public class AppLaunch extends InstrumentationTestCase {
compileApp(launch.getCompilerFilter(), appPkgName));
}
}
+ else if (launch.getLaunchReason().startsWith(IORAP_TRIAL_LAUNCH)) {
+ mIterationCycle = false;
+
+ // In the "applaunch.txt" file, iorap-trial launches is referenced using
+ // "IORAP_TRIAL_LAUNCH" or "IORAP_TRIAL_LAUNCH_LAST"
+ Intent startIntent = mNameToIntent.get(launch.getApp());
+ if (startIntent == null) {
+ Log.w(TAG, "App does not exist: " + launch.getApp());
+ mResult.putString(mNameToResultKey.get(launch.getApp()),
+ "App does not exist");
+ continue;
+ }
+ String appPkgName = startIntent.getComponent().getPackageName();
+
+ if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_FIRST)) {
+ // delete any iorap-traces associated with this package.
+ purgeIorapPackage(appPkgName);
+ }
+ dropCache(/*override*/true); // iorap-trial runs must have drop cache.
+
+ AppLaunchResult launchResult =
+ startApp(launch.getApp(), launch.getLaunchReason());
+ if (launchResult.mLaunchTime < 0) {
+ addLaunchResult(launch, new AppLaunchResult());
+ // simply pass the app if launch isn't successful
+ // error should have already been logged by startApp
+ continue;
+ }
+ // wait for slightly more than 5s (iorapd.perfetto.trace_duration_ms) for the trace buffers to complete.
+ sleep(IORAP_TRACE_DURATION_TIMEOUT);
+
+ if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_LAST)) {
+ // run the iorap job scheduler and wait for iorap to compile fully.
+ assertTrue(String.format("Not able to iorap-compile the app : %s", appPkgName),
+ compileAppForIorap(appPkgName));
+ }
+ }
// App launch times used for final calculation
else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
@@ -438,6 +497,74 @@ public class AppLaunch extends InstrumentationTestCase {
}
/**
+ * Compile the app package using compilerFilter and return true or false
+ * based on status of the compilation command.
+ */
+ private boolean compileAppForIorap(String appPkgName) throws IOException {
+ getInstrumentation().getUiAutomation().
+ executeShellCommand(IORAP_COMPILE_CMD);
+
+ for (int i = 0; i < IORAP_COMPILE_CMD_TIMEOUT; ++i) {
+ IorapCompilationStatus status = waitForIorapCompiled(appPkgName);
+ if (status == IorapCompilationStatus.COMPLETE) {
+ return true;
+ } else if (status == IorapCompilationStatus.INSUFFICIENT_TRACES) {
+ return false;
+ } // else INCOMPLETE. keep asking iorapd if it's done yet.
+ sleep(1000);
+ }
+
+ return false;
+ }
+
+ enum IorapCompilationStatus {
+ INCOMPLETE,
+ COMPLETE,
+ INSUFFICIENT_TRACES,
+ }
+ private IorapCompilationStatus waitForIorapCompiled(String appPkgName) throws IOException {
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand(IORAP_DUMPSYS_CMD);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ String prevLine = "";
+ while ((line = bufferedReader.readLine()) != null) {
+ // Match the indented VersionedComponentName string.
+ // " com.google.android.deskclock/com.android.deskclock.DeskClock@62000712"
+ // Note: spaces are meaningful here.
+ if (prevLine.contains(" " + appPkgName) && prevLine.contains("@")) {
+ // pre-requisite:
+ // Compiled Status: Raw traces pending compilation (3)
+ if (line.contains("Compiled Status: Usable compiled trace")) {
+ return IorapCompilationStatus.COMPLETE;
+ } else if (line.contains("Compiled Status: ") &&
+ line.contains("more traces for compilation")) {
+ // Compiled Status: Need 1 more traces for compilation
+ // No amount of waiting will help here because there were
+ // insufficient traces made.
+ return IorapCompilationStatus.INSUFFICIENT_TRACES;
+ }
+ }
+
+ prevLine = line;
+ }
+ return IorapCompilationStatus.INCOMPLETE;
+ }
+ }
+
+ private String makeReasonForIorapTrialLaunch(int launchCount) {
+ String reason = IORAP_TRIAL_LAUNCH;
+ if (launchCount == 0) {
+ reason = IORAP_TRIAL_LAUNCH_FIRST;
+ }
+ if (launchCount == IORAP_TRIAL_LAUNCH_ITERATIONS - 1) {
+ reason = IORAP_TRIAL_LAUNCH_LAST;
+ }
+ return reason;
+ }
+
+ /**
* If launch order is "cyclic" then apps will be launched one after the
* other for each iteration count.
* If launch order is "sequential" then each app will be launched for given number
@@ -448,20 +575,31 @@ public class AppLaunch extends InstrumentationTestCase {
for (String compilerFilter : mCompilerFilters) {
if (mTrialLaunch) {
for (String app : mNameToResultKey.keySet()) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+ mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
+ }
+ }
+ if (mIorapTrialLaunch) {
+ for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
+ for (String app : mNameToResultKey.keySet()) {
+ String reason = makeReasonForIorapTrialLaunch(launchCount);
+ mLaunchOrderList.add(
+ new LaunchOrder(app, compilerFilter,
+ reason,
+ /*iorapEnabled*/true));
+ }
}
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
+ String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
+ String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -470,16 +608,25 @@ public class AppLaunch extends InstrumentationTestCase {
for (String compilerFilter : mCompilerFilters) {
for (String app : mNameToResultKey.keySet()) {
if (mTrialLaunch) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+ mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
+ }
+ if (mIorapTrialLaunch) {
+ for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
+ String reason = makeReasonForIorapTrialLaunch(launchCount);
+ mLaunchOrderList.add(
+ new LaunchOrder(app, compilerFilter,
+ reason,
+ /*iorapEnabled*/true));
+ }
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
+ String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
+ String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -489,14 +636,92 @@ public class AppLaunch extends InstrumentationTestCase {
}
}
- private void dropCache() {
- if (mDropCache) {
+ private void dropCache(boolean override) {
+ if (mDropCache || override) {
assertNotNull("Issue in dropping the cache",
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT));
}
}
+ // [[ $(adb shell whoami) == "root" ]]
+ private boolean checkIfRoot() throws IOException {
+ String total = "";
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand("whoami");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ total = total + line;
+ }
+ }
+ return total.contains("root");
+ }
+
+ // Delete all db rows and files associated with a package in iorapd.
+ // Effectively deletes any raw or compiled trace files, unoptimizing the package in iorap.
+ private void purgeIorapPackage(String packageName) {
+ try {
+ if (!checkIfRoot()) {
+ throw new AssertionError("must be root to toggle iorapd; try adb root?");
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ sleep(100); // give iorapd enough time to stop.
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format(IORAP_MAINTENANCE_CMD, packageName));
+ Log.v(TAG, "Executed: " + String.format(IORAP_MAINTENANCE_CMD, packageName));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+ sleep(2000); // give iorapd enough time to start up.
+ }
+
+ /**
+ * Toggle iorapd-based readahead and trace-collection.
+ * If iorapd is already enabled and enable is true, does nothing.
+ * If iorapd is already disabled and enable is false, does nothing.
+ */
+ private void toggleIorapStatus(boolean enable) {
+ boolean currentlyEnabled = false;
+ Log.v(TAG, "toggleIorapStatus " + Boolean.toString(enable));
+
+ // Do nothing if we are already enabled or disabled.
+ if (mIorapStatus == IorapStatus.ENABLED && enable) {
+ return;
+ } else if (mIorapStatus == IorapStatus.DISABLED && !enable) {
+ return;
+ }
+
+ try {
+ if (!checkIfRoot()) {
+ throw new AssertionError("must be root to toggle iorapd; try adb root?");
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format("setprop iorapd.perfetto.enable %b", enable));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format("setprop iorapd.readahead.enable %b", enable));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+ sleep(2000); // give enough time for iorapd to start back up.
+
+ if (enable) {
+ mIorapStatus = IorapStatus.ENABLED;
+ } else {
+ mIorapStatus = IorapStatus.DISABLED;
+ }
+ }
+
private void parseArgs(Bundle args) {
mNameToResultKey = new LinkedHashMap<String, String>();
mNameToLaunchTime = new HashMap<>();
@@ -560,6 +785,8 @@ public class AppLaunch extends InstrumentationTestCase {
mCycleCleanUp = Boolean.parseBoolean(args.getString(KEY_CYCLE_CLEAN));
mTraceAll = Boolean.parseBoolean(args.getString(KEY_TRACE_ALL));
mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
+ mIorapTrialLaunch = mIorapTrialLaunch ||
+ Boolean.parseBoolean(args.getString(KEY_IORAP_TRIAL_LAUNCH));
if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
@@ -738,11 +965,13 @@ public class AppLaunch extends InstrumentationTestCase {
private String mApp;
private String mCompilerFilter;
private String mLaunchReason;
+ private boolean mIorapEnabled;
- LaunchOrder(String app, String compilerFilter, String launchReason){
+ LaunchOrder(String app, String compilerFilter, String launchReason, boolean iorapEnabled) {
mApp = app;
mCompilerFilter = compilerFilter;
mLaunchReason = launchReason;
+ mIorapEnabled = iorapEnabled;
}
public String getApp() {
@@ -764,6 +993,14 @@ public class AppLaunch extends InstrumentationTestCase {
public void setLaunchReason(String launchReason) {
mLaunchReason = launchReason;
}
+
+ public void setIorapEnabled(boolean iorapEnabled) {
+ mIorapEnabled = iorapEnabled;
+ }
+
+ public boolean getIorapEnabled() {
+ return mIorapEnabled;
+ }
}
private class AppLaunchResult {
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index efea91ab91f0..9fe1883010b7 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -48,9 +48,11 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.core.os.BuildCompat;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -64,6 +66,13 @@ public class NetworkCapabilitiesTest {
private static final String TEST_SSID = "TEST_SSID";
private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID";
+ private boolean isAtLeastR() {
+ // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R.
+ // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after
+ // releasing Android R.
+ return BuildCompat.isAtLeastR() || Build.VERSION.SDK_INT > Build.VERSION_CODES.Q;
+ }
+
@Test
public void testMaybeMarkCapabilitiesRestricted() {
// verify EIMS is restricted
@@ -269,25 +278,36 @@ public class NetworkCapabilitiesTest {
.setUids(uids)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
- netCap.setOwnerUid(123);
+ if (isAtLeastR()) {
+ netCap.setOwnerUid(123);
+ }
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
- assertParcelSane(netCap, 15);
+ testParcelSane(netCap);
}
@Test
public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() {
final NetworkCapabilities netCap = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
- .setRequestorUid(9304)
- .setRequestorPackageName("com.android.test")
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
+ if (isAtLeastR()) {
+ netCap.setRequestorPackageName("com.android.test");
+ netCap.setRequestorUid(9304);
+ }
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
- assertParcelSane(netCap, 15);
+ testParcelSane(netCap);
}
+ private void testParcelSane(NetworkCapabilities cap) {
+ if (isAtLeastR()) {
+ assertParcelSane(cap, 15);
+ } else {
+ assertParcelSane(cap, 11);
+ }
+ }
@Test
public void testOemPaid() {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index d8f32e1c45e1..51eaf66c0f25 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -25,7 +25,6 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
import static android.net.ConnectivityManager.NETID_UNSET;
@@ -175,6 +174,7 @@ import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.Uri;
@@ -307,6 +307,8 @@ public class ConnectivityServiceTest {
private static final long TIMESTAMP = 1234L;
+ private static final int NET_ID = 110;
+
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
@@ -1016,6 +1018,7 @@ public class ConnectivityServiceTest {
private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private VpnInfo mVpnInfo;
+ private Network[] mUnderlyingNetworks;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
@@ -1105,9 +1108,21 @@ public class ConnectivityServiceTest {
return super.getVpnInfo();
}
- private void setVpnInfo(VpnInfo vpnInfo) {
+ private synchronized void setVpnInfo(VpnInfo vpnInfo) {
mVpnInfo = vpnInfo;
}
+
+ @Override
+ public synchronized Network[] getUnderlyingNetworks() {
+ if (mUnderlyingNetworks != null) return mUnderlyingNetworks;
+
+ return super.getUnderlyingNetworks();
+ }
+
+ /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */
+ private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) {
+ mUnderlyingNetworks = underlyingNetworks;
+ }
}
private void mockVpn(int uid) {
@@ -1374,7 +1389,6 @@ public class ConnectivityServiceTest {
@NonNull final Predicate<Intent> filter) {
final ConditionVariable cv = new ConditionVariable();
final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
- intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
final BroadcastReceiver receiver = new BroadcastReceiver() {
private int remaining = count;
public void onReceive(Context context, Intent intent) {
@@ -1422,56 +1436,28 @@ public class ConnectivityServiceTest {
final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
- // Send request and check that the legacy broadcast for SUPL is sent correctly.
+ // File request, withdraw it and make sure no broadcast is sent
+ final ConditionVariable cv2 = registerConnectivityBroadcast(1);
final TestNetworkCallback callback = new TestNetworkCallback();
- final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
mCm.requestNetwork(legacyRequest, callback);
callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- waitFor(cv2);
-
- // File another request, withdraw it and make sure no broadcast is sent
- final ConditionVariable cv3 = registerConnectivityBroadcast(1);
- final TestNetworkCallback callback2 = new TestNetworkCallback();
- mCm.requestNetwork(legacyRequest, callback2);
- callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- mCm.unregisterNetworkCallback(callback2);
- assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
+ mCm.unregisterNetworkCallback(callback);
+ assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent
// As the broadcast did not fire, the receiver was not unregistered. Do this now.
mServiceContext.clearRegisteredReceivers();
- // Withdraw the request and check that the broadcast for disconnection is sent.
- final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
- !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
- && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
- mCm.unregisterNetworkCallback(callback);
- waitFor(cv4);
-
- // Re-file the request and expect the connected broadcast again
- final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
- final TestNetworkCallback callback3 = new TestNetworkCallback();
- mCm.requestNetwork(legacyRequest, callback3);
- callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- waitFor(cv5);
-
- // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
- // for mobile. Use a small hack to check that both have been sent, but the order is
- // not contractual.
+ // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to
+ // check that has been sent.
final AtomicBoolean vanillaAction = new AtomicBoolean(false);
- final AtomicBoolean suplAction = new AtomicBoolean(false);
- final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
+ final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> {
if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
vanillaAction.set(true);
- } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
- suplAction.set(true);
}
return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
});
mCellNetworkAgent.disconnect();
- waitFor(cv6);
+ waitFor(cv3);
assertTrue(vanillaAction.get());
- assertTrue(suplAction.get());
}
@Test
@@ -2464,8 +2450,8 @@ public class ConnectivityServiceTest {
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter);
// Register the factory and don't be surprised when the default request arrives.
- testFactory.register();
testFactory.expectAddRequestsWithScores(0);
+ testFactory.register();
testFactory.waitForNetworkRequests(1);
testFactory.setScoreFilter(42);
@@ -6064,6 +6050,7 @@ public class ConnectivityServiceTest {
verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
TYPE_MOBILE);
}
+ reset(mMockNetd);
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up.
@@ -6115,7 +6102,6 @@ public class ConnectivityServiceTest {
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
-
// Clat iface comes up. Expect stacked link to be added.
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
@@ -6701,17 +6687,45 @@ public class ConnectivityServiceTest {
}
}
+ private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
+ assertEquals(route.getDestination().toString(), parcel.destination);
+ assertEquals(route.getInterface(), parcel.ifName);
+ assertEquals(route.getMtu(), parcel.mtu);
+
+ switch (route.getType()) {
+ case RouteInfo.RTN_UNICAST:
+ if (route.hasGateway()) {
+ assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
+ } else {
+ assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
+ }
+ break;
+ case RouteInfo.RTN_UNREACHABLE:
+ assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
+ break;
+ case RouteInfo.RTN_THROW:
+ assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
+ break;
+ default:
+ assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
+ break;
+ }
+ }
+
private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
- InOrder inOrder = inOrder(mNetworkManagementService);
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
for (int i = 0; i < routes.length; i++) {
- inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i]));
+ assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
}
}
private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
- InOrder inOrder = inOrder(mNetworkManagementService);
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
+ captor.capture());
for (int i = 0; i < routes.length; i++) {
- inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i]));
+ assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
}
}
@@ -6822,9 +6836,10 @@ public class ConnectivityServiceTest {
@Test
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
+ final Network network = new Network(NET_ID);
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), 0,
+ null, null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6837,11 +6852,19 @@ public class ConnectivityServiceTest {
info.ownerUid = Process.myUid();
info.vpnIface = "interface";
mMockVpn.setVpnInfo(info);
+ mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
+
+ mMockVpn.overrideUnderlyingNetworks(null);
+ assertFalse(
+ "VPN shouldn't receive callback on non-underlying network",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid(), Process.myUid(), naiWithoutUid,
+ mContext.getOpPackageName()));
}
@Test
@@ -6973,4 +6996,60 @@ public class ConnectivityServiceTest {
verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(noConnectivity));
}
+
+ @Test
+ public void testRouteAddDeleteUpdate() throws Exception {
+ final NetworkRequest request = new NetworkRequest.Builder().build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, networkCallback);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ reset(mMockNetd);
+ mCellNetworkAgent.connect(false);
+ networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ final int netId = mCellNetworkAgent.getNetwork().netId;
+
+ final String iface = "rmnet_data0";
+ final InetAddress gateway = InetAddress.getByName("fe80::5678");
+ RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
+ RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
+ RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
+ RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
+ RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
+ 1280 /* mtu */);
+
+ // Send LinkProperties and check that we ask netd to add routes.
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(iface);
+ lp.addRoute(direct);
+ lp.addRoute(rio1);
+ lp.addRoute(defaultRoute);
+ mCellNetworkAgent.sendLinkProperties(lp);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
+
+ assertRoutesAdded(netId, direct, rio1, defaultRoute);
+ reset(mMockNetd);
+
+ // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
+ assertTrue(lp.getRoutes().contains(defaultRoute));
+ lp.removeRoute(rio1);
+ lp.addRoute(rio2);
+ lp.addRoute(defaultWithMtu);
+ // Ensure adding the same route with a different MTU replaces the previous route.
+ assertFalse(lp.getRoutes().contains(defaultRoute));
+ assertTrue(lp.getRoutes().contains(defaultWithMtu));
+
+ mCellNetworkAgent.sendLinkProperties(lp);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ x -> x.getRoutes().contains(rio2));
+
+ assertRoutesRemoved(netId, rio1);
+ assertRoutesAdded(netId, rio2);
+
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
+ assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
+
+
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 6be50c6560a0..b346c923914e 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -1034,10 +1034,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// Create some initial traffic and report to the service.
incrementCurrentTime(HOUR_IN_MILLIS);
final NetworkStats expectedStats = new NetworkStats(0L, 1)
- .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
128L, 2L, 128L, 2L, 1L))
- .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
64L, 1L, 64L, 1L, 1L));
cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats);