Merge "Split the DownloadStateCallback class into two"
diff --git a/Android.bp b/Android.bp
index 6003e85..80df8c5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -904,6 +904,7 @@
],
resourcesdir: "docs/html/reference/images",
resourcesoutdir: "reference/android/images",
+ installable: false,
}
droiddoc {
@@ -915,14 +916,11 @@
"core/java/overview.html",
":current-support-api",
],
- args: framework_docs_args +
- "-referenceonly -api $(genDir)/PACKAGING/public_api.txt -privateApi $(genDir)/PACKAGING/private.txt "+
- "-privateDexApi $(genDir)/PACKAGING/private-dex.txt -removedApi $(genDir)/PACKAGING/removed.txt -nodocs",
- out: [
- "PACKAGING/public_api.txt",
- "PACKAGING/private.txt",
- "PACKAGING/private-dex.txt",
- ]
+ api_filename: "public_api.txt",
+ private_api_filename: "private.txt",
+ private_dex_api_filename: "private-dex.txt",
+ removed_api_filename: "removed.txt",
+ args: framework_docs_args + " -referenceonly -nodocs",
}
droiddoc {
@@ -934,16 +932,13 @@
"core/java/overview.html",
":current-support-api",
],
- args: framework_docs_args +
- "-referenceonly -showAnnotation android.annotation.SystemApi " +
- "-api $(genDir)/PACKAGING/system-api.txt -privateApi $(genDir)/PACKAGING/system-private.txt " +
- "-privateDexApi $(genDir)/PACKAGING/system-private-dex.txt -removedApi $(genDir)/PACKAGING/system-removed.txt " +
- "-exactApi $(genDir)/PACKAGING/system-exact.txt -nodocs",
- out: [
- "PACKAGING/system-api.txt",
- "PACKAGING/system-private.txt",
- "PACKAGING/system-private-dex.txt",
- ]
+ api_tag_name: "SYSTEM",
+ api_filename: "system-api.txt",
+ private_api_filename: "system-private.txt",
+ private_dex_api_filename: "system-private-dex.txt",
+ removed_api_filename: "system-removed.txt",
+ exact_api_filename: "system-exact.txt",
+ args: framework_docs_args + " -referenceonly -showAnnotation android.annotation.SystemApi -nodocs",
}
droiddoc {
@@ -955,12 +950,9 @@
"core/java/overview.html",
":current-support-api",
],
- args: framework_docs_args +
- "-referenceonly -showAnnotation android.annotation.TestApi " +
- "-api $(genDir)/PACKAGING/test-api.txt " +
- "-removedApi $(genDir)/PACKAGING/test-removed.txt " +
- "-exactApi $(genDir)/PACKAGING/test-exact.txt -nodocs",
- out: [
- "PACKAGING/test-api.txt",
- ]
+ api_tag_name: "TEST",
+ api_filename: "test-api.txt",
+ removed_api_filename: "test-removed.txt",
+ exact_api_filename: "test-exact.txt",
+ args: framework_docs_args + " -referenceonly -showAnnotation android.annotation.TestApi -nodocs",
}
diff --git a/Android.mk b/Android.mk
index 147d2cf..b5b4627 100644
--- a/Android.mk
+++ b/Android.mk
@@ -260,116 +260,9 @@
-federate SupportLib https://developer.android.com \
-federationapi SupportLib prebuilts/sdk/current/support-api.txt
-# ==== the api stubs and current.xml ===========================
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := api-stubs
-
-LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_stubs_current_intermediates/src
-
-LOCAL_DROIDDOC_OPTIONS:=\
- $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
- -referenceonly \
- -api $(INTERNAL_PLATFORM_API_FILE) \
- -privateApi $(INTERNAL_PLATFORM_PRIVATE_API_FILE) \
- -privateDexApi $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
- -removedApi $(INTERNAL_PLATFORM_REMOVED_API_FILE) \
- -nodocs
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_DROIDDOC)
-
-$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_API_FILE) \
- $(INTERNAL_PLATFORM_PRIVATE_API_FILE) \
- $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
-
-# ==== the system api stubs ===================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := system-api-stubs
-
-LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_system_stubs_current_intermediates/src
-
-LOCAL_DROIDDOC_OPTIONS:=\
- $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
- -referenceonly \
- -showAnnotation android.annotation.SystemApi \
- -api $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \
- -privateApi $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_API_FILE) \
- -privateDexApi $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE) \
- -removedApi $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \
- -exactApi $(INTERNAL_PLATFORM_SYSTEM_EXACT_API_FILE) \
- -nodocs
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_DROIDDOC)
-
-$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \
- $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_API_FILE) \
- $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
-
-# ==== the test api stubs ===================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := test-api-stubs
-
-LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_test_stubs_current_intermediates/src
-
-LOCAL_DROIDDOC_OPTIONS:=\
- $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
- -referenceonly \
- -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_test_stubs_current_intermediates/src \
- -showAnnotation android.annotation.TestApi \
- -api $(INTERNAL_PLATFORM_TEST_API_FILE) \
- -removedApi $(INTERNAL_PLATFORM_TEST_REMOVED_API_FILE) \
- -exactApi $(INTERNAL_PLATFORM_TEST_EXACT_API_FILE) \
- -nodocs
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_DROIDDOC)
-
-$(INTERNAL_PLATFORM_TEST_API_FILE): $(full_target)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
# ==== check javadoc comments but don't generate docs ========
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 50a5974..75b7491 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,4 +6,5 @@
packages/PrintSpooler/
services/print/
services/usb/
+ telephony/
diff --git a/api/current.txt b/api/current.txt
index 055968d..eec5b24 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7922,7 +7922,7 @@
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public int getConnectionState(android.bluetooth.BluetoothDevice);
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceCallback);
+ method public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, java.util.concurrent.Executor, android.bluetooth.BluetoothHidDevice.Callback);
method public boolean replyReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
method public boolean reportError(android.bluetooth.BluetoothDevice, byte);
method public boolean sendReport(android.bluetooth.BluetoothDevice, int, byte[]);
@@ -7952,49 +7952,8 @@
field public static final byte SUBCLASS2_UNCATEGORIZED = 0; // 0x0
}
- public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable {
- ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int);
- method public int describeContents();
- method public int[] toArray();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR;
- field public static final int MAX = -1; // 0xffffffff
- field public static final int SERVICE_BEST_EFFORT = 1; // 0x1
- field public static final int SERVICE_GUARANTEED = 2; // 0x2
- field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0
- field public final int delayVariation;
- field public final int latency;
- field public final int peakBandwidth;
- field public final int serviceType;
- field public final int tokenBucketSize;
- field public final int tokenRate;
- }
-
- public static class BluetoothHidDeviceAppQosSettings.Builder {
- ctor public BluetoothHidDeviceAppQosSettings.Builder();
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings build();
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder delayVariation(int);
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder latency(int);
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder peakBandwidth(int);
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder serviceType(int);
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder tokenBucketSize(int);
- method public android.bluetooth.BluetoothHidDeviceAppQosSettings.Builder tokenRate(int);
- }
-
- public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable {
- ctor public BluetoothHidDeviceAppSdpSettings(java.lang.String, java.lang.String, java.lang.String, byte, byte[]);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
- field public final java.lang.String description;
- field public final byte[] descriptors;
- field public final java.lang.String name;
- field public final java.lang.String provider;
- field public final byte subclass;
- }
-
- public abstract class BluetoothHidDeviceCallback {
- ctor public BluetoothHidDeviceCallback();
+ public static abstract class BluetoothHidDevice.Callback {
+ ctor public BluetoothHidDevice.Callback();
method public void onAppStatusChanged(android.bluetooth.BluetoothDevice, boolean);
method public void onConnectionStateChanged(android.bluetooth.BluetoothDevice, int);
method public void onGetReport(android.bluetooth.BluetoothDevice, byte, byte, int);
@@ -8004,6 +7963,35 @@
method public void onVirtualCableUnplug(android.bluetooth.BluetoothDevice);
}
+ public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable {
+ ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int);
+ method public int describeContents();
+ method public int getDelayVariation();
+ method public int getLatency();
+ method public int getPeakBandwidth();
+ method public int getServiceType();
+ method public int getTokenBucketSize();
+ method public int getTokenRate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR;
+ field public static final int MAX = -1; // 0xffffffff
+ field public static final int SERVICE_BEST_EFFORT = 1; // 0x1
+ field public static final int SERVICE_GUARANTEED = 2; // 0x2
+ field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0
+ }
+
+ public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable {
+ ctor public BluetoothHidDeviceAppSdpSettings(java.lang.String, java.lang.String, java.lang.String, byte, byte[]);
+ method public int describeContents();
+ method public java.lang.String getDescription();
+ method public byte[] getDescriptors();
+ method public java.lang.String getName();
+ method public java.lang.String getProvider();
+ method public byte getSubclass();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
+ }
+
public final class BluetoothManager {
method public android.bluetooth.BluetoothAdapter getAdapter();
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
@@ -27546,7 +27534,7 @@
field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
- field public static final java.lang.String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+ field public static final java.lang.String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
field public static final int FLAG_READER_NFC_A = 1; // 0x1
field public static final int FLAG_READER_NFC_B = 2; // 0x2
@@ -39194,7 +39182,7 @@
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
- field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+ field public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4; // 0x4
field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
}
@@ -40609,17 +40597,17 @@
ctor public ServiceState(android.os.Parcel);
method protected void copyFrom(android.telephony.ServiceState);
method public int describeContents();
+ method public int getCdmaNetworkId();
+ method public int getCdmaSystemId();
method public int[] getCellBandwidths();
method public int getChannelNumber();
method public int getDuplexMode();
method public boolean getIsManualSelection();
- method public int getNetworkId();
method public java.lang.String getOperatorAlphaLong();
method public java.lang.String getOperatorAlphaShort();
method public java.lang.String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
- method public int getSystemId();
method public void setIsManualSelection(boolean);
method public void setOperatorName(java.lang.String, java.lang.String, java.lang.String);
method public void setRoaming(boolean);
@@ -41079,21 +41067,21 @@
public class ApnSetting implements android.os.Parcelable {
method public int describeContents();
method public java.lang.String getApnName();
+ method public int getApnTypeBitmask();
method public int getAuthType();
method public java.lang.String getEntryName();
method public int getId();
- method public int getMmsPort();
- method public java.net.InetAddress getMmsProxy();
- method public java.net.URL getMmsc();
- method public java.lang.String getMvnoType();
+ method public java.net.InetAddress getMmsProxyAddress();
+ method public int getMmsProxyPort();
+ method public android.net.Uri getMmsc();
+ method public int getMvnoType();
method public int getNetworkTypeBitmask();
method public java.lang.String getOperatorNumeric();
method public java.lang.String getPassword();
- method public int getPort();
- method public java.lang.String getProtocol();
- method public java.net.InetAddress getProxy();
- method public java.lang.String getRoamingProtocol();
- method public java.util.List<java.lang.String> getTypes();
+ method public int getProtocol();
+ method public java.net.InetAddress getProxyAddress();
+ method public int getProxyPort();
+ method public int getRoamingProtocol();
method public java.lang.String getUser();
method public boolean isEnabled();
method public void writeToParcel(android.os.Parcel, int);
@@ -41102,46 +41090,45 @@
field public static final int AUTH_TYPE_PAP = 1; // 0x1
field public static final int AUTH_TYPE_PAP_OR_CHAP = 3; // 0x3
field public static final android.os.Parcelable.Creator<android.telephony.data.ApnSetting> CREATOR;
- field public static final java.lang.String MVNO_TYPE_GID = "gid";
- field public static final java.lang.String MVNO_TYPE_ICCID = "iccid";
- field public static final java.lang.String MVNO_TYPE_IMSI = "imsi";
- field public static final java.lang.String MVNO_TYPE_SPN = "spn";
- field public static final java.lang.String PROTOCOL_IP = "IP";
- field public static final java.lang.String PROTOCOL_IPV4V6 = "IPV4V6";
- field public static final java.lang.String PROTOCOL_IPV6 = "IPV6";
- field public static final java.lang.String PROTOCOL_PPP = "PPP";
- field public static final java.lang.String TYPE_ALL = "*";
- field public static final java.lang.String TYPE_CBS = "cbs";
- field public static final java.lang.String TYPE_DEFAULT = "default";
- field public static final java.lang.String TYPE_DUN = "dun";
- field public static final java.lang.String TYPE_EMERGENCY = "emergency";
- field public static final java.lang.String TYPE_FOTA = "fota";
- field public static final java.lang.String TYPE_HIPRI = "hipri";
- field public static final java.lang.String TYPE_IA = "ia";
- field public static final java.lang.String TYPE_IMS = "ims";
- field public static final java.lang.String TYPE_MMS = "mms";
- field public static final java.lang.String TYPE_SUPL = "supl";
+ field public static final int MVNO_TYPE_GID = 2; // 0x2
+ field public static final int MVNO_TYPE_ICCID = 3; // 0x3
+ field public static final int MVNO_TYPE_IMSI = 1; // 0x1
+ field public static final int MVNO_TYPE_SPN = 0; // 0x0
+ field public static final int PROTOCOL_IP = 0; // 0x0
+ field public static final int PROTOCOL_IPV4V6 = 2; // 0x2
+ field public static final int PROTOCOL_IPV6 = 1; // 0x1
+ field public static final int PROTOCOL_PPP = 3; // 0x3
+ field public static final int TYPE_CBS = 128; // 0x80
+ field public static final int TYPE_DEFAULT = 17; // 0x11
+ field public static final int TYPE_DUN = 8; // 0x8
+ field public static final int TYPE_EMERGENCY = 512; // 0x200
+ field public static final int TYPE_FOTA = 32; // 0x20
+ field public static final int TYPE_HIPRI = 16; // 0x10
+ field public static final int TYPE_IA = 256; // 0x100
+ field public static final int TYPE_IMS = 64; // 0x40
+ field public static final int TYPE_MMS = 2; // 0x2
+ field public static final int TYPE_SUPL = 4; // 0x4
}
public static class ApnSetting.Builder {
ctor public ApnSetting.Builder();
method public android.telephony.data.ApnSetting build();
method public android.telephony.data.ApnSetting.Builder setApnName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
method public android.telephony.data.ApnSetting.Builder setAuthType(int);
method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
method public android.telephony.data.ApnSetting.Builder setEntryName(java.lang.String);
- method public android.telephony.data.ApnSetting.Builder setMmsPort(int);
- method public android.telephony.data.ApnSetting.Builder setMmsProxy(java.net.InetAddress);
- method public android.telephony.data.ApnSetting.Builder setMmsc(java.net.URL);
- method public android.telephony.data.ApnSetting.Builder setMvnoType(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri);
+ method public android.telephony.data.ApnSetting.Builder setMvnoType(int);
method public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int);
method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(java.lang.String);
method public android.telephony.data.ApnSetting.Builder setPassword(java.lang.String);
- method public android.telephony.data.ApnSetting.Builder setPort(int);
- method public android.telephony.data.ApnSetting.Builder setProtocol(java.lang.String);
- method public android.telephony.data.ApnSetting.Builder setProxy(java.net.InetAddress);
- method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(java.lang.String);
- method public android.telephony.data.ApnSetting.Builder setTypes(java.util.List<java.lang.String>);
+ method public android.telephony.data.ApnSetting.Builder setProtocol(int);
+ method public android.telephony.data.ApnSetting.Builder setProxyAddress(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setProxyPort(int);
+ method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int);
method public android.telephony.data.ApnSetting.Builder setUser(java.lang.String);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index dac2979..31a6d4d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2611,8 +2611,10 @@
}
public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
+ method public void addAddress(android.net.LinkAddress) throws java.io.IOException;
method public void close();
method public java.lang.String getInterfaceName();
+ method public void removeAddress(android.net.LinkAddress) throws java.io.IOException;
}
public final class IpSecTransform implements java.lang.AutoCloseable {
@@ -4357,12 +4359,13 @@
}
public class UiccSlotInfo implements android.os.Parcelable {
- ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
+ ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean);
method public int describeContents();
method public java.lang.String getCardId();
method public int getCardStateInfo();
method public boolean getIsActive();
method public boolean getIsEuicc();
+ method public boolean getIsExtendedApduSupported();
method public int getLogicalSlotIdx();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -4530,6 +4533,7 @@
public class EuiccManager {
method public void continueOperation(android.content.Intent, android.os.Bundle);
+ method public void eraseSubscriptions(android.app.PendingIntent);
method public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
method public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
method public int getOtaStatus();
diff --git a/api/test-current.txt b/api/test-current.txt
index ad5bd13..ce6810f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -436,6 +436,10 @@
field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
}
+ public class ServiceState implements android.os.Parcelable {
+ method public void setCdmaSystemAndNetworkId(int, int);
+ }
+
}
package android.telephony.mbms {
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 1671337..12083b6 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <android-base/macros.h>
#include <binder/IPCThreadState.h>
#include <hwbinder/IPCThreadState.h>
#include <utils/Log.h>
@@ -137,27 +138,12 @@
}
static void maybeCreateDalvikCache() {
-#if defined(__aarch64__)
- static const char kInstructionSet[] = "arm64";
-#elif defined(__x86_64__)
- static const char kInstructionSet[] = "x86_64";
-#elif defined(__arm__)
- static const char kInstructionSet[] = "arm";
-#elif defined(__i386__)
- static const char kInstructionSet[] = "x86";
-#elif defined (__mips__) && !defined(__LP64__)
- static const char kInstructionSet[] = "mips";
-#elif defined (__mips__) && defined(__LP64__)
- static const char kInstructionSet[] = "mips64";
-#else
-#error "Unknown instruction set"
-#endif
const char* androidRoot = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset");
char dalvikCacheDir[PATH_MAX];
const int numChars = snprintf(dalvikCacheDir, PATH_MAX,
- "%s/dalvik-cache/%s", androidRoot, kInstructionSet);
+ "%s/dalvik-cache/" ABI_STRING, androidRoot);
LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
"Error constructing dalvik cache : %s", strerror(errno));
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 565eaeb..bae2a26 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -612,7 +612,7 @@
streamingOutput);
profiling = true;
} catch (RuntimeException e) {
- Slog.w(TAG, "Profiling failed on path " + profileFile);
+ Slog.w(TAG, "Profiling failed on path " + profileFile, e);
try {
profileFd.close();
profileFd = null;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index be4e207..6aabe18 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -676,6 +676,10 @@
if (!getLeAccess()) {
return null;
}
+ if (!isMultipleAdvertisementSupported()) {
+ Log.e(TAG, "Bluetooth LE advertising not supported");
+ return null;
+ }
synchronized (mLock) {
if (sBluetoothLeAdvertiser == null) {
sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index 2fab305..a3d6968 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -27,8 +27,8 @@
import android.util.Log;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Provides the public APIs to control the Bluetooth HID Device profile.
@@ -37,7 +37,6 @@
* Use {@link BluetoothAdapter#getProfileProxy} to get the BluetoothHidDevice proxy object.
*/
public final class BluetoothHidDevice implements BluetoothProfile {
-
private static final String TAG = BluetoothHidDevice.class.getSimpleName();
/**
@@ -62,106 +61,327 @@
"android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
/**
- * Constants representing device subclass.
+ * Constant representing unspecified HID device subclass.
*
* @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
*/
public static final byte SUBCLASS1_NONE = (byte) 0x00;
+ /**
+ * Constant representing keyboard subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
+ /**
+ * Constant representing mouse subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
+ /**
+ * Constant representing combo keyboard and mouse subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
+ /**
+ * Constant representing uncategorized HID device subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
+ /**
+ * Constant representing joystick subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
+ /**
+ * Constant representing gamepad subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
+ /**
+ * Constant representing remote control subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
+ /**
+ * Constant representing sensing device subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
+ /**
+ * Constant representing digitizer tablet subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
+ /**
+ * Constant representing card reader subclass.
+ *
+ * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)
+ */
public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
/**
- * Constants representing report types.
+ * Constant representing HID Input Report type.
*
- * @see BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)
- * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
- * @see BluetoothHidDeviceCallback#onInterruptData(BluetoothDevice, byte, byte[])
+ * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
*/
public static final byte REPORT_TYPE_INPUT = (byte) 1;
+ /**
+ * Constant representing HID Output Report type.
+ *
+ * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
+ */
public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
+ /**
+ * Constant representing HID Feature Report type.
+ *
+ * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
+ */
public static final byte REPORT_TYPE_FEATURE = (byte) 3;
/**
- * Constants representing error response for Set Report.
+ * Constant representing success response for Set Report.
*
- * @see BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
*/
public static final byte ERROR_RSP_SUCCESS = (byte) 0;
+ /**
+ * Constant representing error response for Set Report due to "not ready".
+ *
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ */
public static final byte ERROR_RSP_NOT_READY = (byte) 1;
+ /**
+ * Constant representing error response for Set Report due to "invalid report ID".
+ *
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ */
public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
+ /**
+ * Constant representing error response for Set Report due to "unsupported request".
+ *
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ */
public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
+ /**
+ * Constant representing error response for Set Report due to "invalid parameter".
+ *
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ */
public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
+ /**
+ * Constant representing error response for Set Report with unknown reason.
+ *
+ * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
+ */
public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
/**
- * Constants representing protocol mode used set by host. Default is always {@link
+ * Constant representing boot protocol mode used set by host. Default is always {@link
* #PROTOCOL_REPORT_MODE} unless notified otherwise.
*
- * @see BluetoothHidDeviceCallback#onSetProtocol(BluetoothDevice, byte)
+ * @see Callback#onSetProtocol(BluetoothDevice, byte)
*/
public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
+ /**
+ * Constant representing report protocol mode used set by host. Default is always {@link
+ * #PROTOCOL_REPORT_MODE} unless notified otherwise.
+ *
+ * @see Callback#onSetProtocol(BluetoothDevice, byte)
+ */
public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
+ /**
+ * The template class that applications use to call callback functions on events from the HID
+ * host. Callback functions are wrapped in this class and registered to the Android system
+ * during app registration.
+ */
+ public abstract static class Callback {
+
+ private static final String TAG = "BluetoothHidDevCallback";
+
+ /**
+ * Callback called when application registration state changes. Usually it's called due to
+ * either {@link BluetoothHidDevice#registerApp (String, String, String, byte, byte[],
+ * Executor, Callback)} or {@link BluetoothHidDevice#unregisterApp()} , but can be also
+ * unsolicited in case e.g. Bluetooth was turned off in which case application is
+ * unregistered automatically.
+ *
+ * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently
+ * has Virtual Cable established with device. Only valid when application is registered,
+ * can be <code>null</code>.
+ * @param registered <code>true</code> if application is registered, <code>false</code>
+ * otherwise.
+ */
+ public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
+ Log.d(
+ TAG,
+ "onAppStatusChanged: pluggedDevice="
+ + pluggedDevice
+ + " registered="
+ + registered);
+ }
+
+ /**
+ * Callback called when connection state with remote host was changed. Application can
+ * assume than Virtual Cable is established when called with {@link
+ * BluetoothProfile#STATE_CONNECTED} <code>state</code>.
+ *
+ * @param device {@link BluetoothDevice} object representing host device which connection
+ * state was changed.
+ * @param state Connection state as defined in {@link BluetoothProfile}.
+ */
+ public void onConnectionStateChanged(BluetoothDevice device, int state) {
+ Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
+ }
+
+ /**
+ * Callback called when GET_REPORT is received from remote host. Should be replied by
+ * application using {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte,
+ * byte[])}.
+ *
+ * @param type Requested Report Type.
+ * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor.
+ * @param bufferSize Requested buffer size, application shall respond with at least given
+ * number of bytes.
+ */
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ Log.d(
+ TAG,
+ "onGetReport: device="
+ + device
+ + " type="
+ + type
+ + " id="
+ + id
+ + " bufferSize="
+ + bufferSize);
+ }
+
+ /**
+ * Callback called when SET_REPORT is received from remote host. In case received data are
+ * invalid, application shall respond with {@link
+ * BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
+ *
+ * @param type Report Type.
+ * @param id Report Id.
+ * @param data Report data.
+ */
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
+ }
+
+ /**
+ * Callback called when SET_PROTOCOL is received from remote host. Application shall use
+ * this information to send only reports valid for given protocol mode. By default, {@link
+ * BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
+ *
+ * @param protocol Protocol Mode.
+ */
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
+ }
+
+ /**
+ * Callback called when report data is received over interrupt channel. Report Type is
+ * assumed to be {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
+ *
+ * @param reportId Report Id.
+ * @param data Report data.
+ */
+ public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
+ Log.d(TAG, "onInterruptData: device=" + device + " reportId=" + reportId);
+ }
+
+ /**
+ * Callback called when Virtual Cable is removed. After this callback is received connection
+ * will be disconnected automatically.
+ */
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ Log.d(TAG, "onVirtualCableUnplug: device=" + device);
+ }
+ }
+
private Context mContext;
-
private ServiceListener mServiceListener;
-
private volatile IBluetoothHidDevice mService;
-
private BluetoothAdapter mAdapter;
- private static class BluetoothHidDeviceCallbackWrapper
- extends IBluetoothHidDeviceCallback.Stub {
+ private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
- private BluetoothHidDeviceCallback mCallback;
+ private final Executor mExecutor;
+ private final Callback mCallback;
- public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) {
+ CallbackWrapper(Executor executor, Callback callback) {
+ mExecutor = executor;
mCallback = callback;
}
@Override
public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
- mCallback.onAppStatusChanged(pluggedDevice, registered);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onAppStatusChanged(pluggedDevice, registered));
}
@Override
public void onConnectionStateChanged(BluetoothDevice device, int state) {
- mCallback.onConnectionStateChanged(device, state);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onConnectionStateChanged(device, state));
}
@Override
public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
- mCallback.onGetReport(device, type, id, bufferSize);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onGetReport(device, type, id, bufferSize));
}
@Override
public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- mCallback.onSetReport(device, type, id, data);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onSetReport(device, type, id, data));
}
@Override
public void onSetProtocol(BluetoothDevice device, byte protocol) {
- mCallback.onSetProtocol(device, protocol);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onSetProtocol(device, protocol));
}
@Override
public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
- mCallback.onInterruptData(device, reportId, data);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onInterruptData(device, reportId, data));
}
@Override
public void onVirtualCableUnplug(BluetoothDevice device) {
- mCallback.onVirtualCableUnplug(device);
+ clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onVirtualCableUnplug(device));
}
}
@@ -213,8 +433,6 @@
};
BluetoothHidDevice(Context context, ServiceListener listener) {
- Log.v(TAG, "BluetoothHidDevice");
-
mContext = context;
mServiceListener = listener;
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -245,7 +463,6 @@
}
void doUnbind() {
- Log.d(TAG, "Unbinding HidDevService");
if (mService != null) {
mService = null;
try {
@@ -257,8 +474,6 @@
}
void close() {
- Log.v(TAG, "close()");
-
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
@@ -277,8 +492,6 @@
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getConnectedDevices() {
- Log.v(TAG, "getConnectedDevices()");
-
final IBluetoothHidDevice service = mService;
if (service != null) {
try {
@@ -290,14 +503,12 @@
Log.w(TAG, "Proxy not attached to service");
}
- return new ArrayList<BluetoothDevice>();
+ return new ArrayList<>();
}
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
-
final IBluetoothHidDevice service = mService;
if (service != null) {
try {
@@ -309,14 +520,12 @@
Log.w(TAG, "Proxy not attached to service");
}
- return new ArrayList<BluetoothDevice>();
+ return new ArrayList<>();
}
/** {@inheritDoc} */
@Override
public int getConnectionState(BluetoothDevice device) {
- Log.v(TAG, "getConnectionState(): device=" + device);
-
final IBluetoothHidDevice service = mService;
if (service != null) {
try {
@@ -336,9 +545,9 @@
* when application is registered. Only one application can be registered at one time. When an
* application is registered, the HID Host service will be disabled until it is unregistered.
* When no longer used, application should be unregistered using {@link #unregisterApp()}. The
- * registration status should be tracked by the application by handling callback from
- * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related to
- * the return value of this method.
+ * app will be automatically unregistered if it is not foreground. The registration status
+ * should be tracked by the application by handling callback from Callback#onAppStatusChanged.
+ * The app registration status is not related to the return value of this method.
*
* @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record. The HID
* Device SDP record is required.
@@ -348,27 +557,36 @@
* @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings. The
* Outgoing QoS Settings is not required. Use null or default
* BluetoothHidDeviceAppQosSettings.Builder for default values.
- * @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be
- * sent. The BluetoothHidDeviceCallback object is required.
+ * @param executor {@link Executor} object on which callback will be executed. The Executor
+ * object is required.
+ * @param callback {@link Callback} object to which callback messages will be sent. The Callback
+ * object is required.
* @return true if the command is successfully sent; otherwise false.
*/
- public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
- BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
- BluetoothHidDeviceCallback callback) {
- Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
- + " callback=" + callback);
-
+ public boolean registerApp(
+ BluetoothHidDeviceAppSdpSettings sdp,
+ BluetoothHidDeviceAppQosSettings inQos,
+ BluetoothHidDeviceAppQosSettings outQos,
+ Executor executor,
+ Callback callback) {
boolean result = false;
- if (sdp == null || callback == null) {
- return false;
+ if (sdp == null) {
+ throw new IllegalArgumentException("sdp parameter cannot be null");
+ }
+
+ if (executor == null) {
+ throw new IllegalArgumentException("executor parameter cannot be null");
+ }
+
+ if (callback == null) {
+ throw new IllegalArgumentException("callback parameter cannot be null");
}
final IBluetoothHidDevice service = mService;
if (service != null) {
try {
- BluetoothHidDeviceCallbackWrapper cbw =
- new BluetoothHidDeviceCallbackWrapper(callback);
+ CallbackWrapper cbw = new CallbackWrapper(executor, callback);
result = service.registerApp(sdp, inQos, outQos, cbw);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
@@ -384,16 +602,13 @@
* Unregisters application. Active connection will be disconnected and no new connections will
* be allowed until registered again using {@link #registerApp
* (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)} The registration status should
- * be tracked by the application by handling callback from
- * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related to
- * the return value of this method.
+ * BluetoothHidDeviceAppQosSettings, Executor, Callback)}. The registration status should be
+ * tracked by the application by handling callback from Callback#onAppStatusChanged. The app
+ * registration status is not related to the return value of this method.
*
* @return true if the command is successfully sent; otherwise false.
*/
public boolean unregisterApp() {
- Log.v(TAG, "unregisterApp()");
-
boolean result = false;
final IBluetoothHidDevice service = mService;
@@ -437,7 +652,7 @@
/**
* Sends report to remote host as reply for GET_REPORT request from {@link
- * BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
+ * Callback#onGetReport(BluetoothDevice, byte, byte, int)}.
*
* @param type Report Type, as in request.
* @param id Report Id, as in request.
@@ -445,8 +660,6 @@
* @return true if the command is successfully sent; otherwise false.
*/
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
-
boolean result = false;
final IBluetoothHidDevice service = mService;
@@ -465,14 +678,12 @@
/**
* Sends error handshake message as reply for invalid SET_REPORT request from {@link
- * BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
+ * Callback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
* @return true if the command is successfully sent; otherwise false.
*/
public boolean reportError(BluetoothDevice device, byte error) {
- Log.v(TAG, "reportError(): device=" + device + " error=" + error);
-
boolean result = false;
final IBluetoothHidDevice service = mService;
@@ -496,8 +707,6 @@
* {@hide}
*/
public boolean unplug(BluetoothDevice device) {
- Log.v(TAG, "unplug(): device=" + device);
-
boolean result = false;
final IBluetoothHidDevice service = mService;
@@ -517,15 +726,12 @@
/**
* Initiates connection to host which is currently paired with this device. If the application
* is not registered, #connect(BluetoothDevice) will fail. The connection state should be
- * tracked by the application by handling callback from
- * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related to
- * the return value of this method.
+ * tracked by the application by handling callback from Callback#onConnectionStateChanged. The
+ * connection state is not related to the return value of this method.
*
* @return true if the command is successfully sent; otherwise false.
*/
public boolean connect(BluetoothDevice device) {
- Log.v(TAG, "connect(): device=" + device);
-
boolean result = false;
final IBluetoothHidDevice service = mService;
@@ -544,14 +750,12 @@
/**
* Disconnects from currently connected host. The connection state should be tracked by the
- * application by handling callback from BluetoothHidDeviceCallback#onConnectionStateChanged.
- * The connection state is not related to the return value of this method.
+ * application by handling callback from Callback#onConnectionStateChanged. The connection state
+ * is not related to the return value of this method.
*
* @return true if the command is successfully sent; otherwise false.
*/
public boolean disconnect(BluetoothDevice device) {
- Log.v(TAG, "disconnect(): device=" + device);
-
boolean result = false;
final IBluetoothHidDevice service = mService;
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
index c05df2d..a485b89 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
@@ -29,12 +29,12 @@
*/
public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
- public final int serviceType;
- public final int tokenRate;
- public final int tokenBucketSize;
- public final int peakBandwidth;
- public final int latency;
- public final int delayVariation;
+ private final int mServiceType;
+ private final int mTokenRate;
+ private final int mTokenBucketSize;
+ private final int mPeakBandwidth;
+ private final int mLatency;
+ private final int mDelayVariation;
public static final int SERVICE_NO_TRAFFIC = 0x00;
public static final int SERVICE_BEST_EFFORT = 0x01;
@@ -44,38 +44,53 @@
/**
* Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel. The QoS
- * Settings is optional. Recommended to use BluetoothHidDeviceAppQosSettings.Builder.
- * Please refer to Bluetooth HID Specfication v1.1.1 Section 5.2 and Appendix D for parameters.
+ * Settings is optional. Please refer to Bluetooth HID Specfication v1.1.1 Section 5.2 and
+ * Appendix D for parameters.
*
- * @param serviceType L2CAP service type
- * @param tokenRate L2CAP token rate
- * @param tokenBucketSize L2CAP token bucket size
- * @param peakBandwidth L2CAP peak bandwidth
- * @param latency L2CAP latency
- * @param delayVariation L2CAP delay variation
+ * @param serviceType L2CAP service type, default = SERVICE_BEST_EFFORT
+ * @param tokenRate L2CAP token rate, default = 0
+ * @param tokenBucketSize L2CAP token bucket size, default = 0
+ * @param peakBandwidth L2CAP peak bandwidth, default = 0
+ * @param latency L2CAP latency, default = MAX
+ * @param delayVariation L2CAP delay variation, default = MAX
*/
- public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize,
- int peakBandwidth, int latency, int delayVariation) {
- this.serviceType = serviceType;
- this.tokenRate = tokenRate;
- this.tokenBucketSize = tokenBucketSize;
- this.peakBandwidth = peakBandwidth;
- this.latency = latency;
- this.delayVariation = delayVariation;
+ public BluetoothHidDeviceAppQosSettings(
+ int serviceType,
+ int tokenRate,
+ int tokenBucketSize,
+ int peakBandwidth,
+ int latency,
+ int delayVariation) {
+ mServiceType = serviceType;
+ mTokenRate = tokenRate;
+ mTokenBucketSize = tokenBucketSize;
+ mPeakBandwidth = peakBandwidth;
+ mLatency = latency;
+ mDelayVariation = delayVariation;
}
- @Override
- public boolean equals(Object o) {
- if (o instanceof BluetoothHidDeviceAppQosSettings) {
- BluetoothHidDeviceAppQosSettings qos = (BluetoothHidDeviceAppQosSettings) o;
- return this.serviceType == qos.serviceType
- && this.tokenRate == qos.tokenRate
- && this.tokenBucketSize == qos.tokenBucketSize
- && this.peakBandwidth == qos.peakBandwidth
- && this.latency == qos.latency
- && this.delayVariation == qos.delayVariation;
- }
- return false;
+ public int getServiceType() {
+ return mServiceType;
+ }
+
+ public int getTokenRate() {
+ return mTokenRate;
+ }
+
+ public int getTokenBucketSize() {
+ return mTokenBucketSize;
+ }
+
+ public int getPeakBandwidth() {
+ return mPeakBandwidth;
+ }
+
+ public int getLatency() {
+ return mLatency;
+ }
+
+ public int getDelayVariation() {
+ return mDelayVariation;
}
@Override
@@ -106,104 +121,11 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeInt(serviceType);
- out.writeInt(tokenRate);
- out.writeInt(tokenBucketSize);
- out.writeInt(peakBandwidth);
- out.writeInt(latency);
- out.writeInt(delayVariation);
- }
-
- /** @return an int array representation of this instance */
- public int[] toArray() {
- return new int[] {
- serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation
- };
- }
-
- /** A helper to build the BluetoothHidDeviceAppQosSettings object. */
- public static class Builder {
- // Optional parameters - initialized to default values
- private int mServiceType = SERVICE_BEST_EFFORT;
- private int mTokenRate = 0;
- private int mTokenBucketSize = 0;
- private int mPeakBandwidth = 0;
- private int mLatency = MAX;
- private int mDelayVariation = MAX;
-
- /**
- * Set the service type.
- *
- * @param val service type. Should be one of {SERVICE_NO_TRAFFIC, SERVICE_BEST_EFFORT,
- * SERVICE_GUARANTEED}, with SERVICE_BEST_EFFORT being the default one.
- * @return BluetoothHidDeviceAppQosSettings Builder with specified service type.
- */
- public Builder serviceType(int val) {
- mServiceType = val;
- return this;
- }
- /**
- * Set the token rate.
- *
- * @param val token rate
- * @return BluetoothHidDeviceAppQosSettings Builder with specified token rate.
- */
- public Builder tokenRate(int val) {
- mTokenRate = val;
- return this;
- }
-
- /**
- * Set the bucket size.
- *
- * @param val bucket size
- * @return BluetoothHidDeviceAppQosSettings Builder with specified bucket size.
- */
- public Builder tokenBucketSize(int val) {
- mTokenBucketSize = val;
- return this;
- }
-
- /**
- * Set the peak bandwidth.
- *
- * @param val peak bandwidth
- * @return BluetoothHidDeviceAppQosSettings Builder with specified peak bandwidth.
- */
- public Builder peakBandwidth(int val) {
- mPeakBandwidth = val;
- return this;
- }
- /**
- * Set the latency.
- *
- * @param val latency
- * @return BluetoothHidDeviceAppQosSettings Builder with specified latency.
- */
- public Builder latency(int val) {
- mLatency = val;
- return this;
- }
-
- /**
- * Set the delay variation.
- *
- * @param val delay variation
- * @return BluetoothHidDeviceAppQosSettings Builder with specified delay variation.
- */
- public Builder delayVariation(int val) {
- mDelayVariation = val;
- return this;
- }
-
- /**
- * Build the BluetoothHidDeviceAppQosSettings object.
- *
- * @return BluetoothHidDeviceAppQosSettings object with current settings.
- */
- public BluetoothHidDeviceAppQosSettings build() {
- return new BluetoothHidDeviceAppQosSettings(mServiceType, mTokenRate, mTokenBucketSize,
- mPeakBandwidth, mLatency, mDelayVariation);
- }
+ out.writeInt(mServiceType);
+ out.writeInt(mTokenRate);
+ out.writeInt(mTokenBucketSize);
+ out.writeInt(mPeakBandwidth);
+ out.writeInt(mLatency);
+ out.writeInt(mDelayVariation);
}
}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
index 562c559..237082e 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
@@ -19,7 +19,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
/**
* Represents the Service Discovery Protocol (SDP) settings for a Bluetooth HID Device application.
@@ -31,11 +30,11 @@
*/
public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
- public final String name;
- public final String description;
- public final String provider;
- public final byte subclass;
- public final byte[] descriptors;
+ private final String mName;
+ private final String mDescription;
+ private final String mProvider;
+ private final byte mSubclass;
+ private final byte[] mDescriptors;
/**
* Create a BluetoothHidDeviceAppSdpSettings object for the Bluetooth SDP record.
@@ -52,24 +51,31 @@
*/
public BluetoothHidDeviceAppSdpSettings(
String name, String description, String provider, byte subclass, byte[] descriptors) {
- this.name = name;
- this.description = description;
- this.provider = provider;
- this.subclass = subclass;
- this.descriptors = descriptors.clone();
+ mName = name;
+ mDescription = description;
+ mProvider = provider;
+ mSubclass = subclass;
+ mDescriptors = descriptors.clone();
}
- @Override
- public boolean equals(Object o) {
- if (o instanceof BluetoothHidDeviceAppSdpSettings) {
- BluetoothHidDeviceAppSdpSettings sdp = (BluetoothHidDeviceAppSdpSettings) o;
- return this.name.equals(sdp.name)
- && this.description.equals(sdp.description)
- && this.provider.equals(sdp.provider)
- && this.subclass == sdp.subclass
- && Arrays.equals(this.descriptors, sdp.descriptors);
- }
- return false;
+ public String getName() {
+ return mName;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String getProvider() {
+ return mProvider;
+ }
+
+ public byte getSubclass() {
+ return mSubclass;
+ }
+
+ public byte[] getDescriptors() {
+ return mDescriptors;
}
@Override
@@ -99,10 +105,10 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeString(name);
- out.writeString(description);
- out.writeString(provider);
- out.writeByte(subclass);
- out.writeByteArray(descriptors);
+ out.writeString(mName);
+ out.writeString(mDescription);
+ out.writeString(mProvider);
+ out.writeByte(mSubclass);
+ out.writeByteArray(mDescriptors);
}
}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
deleted file mode 100644
index e71b00f..0000000
--- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2016 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.bluetooth;
-
-import android.util.Log;
-
-/**
- * The template class that applications use to call callback functions on events from the HID host.
- * Callback functions are wrapped in this class and registered to the Android system during app
- * registration.
- *
- * <p>{@see BluetoothHidDevice}
- */
-public abstract class BluetoothHidDeviceCallback {
-
- private static final String TAG = "BluetoothHidDevCallback";
-
- /**
- * Callback called when application registration state changes. Usually it's called due to
- * either {@link BluetoothHidDevice#registerApp (String, String, String, byte, byte[],
- * BluetoothHidDeviceCallback)} or {@link BluetoothHidDevice#unregisterApp()} , but can be also
- * unsolicited in case e.g. Bluetooth was turned off in which case application is unregistered
- * automatically.
- *
- * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently has
- * Virtual Cable established with device. Only valid when application is registered, can be
- * <code>null</code>.
- * @param registered <code>true</code> if application is registered, <code>false</code>
- * otherwise.
- */
- public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
- Log.d(TAG,
- "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered=" + registered);
- }
-
- /**
- * Callback called when connection state with remote host was changed. Application can assume
- * than Virtual Cable is established when called with {@link BluetoothProfile#STATE_CONNECTED}
- * <code>state</code>.
- *
- * @param device {@link BluetoothDevice} object representing host device which connection state
- * was changed.
- * @param state Connection state as defined in {@link BluetoothProfile}.
- */
- public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
- }
-
- /**
- * Callback called when GET_REPORT is received from remote host. Should be replied by
- * application using {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte,
- * byte[])}.
- *
- * @param type Requested Report Type.
- * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor.
- * @param bufferSize Requested buffer size, application shall respond with at least given number
- * of bytes.
- */
- public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
- Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize="
- + bufferSize);
- }
-
- /**
- * Callback called when SET_REPORT is received from remote host. In case received data are
- * invalid, application shall respond with {@link
- * BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
- *
- * @param type Report Type.
- * @param id Report Id.
- * @param data Report data.
- */
- public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
- }
-
- /**
- * Callback called when SET_PROTOCOL is received from remote host. Application shall use this
- * information to send only reports valid for given protocol mode. By default, {@link
- * BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
- *
- * @param protocol Protocol Mode.
- */
- public void onSetProtocol(BluetoothDevice device, byte protocol) {
- Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
- }
-
- /**
- * Callback called when report data is received over interrupt channel. Report Type is assumed
- * to be {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
- *
- * @param reportId Report Id.
- * @param data Report data.
- */
- public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
- Log.d(TAG, "onInterruptData: device=" + device + " reportId=" + reportId);
- }
-
- /**
- * Callback called when Virtual Cable is removed. After this callback is
- * received connection will be disconnected automatically.
- */
- public void onVirtualCableUnplug(BluetoothDevice device) {
- Log.d(TAG, "onVirtualCableUnplug: device=" + device);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 656188f..6aeb94d 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -38,7 +38,7 @@
* This extra represents the current connection state of the profile of the
* Bluetooth device.
*/
- public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
+ String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
/**
* Extra for the connection state intents of the individual profiles.
@@ -46,123 +46,130 @@
* This extra represents the previous connection state of the profile of the
* Bluetooth device.
*/
- public static final String EXTRA_PREVIOUS_STATE =
+ String EXTRA_PREVIOUS_STATE =
"android.bluetooth.profile.extra.PREVIOUS_STATE";
/** The profile is in disconnected state */
- public static final int STATE_DISCONNECTED = 0;
+ int STATE_DISCONNECTED = 0;
/** The profile is in connecting state */
- public static final int STATE_CONNECTING = 1;
+ int STATE_CONNECTING = 1;
/** The profile is in connected state */
- public static final int STATE_CONNECTED = 2;
+ int STATE_CONNECTED = 2;
/** The profile is in disconnecting state */
- public static final int STATE_DISCONNECTING = 3;
+ int STATE_DISCONNECTING = 3;
/**
* Headset and Handsfree profile
*/
- public static final int HEADSET = 1;
+ int HEADSET = 1;
/**
* A2DP profile.
*/
- public static final int A2DP = 2;
+ int A2DP = 2;
/**
* Health Profile
*/
- public static final int HEALTH = 3;
+ int HEALTH = 3;
/**
* HID Host
*
* @hide
*/
- public static final int HID_HOST = 4;
+ int HID_HOST = 4;
/**
* PAN Profile
*
* @hide
*/
- public static final int PAN = 5;
+ int PAN = 5;
/**
* PBAP
*
* @hide
*/
- public static final int PBAP = 6;
+ int PBAP = 6;
/**
* GATT
*/
- public static final int GATT = 7;
+ int GATT = 7;
/**
* GATT_SERVER
*/
- public static final int GATT_SERVER = 8;
+ int GATT_SERVER = 8;
/**
* MAP Profile
*
* @hide
*/
- public static final int MAP = 9;
+ int MAP = 9;
/*
* SAP Profile
* @hide
*/
- public static final int SAP = 10;
+ int SAP = 10;
/**
* A2DP Sink Profile
*
* @hide
*/
- public static final int A2DP_SINK = 11;
+ int A2DP_SINK = 11;
/**
* AVRCP Controller Profile
*
* @hide
*/
- public static final int AVRCP_CONTROLLER = 12;
+ int AVRCP_CONTROLLER = 12;
+
+ /**
+ * AVRCP Target Profile
+ *
+ * @hide
+ */
+ int AVRCP = 13;
/**
* Headset Client - HFP HF Role
*
* @hide
*/
- public static final int HEADSET_CLIENT = 16;
+ int HEADSET_CLIENT = 16;
/**
* PBAP Client
*
* @hide
*/
- public static final int PBAP_CLIENT = 17;
+ int PBAP_CLIENT = 17;
/**
* MAP Messaging Client Equipment (MCE)
*
* @hide
*/
- public static final int MAP_CLIENT = 18;
+ int MAP_CLIENT = 18;
/**
* HID Device
*/
- public static final int HID_DEVICE = 19;
+ int HID_DEVICE = 19;
/**
* Object Push Profile (OPP)
*
* @hide
*/
- public static final int OPP = 20;
+ int OPP = 20;
/**
* Hearing Aid Device
@@ -185,7 +192,7 @@
*
* @hide
**/
- public static final int PRIORITY_AUTO_CONNECT = 1000;
+ int PRIORITY_AUTO_CONNECT = 1000;
/**
* Default priority for devices that allow incoming
@@ -194,7 +201,7 @@
* @hide
**/
@SystemApi
- public static final int PRIORITY_ON = 100;
+ int PRIORITY_ON = 100;
/**
* Default priority for devices that does not allow incoming
@@ -203,14 +210,14 @@
* @hide
**/
@SystemApi
- public static final int PRIORITY_OFF = 0;
+ int PRIORITY_OFF = 0;
/**
* Default priority when not set or when the device is unpaired
*
* @hide
*/
- public static final int PRIORITY_UNDEFINED = -1;
+ int PRIORITY_UNDEFINED = -1;
/**
* Get connected devices for this specific profile.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8ea81a4..ebc88ff 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1046,6 +1046,58 @@
/** @hide */
public String[] splitClassLoaderNames;
+ /**
+ * Represents the default policy. The actual policy used will depend on other properties of
+ * the application, e.g. the target SDK version.
+ * @hide
+ */
+ public static final int HIDDEN_API_ENFORCEMENT_DEFAULT = -1;
+ /**
+ * No API enforcement; the app can access the entire internal private API. Only for use by
+ * system apps.
+ * @hide
+ */
+ public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+ /**
+ * Light grey list enforcement, the strictest option. Enforces the light grey, dark grey and
+ * black lists.
+ * @hide
+ * */
+ public static final int HIDDEN_API_ENFORCEMENT_ALL_LISTS = 1;
+ /**
+ * Dark grey list enforcement. Enforces the dark grey and black lists
+ * @hide
+ */
+ public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
+ /**
+ * Blacklist enforcement only.
+ * @hide
+ */
+ public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+
+ private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+
+ /**
+ * Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
+ * art/runtime/hidden_api.h
+ * @hide
+ */
+ @IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
+ HIDDEN_API_ENFORCEMENT_DEFAULT,
+ HIDDEN_API_ENFORCEMENT_NONE,
+ HIDDEN_API_ENFORCEMENT_ALL_LISTS,
+ HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
+ HIDDEN_API_ENFORCEMENT_BLACK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface HiddenApiEnforcementPolicy {}
+
+ private boolean isValidHiddenApiEnforcementPolicy(int policy) {
+ return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+ }
+
+ private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
+
public void dump(Printer pw, String prefix) {
dump(pw, prefix, DUMP_FLAG_ALL);
}
@@ -1133,6 +1185,7 @@
if (category != CATEGORY_UNDEFINED) {
pw.println(prefix + "category=" + category);
}
+ pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
}
super.dumpBack(pw, prefix);
}
@@ -1228,6 +1281,7 @@
targetSandboxVersion = orig.targetSandboxVersion;
classLoaderName = orig.classLoaderName;
splitClassLoaderNames = orig.splitClassLoaderNames;
+ mHiddenApiPolicy = orig.mHiddenApiPolicy;
}
public String toString() {
@@ -1298,6 +1352,7 @@
dest.writeInt(targetSandboxVersion);
dest.writeString(classLoaderName);
dest.writeStringArray(splitClassLoaderNames);
+ dest.writeInt(mHiddenApiPolicy);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1365,6 +1420,7 @@
targetSandboxVersion = source.readInt();
classLoaderName = source.readString();
splitClassLoaderNames = source.readStringArray();
+ mHiddenApiPolicy = source.readInt();
}
/**
@@ -1456,14 +1512,31 @@
}
}
+ private boolean isPackageWhitelistedForHiddenApis() {
+ return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
+ }
+
/**
* @hide
*/
- public boolean isAllowedToUseHiddenApi() {
- boolean whitelisted =
- SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
- return isSystemApp() || // TODO get rid of this once the whitelist has been populated
- (whitelisted && (isSystemApp() || isUpdatedSystemApp()));
+ public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
+ if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
+ return mHiddenApiPolicy;
+ }
+ if (isPackageWhitelistedForHiddenApis() && (isSystemApp() || isUpdatedSystemApp())) {
+ return HIDDEN_API_ENFORCEMENT_NONE;
+ }
+ return HIDDEN_API_ENFORCEMENT_BLACK;
+ }
+
+ /**
+ * @hide
+ */
+ public void setHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
+ if (!isValidHiddenApiEnforcementPolicy(policy)) {
+ throw new IllegalArgumentException("Invalid API enforcement policy: " + policy);
+ }
+ mHiddenApiPolicy = policy;
}
/**
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f136e27..9d518e9 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1977,13 +1977,6 @@
* services.jar, possibly in com.android.server.net. */
/** {@hide} */
- public static final boolean checkChangePermission(Context context) {
- int uid = Binder.getCallingUid();
- return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, Settings
- .getPackageNameForUid(context, uid), false /* throwException */);
- }
-
- /** {@hide} */
public static final void enforceChangePermission(Context context) {
int uid = Binder.getCallingUid();
Settings.checkAndNoteChangeNetworkStateOperation(context, uid, Settings
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index 3ce0283..3a3ddcc 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -16,6 +16,7 @@
package android.net;
+import android.net.LinkAddress;
import android.net.Network;
import android.net.IpSecConfig;
import android.net.IpSecUdpEncapResponse;
@@ -48,11 +49,11 @@
void addAddressToTunnelInterface(
int tunnelResourceId,
- String localAddr);
+ in LinkAddress localAddr);
void removeAddressFromTunnelInterface(
int tunnelResourceId,
- String localAddr);
+ in LinkAddress localAddr);
void deleteTunnelInterface(int resourceId);
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 90e3ffd..eab7041 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -44,6 +44,16 @@
/** Return data layer snapshot of UID network usage. */
NetworkStats getDataLayerSnapshotForUid(int uid);
+
+ /** Get a detailed snapshot of stats since boot for all UIDs.
+ *
+ * <p>Results will not always be limited to stats on requiredIfaces when specified: stats for
+ * interfaces stacked on the specified interfaces, or for interfaces on which the specified
+ * interfaces are stacked on, will also be included.
+ * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}.
+ */
+ NetworkStats getDetailedUidStats(in String[] requiredIfaces);
+
/** Return set of any ifaces associated with mobile networks since boot. */
String[] getMobileIfaces();
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index c69a4d4..57f0588 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -38,6 +38,13 @@
private static final String TAG = "IpSecAlgorithm";
/**
+ * Null cipher.
+ *
+ * @hide
+ */
+ public static final String CRYPT_NULL = "ecb(cipher_null)";
+
+ /**
* AES-CBC Encryption/Ciphering Algorithm.
*
* <p>Valid lengths for this key are {128, 192, 256}.
@@ -122,7 +129,7 @@
* @param algorithm name of the algorithm.
* @param key key padded to a multiple of 8 bits.
*/
- public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) {
+ public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
this(algorithm, key, key.length * 8);
}
@@ -137,7 +144,8 @@
* @param key key padded to a multiple of 8 bits.
* @param truncLenBits number of bits of output hash to use.
*/
- public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
+ public IpSecAlgorithm(
+ @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
mName = algorithm;
mKey = key.clone();
mTruncLenBits = truncLenBits;
@@ -145,11 +153,13 @@
}
/** Get the algorithm name */
+ @NonNull
public String getName() {
return mName;
}
/** Get the key for this algorithm */
+ @NonNull
public byte[] getKey() {
return mKey.clone();
}
@@ -263,6 +273,7 @@
}
@Override
+ @NonNull
public String toString() {
return new StringBuilder()
.append("{mName=")
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index b609847..4157845 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -58,14 +58,18 @@
private static final String TAG = "IpSecManager";
/**
- * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
- * applies to traffic towards the host.
+ * Used when applying a transform to direct traffic through an {@link IpSecTransform}
+ * towards the host.
+ *
+ * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
*/
public static final int DIRECTION_IN = 0;
/**
- * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
- * applies to traffic from the host.
+ * Used when applying a transform to direct traffic through an {@link IpSecTransform}
+ * away from the host.
+ *
+ * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
*/
public static final int DIRECTION_OUT = 1;
@@ -249,8 +253,9 @@
* @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
* currently allocated for this user
*/
- public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress)
- throws ResourceUnavailableException {
+ @NonNull
+ public SecurityParameterIndex allocateSecurityParameterIndex(
+ @NonNull InetAddress destinationAddress) throws ResourceUnavailableException {
try {
return new SecurityParameterIndex(
mService,
@@ -276,8 +281,9 @@
* @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
* reserved
*/
+ @NonNull
public SecurityParameterIndex allocateSecurityParameterIndex(
- InetAddress destinationAddress, int requestedSpi)
+ @NonNull InetAddress destinationAddress, int requestedSpi)
throws SpiUnavailableException, ResourceUnavailableException {
if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
@@ -301,20 +307,21 @@
*
* <h4>Rekey Procedure</h4>
*
- * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
- * inbound traffic on the old transform will continue to be decrypted until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
- * where both transforms are valid until both endpoints are using the new transform and all
- * in-flight packets have been received.
+ * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+ * will be removed and the new transform will take effect immediately, sending all traffic on
+ * the new transform; however, when applying a transform in the inbound direction, traffic
+ * on the old transform will continue to be decrypted and delivered until that transform is
+ * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+ * procedures where both transforms are valid until both endpoints are using the new transform
+ * and all in-flight packets have been received.
*
* @param socket a stream socket
- * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
+ * @param direction the direction in which the transform should be applied
* @param transform a transport mode {@code IpSecTransform}
* @throws IOException indicating that the transform could not be applied
*/
- public void applyTransportModeTransform(
- Socket socket, int direction, IpSecTransform transform)
- throws IOException {
+ public void applyTransportModeTransform(@NonNull Socket socket,
+ @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
}
@@ -334,19 +341,21 @@
*
* <h4>Rekey Procedure</h4>
*
- * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
- * inbound traffic on the old transform will continue to be decrypted until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
- * where both transforms are valid until both endpoints are using the new transform and all
- * in-flight packets have been received.
+ * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+ * will be removed and the new transform will take effect immediately, sending all traffic on
+ * the new transform; however, when applying a transform in the inbound direction, traffic
+ * on the old transform will continue to be decrypted and delivered until that transform is
+ * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+ * procedures where both transforms are valid until both endpoints are using the new transform
+ * and all in-flight packets have been received.
*
* @param socket a datagram socket
- * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
+ * @param direction the direction in which the transform should be applied
* @param transform a transport mode {@code IpSecTransform}
* @throws IOException indicating that the transform could not be applied
*/
- public void applyTransportModeTransform(
- DatagramSocket socket, int direction, IpSecTransform transform) throws IOException {
+ public void applyTransportModeTransform(@NonNull DatagramSocket socket,
+ @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
}
@@ -366,20 +375,21 @@
*
* <h4>Rekey Procedure</h4>
*
- * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
- * inbound traffic on the old transform will continue to be decrypted until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
- * where both transforms are valid until both endpoints are using the new transform and all
- * in-flight packets have been received.
+ * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+ * will be removed and the new transform will take effect immediately, sending all traffic on
+ * the new transform; however, when applying a transform in the inbound direction, traffic
+ * on the old transform will continue to be decrypted and delivered until that transform is
+ * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+ * procedures where both transforms are valid until both endpoints are using the new transform
+ * and all in-flight packets have been received.
*
* @param socket a socket file descriptor
- * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
+ * @param direction the direction in which the transform should be applied
* @param transform a transport mode {@code IpSecTransform}
* @throws IOException indicating that the transform could not be applied
*/
- public void applyTransportModeTransform(
- FileDescriptor socket, int direction, IpSecTransform transform)
- throws IOException {
+ public void applyTransportModeTransform(@NonNull FileDescriptor socket,
+ @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
// We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
// constructor takes control and closes the user's FD when we exit the method.
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
@@ -390,21 +400,6 @@
}
/**
- * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
- * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
- * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
- * Applications should probably not use this API directly. Instead, they should use {@link
- * VpnService} to provide VPN capability in a more generic fashion.
- *
- * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
- *
- * @param net a {@link Network} that will be tunneled via IP Sec.
- * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
- * @hide
- */
- public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
-
- /**
* Remove an IPsec transform from a stream socket.
*
* <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
@@ -417,8 +412,7 @@
* @param socket a socket that previously had a transform applied to it
* @throws IOException indicating that the transform could not be removed from the socket
*/
- public void removeTransportModeTransforms(Socket socket)
- throws IOException {
+ public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
removeTransportModeTransforms(socket.getFileDescriptor$());
}
@@ -435,8 +429,7 @@
* @param socket a socket that previously had a transform applied to it
* @throws IOException indicating that the transform could not be removed from the socket
*/
- public void removeTransportModeTransforms(DatagramSocket socket)
- throws IOException {
+ public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException {
removeTransportModeTransforms(socket.getFileDescriptor$());
}
@@ -453,8 +446,7 @@
* @param socket a socket that previously had a transform applied to it
* @throws IOException indicating that the transform could not be removed from the socket
*/
- public void removeTransportModeTransforms(FileDescriptor socket)
- throws IOException {
+ public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
mService.removeTransportModeTransforms(pfd);
} catch (RemoteException e) {
@@ -592,6 +584,7 @@
// safely usable for Encapsulation without allowing a user to possibly unbind from/close
// the port, which could potentially impact the traffic of the next user who binds to that
// socket.
+ @NonNull
public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
throws IOException, ResourceUnavailableException {
/*
@@ -621,6 +614,7 @@
// safely usable for Encapsulation without allowing a user to possibly unbind from/close
// the port, which could potentially impact the traffic of the next user who binds to that
// socket.
+ @NonNull
public UdpEncapsulationSocket openUdpEncapsulationSocket()
throws IOException, ResourceUnavailableException {
return new UdpEncapsulationSocket(mService, 0);
@@ -649,6 +643,7 @@
private int mResourceId = INVALID_RESOURCE_ID;
/** Get the underlying SPI held by this object. */
+ @NonNull
public String getInterfaceName() {
return mInterfaceName;
}
@@ -660,10 +655,15 @@
* tunneled traffic.
*
* @param address the local address for traffic inside the tunnel
- * @throws IOException if the address could not be added
* @hide
*/
- public void addAddress(LinkAddress address) throws IOException {
+ @SystemApi
+ public void addAddress(@NonNull LinkAddress address) throws IOException {
+ try {
+ mService.addAddressToTunnelInterface(mResourceId, address);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -672,10 +672,15 @@
* <p>Remove an address which was previously added to the IpSecTunnelInterface
*
* @param address to be removed
- * @throws IOException if the address could not be removed
* @hide
*/
- public void removeAddress(LinkAddress address) throws IOException {
+ @SystemApi
+ public void removeAddress(@NonNull LinkAddress address) throws IOException {
+ try {
+ mService.removeAddressFromTunnelInterface(mResourceId, address);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
private IpSecTunnelInterface(@NonNull IIpSecService service,
@@ -762,6 +767,7 @@
* @hide
*/
@SystemApi
+ @NonNull
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
@NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
@@ -770,7 +776,12 @@
}
/**
- * Apply a transform to the IpSecTunnelInterface
+ * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will
+ * tunnel all traffic for the given direction through the underlying network's interface with
+ * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional
+ * IP header and IPsec Header on all inbound traffic).
+ * <p>Applications should probably not use this API directly.
+ *
*
* @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
* transform.
@@ -783,8 +794,8 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
- public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
- IpSecTransform transform) throws IOException {
+ public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
+ @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
try {
mService.applyTunnelModeTransform(
tunnel.getResourceId(), direction, transform.getResourceId());
@@ -792,6 +803,7 @@
throw e.rethrowFromSystemServer();
}
}
+
/**
* Construct an instance of IpSecManager within an application context.
*
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 60e96f9..cf58647 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -350,6 +350,7 @@
*
* @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
*/
+ @NonNull
public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
Preconditions.checkNotNull(algo);
@@ -364,6 +365,7 @@
*
* @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
*/
+ @NonNull
public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
Preconditions.checkNotNull(algo);
@@ -384,6 +386,7 @@
* @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
* be applied.
*/
+ @NonNull
public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
Preconditions.checkNotNull(algo);
mConfig.setAuthenticatedEncryption(algo);
@@ -403,6 +406,7 @@
* @param remotePort the UDP port number of the remote host that will send and receive
* encapsulated traffic. In the case of IKEv2, this should be port 4500.
*/
+ @NonNull
public IpSecTransform.Builder setIpv4Encapsulation(
@NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
Preconditions.checkNotNull(localSocket);
@@ -436,6 +440,7 @@
* collides with an existing transform
* @throws IOException indicating other errors
*/
+ @NonNull
public IpSecTransform buildTransportModeTransform(
@NonNull InetAddress sourceAddress,
@NonNull IpSecManager.SecurityParameterIndex spi)
@@ -472,6 +477,7 @@
* @hide
*/
@SystemApi
+ @NonNull
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public IpSecTransform buildTunnelModeTransform(
@NonNull InetAddress sourceAddress,
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 96826f8..1ee0ed7d 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -23,6 +23,7 @@
import android.text.TextUtils;
import java.util.Objects;
+import java.util.Set;
/**
* Defines a request for a network, made through {@link NetworkRequest.Builder} and used
@@ -204,6 +205,19 @@
}
/**
+ * Set the watched UIDs for this request. This will be reset and wiped out unless
+ * the calling app holds the CHANGE_NETWORK_STATE permission.
+ *
+ * @param uids The watched UIDs as a set of UidRanges, or null for everything.
+ * @return The builder to facilitate chaining.
+ * @hide
+ */
+ public Builder setUids(Set<UidRange> uids) {
+ mNetworkCapabilities.setUids(uids);
+ return this;
+ }
+
+ /**
* Add a capability that must not exist in the requested network.
* <p>
* If the capability was previously added to the list of required capabilities (for
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 01b2b39..940f985 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -64,6 +64,9 @@
/** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
public static final int SET_DBG_VPN_OUT = 1002;
+ /** Include all interfaces when filtering */
+ public static final String[] INTERFACES_ALL = null;
+
/** {@link #tag} value for total data across all tags. */
// TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
@@ -359,23 +362,27 @@
capacity = newLength;
}
- iface[size] = entry.iface;
- uid[size] = entry.uid;
- set[size] = entry.set;
- tag[size] = entry.tag;
- metered[size] = entry.metered;
- roaming[size] = entry.roaming;
- defaultNetwork[size] = entry.defaultNetwork;
- rxBytes[size] = entry.rxBytes;
- rxPackets[size] = entry.rxPackets;
- txBytes[size] = entry.txBytes;
- txPackets[size] = entry.txPackets;
- operations[size] = entry.operations;
+ setValues(size, entry);
size++;
return this;
}
+ private void setValues(int i, Entry entry) {
+ iface[i] = entry.iface;
+ uid[i] = entry.uid;
+ set[i] = entry.set;
+ tag[i] = entry.tag;
+ metered[i] = entry.metered;
+ roaming[i] = entry.roaming;
+ defaultNetwork[i] = entry.defaultNetwork;
+ rxBytes[i] = entry.rxBytes;
+ rxPackets[i] = entry.rxPackets;
+ txBytes[i] = entry.txBytes;
+ txPackets[i] = entry.txPackets;
+ operations[i] = entry.operations;
+ }
+
/**
* Return specific stats entry.
*/
@@ -824,6 +831,39 @@
return stats;
}
+ /**
+ * Only keep entries that match all specified filters.
+ *
+ * <p>This mutates the original structure in place. After this method is called,
+ * size is the number of matching entries, and capacity is the previous capacity.
+ * @param limitUid UID to filter for, or {@link #UID_ALL}.
+ * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
+ * @param limitTag Tag to filter for, or {@link #TAG_ALL}.
+ */
+ public void filter(int limitUid, String[] limitIfaces, int limitTag) {
+ if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
+ return;
+ }
+
+ Entry entry = new Entry();
+ int nextOutputEntry = 0;
+ for (int i = 0; i < size; i++) {
+ entry = getValues(i, entry);
+ final boolean matches =
+ (limitUid == UID_ALL || limitUid == entry.uid)
+ && (limitTag == TAG_ALL || limitTag == entry.tag)
+ && (limitIfaces == INTERFACES_ALL
+ || ArrayUtils.contains(limitIfaces, entry.iface));
+
+ if (matches) {
+ setValues(nextOutputEntry, entry);
+ nextOutputEntry++;
+ }
+ }
+
+ size = nextOutputEntry;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b02d48d..c3f23a1 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -225,7 +225,7 @@
* Indicates the Secure Element on which the transaction occurred.
* eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
*/
- public static final String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+ public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
public static final int STATE_OFF = 1;
public static final int STATE_TURNING_ON = 2;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 336e1b4..5652d6d 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -22,6 +22,7 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.BinderInternal;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
@@ -361,7 +362,9 @@
* Add the calling thread to the IPC thread pool. This function does
* not return until the current process is exiting.
*/
- public static final native void joinThreadPool();
+ public static final void joinThreadPool() {
+ BinderInternal.joinThreadPool();
+ }
/**
* Returns true if the specified interface is a proxy.
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index a5e1934..31dbafa 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -268,10 +268,12 @@
NetworkStats getNetworkStatsDetail();
/**
- * Return detailed network statistics for the requested UID,
+ * Return detailed network statistics for the requested UID and interfaces,
* including interface and tag details.
+ * @param uid UID to obtain statistics for, or {@link NetworkStats#UID_ALL}.
+ * @param ifaces Interfaces to obtain statistics for, or {@link NetworkStats#INTERFACES_ALL}.
*/
- NetworkStats getNetworkStatsUidDetail(int uid);
+ NetworkStats getNetworkStatsUidDetail(int uid, in String[] ifaces);
/**
* Return summary of network statistics all tethering interfaces.
@@ -340,7 +342,7 @@
* Configure name servers, search paths, and resolver parameters for the given network.
*/
void setDnsConfigurationForNetwork(int netId, in String[] servers, in String[] domains,
- in int[] params, boolean useTls, String tlsHostname);
+ in int[] params, String tlsHostname, in String[] tlsServers);
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 4f6d322..89168ae 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -189,7 +189,12 @@
}
ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks);
for (int i=0; i<callbacks.size(); i++) {
- callbacks.get(i).run();
+ try {
+ callbacks.get(i).run();
+ } catch (Throwable t) {
+ Log.wtf(TAG, "Exception in SystemProperties change callback", t);
+ // Ignore and try to go on.
+ }
}
}
}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index fa96dd3..0f4fc36 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -89,6 +89,8 @@
public static final long TRACE_TAG_NETWORK = 1L << 21;
/** @hide */
public static final long TRACE_TAG_ADB = 1L << 22;
+ /** @hide */
+ public static final long TRACE_TAG_AIDL = 1L << 24;
private static final long TRACE_TAG_NOT_READY = 1L << 63;
private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 8aef012..67c6fb9 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
+import android.telecom.Log;
/**
* <p>
@@ -261,9 +262,16 @@
*/
@WorkerThread
public static boolean isBlocked(Context context, String phoneNumber) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);
- return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);
+ return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "isBlocked: provider not ready.");
+ return false;
+ }
}
/**
@@ -297,9 +305,16 @@
* @return {@code true} if the current user can block numbers.
*/
public static boolean canCurrentUserBlockNumbers(Context context) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null);
- return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null);
+ return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "canCurrentUserBlockNumbers: provider not ready.");
+ return false;
+ }
}
/**
@@ -368,8 +383,14 @@
* the provider unless {@link #endBlockSuppression(Context)} is called.
*/
public static void notifyEmergencyContact(Context context) {
- context.getContentResolver().call(
- AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null);
+ try {
+ context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "notifyEmergencyContact: provider not ready.");
+ }
}
/**
@@ -394,9 +415,16 @@
*/
public static boolean shouldSystemBlockNumber(Context context, String phoneNumber,
Bundle extras) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
- return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
+ return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "shouldSystemBlockNumber: provider not ready.");
+ return false;
+ }
}
/**
@@ -416,9 +444,16 @@
* @return {@code true} if should show emergency call notification. {@code false} otherwise.
*/
public static boolean shouldShowEmergencyCallNotification(Context context) {
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
- return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
+ return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "shouldShowEmergencyCallNotification: provider not ready.");
+ return false;
+ }
}
/**
@@ -436,9 +471,16 @@
public static boolean getEnhancedBlockSetting(Context context, String key) {
Bundle extras = new Bundle();
extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
- final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
- return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+ try {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
+ return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+ } catch (NullPointerException | IllegalArgumentException ex) {
+ // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+ // either of these happen.
+ Log.w(null, "getEnhancedBlockSetting: provider not ready.");
+ return false;
+ }
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ca3f5e9..2b5353d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3621,6 +3621,14 @@
public static final Validator VIBRATE_WHEN_RINGING_VALIDATOR = sBooleanValidator;
/**
+ * When {@code 1}, Telecom enhanced call blocking functionality is enabled. When
+ * {@code 0}, enhanced call blocking functionality is disabled.
+ * @hide
+ */
+ public static final String DEBUG_ENABLE_ENHANCED_CALL_BLOCKING =
+ "debug.enable_enhanced_calling";
+
+ /**
* Whether the audible DTMF tones are played by the dialer when dialing. The value is
* boolean (1 or 0).
*/
@@ -8706,6 +8714,12 @@
public static final String BLE_SCAN_LOW_LATENCY_INTERVAL_MS =
"ble_scan_low_latency_interval_ms";
+ /**
+ * The mode that BLE scanning clients will be moved to when in the background.
+ * @hide
+ */
+ public static final String BLE_SCAN_BACKGROUND_MODE = "ble_scan_background_mode";
+
/**
* Used to save the Wifi_ON state prior to tethering.
* This state will be checked to restore Wifi after
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 6965dc0..a4ffbe4 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -23,21 +23,24 @@
public final class StatsLog {
private static final String TAG = "StatsManager";
- public static final int BLUETOOTH_ENABLED = 0;
+ public static final int BLUETOOTH_ENABLED_STATE_CHANGED = 0;
+ public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN = 0;
+ public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED = 1;
+ public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED = 2;
public static final int BLUETOOTH_CONNECTION_STATE_CHANGED = 1;
public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED = 2;
public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__UNKNOWN = 0;
- public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__START = 1;
+ public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__PLAY = 1;
public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__STOP = 2;
private StatsLog() {}
public static void write(int id, int field1) {}
- public static void write(int id, int field1, int field2) {}
+ public static void write(int id, int field1, int field2, int field3) {}
public static void write_non_chained(int id, int uid, String tag,
- boolean field1, int field2, String field3) {}
+ int field1, int field2, String field3) {}
}
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 902bd12..8172a20 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -22,16 +22,14 @@
import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import android.annotation.Nullable;
import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
-import android.util.ArrayMap;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
-import com.google.android.collect.Lists;
import libcore.io.IoUtils;
@@ -41,8 +39,10 @@
import java.io.FileReader;
import java.io.IOException;
import java.net.ProtocolException;
-import java.util.ArrayList;
-import java.util.Objects;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Creates {@link NetworkStats} instances by parsing various {@code /proc/}
@@ -70,18 +70,55 @@
private boolean mUseBpfStats;
- // TODO: to improve testability and avoid global state, do not use a static variable.
- @GuardedBy("sStackedIfaces")
- private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
+ // TODO: only do adjustments in NetworkStatsService and remove this.
+ /**
+ * (Stacked interface) -> (base interface) association for all connected ifaces since boot.
+ *
+ * Because counters must never roll backwards, once a given interface is stacked on top of an
+ * underlying interface, the stacked interface can never be stacked on top of
+ * another interface. */
+ private static final ConcurrentHashMap<String, String> sStackedIfaces
+ = new ConcurrentHashMap<>();
public static void noteStackedIface(String stackedIface, String baseIface) {
- synchronized (sStackedIfaces) {
- if (baseIface != null) {
- sStackedIfaces.put(stackedIface, baseIface);
- } else {
- sStackedIfaces.remove(stackedIface);
+ if (stackedIface != null && baseIface != null) {
+ sStackedIfaces.put(stackedIface, baseIface);
+ }
+ }
+
+ /**
+ * Get a set of interfaces containing specified ifaces and stacked interfaces.
+ *
+ * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
+ * on which the specified ones are stacked. Stacked interfaces are those noted with
+ * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
+ * is called are guaranteed to be included.
+ */
+ public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) {
+ if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
+ return null;
+ }
+
+ HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
+ // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
+ // elements as they existed upon construction exactly once, and may
+ // (but are not guaranteed to) reflect any modifications subsequent to construction".
+ // This is enough here.
+ for (Map.Entry<String, String> entry : sStackedIfaces.entrySet()) {
+ if (relatedIfaces.contains(entry.getKey())) {
+ relatedIfaces.add(entry.getValue());
+ } else if (relatedIfaces.contains(entry.getValue())) {
+ relatedIfaces.add(entry.getKey());
}
}
+
+ String[] outArray = new String[relatedIfaces.size()];
+ return relatedIfaces.toArray(outArray);
+ }
+
+ @VisibleForTesting
+ public static void clearStackedIfaces() {
+ sStackedIfaces.clear();
}
public NetworkStatsFactory() {
@@ -250,12 +287,9 @@
NetworkStats lastStats) throws IOException {
final NetworkStats stats =
readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats);
- final ArrayMap<String, String> stackedIfaces;
- synchronized (sStackedIfaces) {
- stackedIfaces = new ArrayMap<>(sStackedIfaces);
- }
// Total 464xlat traffic to subtract from uid 0 on all base interfaces.
- final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size());
+ // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically.
+ final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size());
NetworkStats.Entry entry = null; // For recycling
@@ -269,7 +303,7 @@
if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) {
continue;
}
- final String baseIface = stackedIfaces.get(entry.iface);
+ final String baseIface = sStackedIfaces.get(entry.iface);
if (baseIface == null) {
continue;
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 4901080..f0e7796 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -115,6 +115,14 @@
command.append(' ');
command.append(appProcess);
+ // Generate bare minimum of debug information to be able to backtrace through JITed code.
+ // We assume that if the invoke wrapper is used, backtraces are desirable:
+ // * The wrap.sh script can only be used by debuggable apps, which would enable this flag
+ // without the script anyway (the fork-zygote path). So this makes the two consistent.
+ // * The wrap.* property can only be used on userdebug builds and is likely to be used by
+ // developers (e.g. enable debug-malloc), in which case backtraces are also useful.
+ command.append(" -Xcompiler-option --generate-mini-debug-info");
+
command.append(" /system/bin --application");
if (niceName != null) {
command.append(" '--nice-name=").append(niceName).append("'");
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index e23cbf8..0d10888 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -55,10 +55,21 @@
public static final int DISABLE_VERIFIER = 1 << 9;
/** Only use oat files located in /system. Otherwise use dex/jar/apk . */
public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
- /** Do enfore hidden API access restrictions. */
- public static final int ENABLE_HIDDEN_API_CHECKS = 1 << 11;
/** Force generation of native debugging information for backtraces. */
- public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12;
+ public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 11;
+ /**
+ * Hidden API access restrictions. This is a mask for bits representing the API enforcement
+ * policy, defined by {@code @ApplicationInfo.HiddenApiEnforcementPolicy}.
+ */
+ public static final int API_ENFORCEMENT_POLICY_MASK = (1 << 12) | (1 << 13);
+ /**
+ * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}.
+ *
+ * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives
+ * @ApplicationInfo.ApiEnforcementPolicy values.
+ */
+ public static final int API_ENFORCEMENT_POLICY_SHIFT =
+ Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK);
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3784d4d..6c46cfc 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -20,6 +20,7 @@
#include <android_runtime/AndroidRuntime.h>
+#include <android-base/macros.h>
#include <android-base/properties.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
@@ -860,34 +861,18 @@
// The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
// pass the instruction-set-features/variant as an image-compiler-option.
- // TODO: Find a better way for the instruction-set.
-#if defined(__arm__)
- constexpr const char* instruction_set = "arm";
-#elif defined(__aarch64__)
- constexpr const char* instruction_set = "arm64";
-#elif defined(__mips__) && !defined(__LP64__)
- constexpr const char* instruction_set = "mips";
-#elif defined(__mips__) && defined(__LP64__)
- constexpr const char* instruction_set = "mips64";
-#elif defined(__i386__)
- constexpr const char* instruction_set = "x86";
-#elif defined(__x86_64__)
- constexpr const char* instruction_set = "x86_64";
-#else
- constexpr const char* instruction_set = "unknown";
-#endif
// Note: it is OK to reuse the buffer, as the values are exactly the same between
// * compiler-option, used for runtime compilation (DexClassLoader)
// * image-compiler-option, used for boot-image compilation on device
// Copy the variant.
- sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
+ sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", ABI_STRING);
parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
"--instruction-set-variant=", "-Ximage-compiler-option");
parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
"--instruction-set-variant=", "-Xcompiler-option");
// Copy the features.
- sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
+ sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", ABI_STRING);
parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
"--instruction-set-features=", "-Ximage-compiler-option");
parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index a94cac0..9ec7517 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -124,6 +124,12 @@
if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
//ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
+ // There should not be any exceptions. But we must guarantee
+ // there are none on return.
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ LOG(ERROR) << "Exception pending after sysprop_change!";
+ }
}
}
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 6532569..f1b736b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -71,6 +71,9 @@
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
+ append(StringPrintf(__VA_ARGS__))
+
static pid_t gSystemServerPid = 0;
static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
@@ -186,30 +189,32 @@
// Calls POSIX setgroups() using the int[] object as an argument.
// A NULL argument is tolerated.
-static void SetGids(JNIEnv* env, jintArray javaGids) {
+static bool SetGids(JNIEnv* env, jintArray javaGids, std::string* error_msg) {
if (javaGids == NULL) {
- return;
+ return true;
}
ScopedIntArrayRO gids(env, javaGids);
if (gids.get() == NULL) {
- RuntimeAbort(env, __LINE__, "Getting gids int array failed");
+ *error_msg = CREATE_ERROR("Getting gids int array failed");
+ return false;
}
int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
if (rc == -1) {
- std::ostringstream oss;
- oss << "setgroups failed: " << strerror(errno) << ", gids.size=" << gids.size();
- RuntimeAbort(env, __LINE__, oss.str().c_str());
+ *error_msg = CREATE_ERROR("setgroups failed: %s, gids.size=%zu", strerror(errno), gids.size());
+ return false;
}
+
+ return true;
}
// Sets the resource limits via setrlimit(2) for the values in the
// two-dimensional array of integers that's passed in. The second dimension
// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
// treated as an empty array.
-static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+static bool SetRLimits(JNIEnv* env, jobjectArray javaRlimits, std::string* error_msg) {
if (javaRlimits == NULL) {
- return;
+ return true;
}
rlimit rlim;
@@ -219,7 +224,8 @@
ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
if (javaRlimit.size() != 3) {
- RuntimeAbort(env, __LINE__, "rlimits array must have a second dimension of size 3");
+ *error_msg = CREATE_ERROR("rlimits array must have a second dimension of size 3");
+ return false;
}
rlim.rlim_cur = javaRlimit[1];
@@ -227,11 +233,13 @@
int rc = setrlimit(javaRlimit[0], &rlim);
if (rc == -1) {
- ALOGE("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
+ *error_msg = CREATE_ERROR("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
rlim.rlim_max);
- RuntimeAbort(env, __LINE__, "setrlimit failed");
+ return false;
}
}
+
+ return true;
}
// The debug malloc library needs to know whether it's the zygote or a child.
@@ -259,14 +267,16 @@
}
}
-static void EnableKeepCapabilities(JNIEnv* env) {
+static bool EnableKeepCapabilities(std::string* error_msg) {
int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
if (rc == -1) {
- RuntimeAbort(env, __LINE__, "prctl(PR_SET_KEEPCAPS) failed");
+ *error_msg = CREATE_ERROR("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno));
+ return false;
}
+ return true;
}
-static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+static bool DropCapabilitiesBoundingSet(std::string* error_msg) {
for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
if (rc == -1) {
@@ -274,14 +284,15 @@
ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
"your kernel is compiled with file capabilities support");
} else {
- ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
- RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed");
+ *error_msg = CREATE_ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
+ return false;
}
}
}
+ return true;
}
-static void SetInheritable(JNIEnv* env, uint64_t inheritable) {
+static bool SetInheritable(uint64_t inheritable, std::string* error_msg) {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -289,21 +300,23 @@
__user_cap_data_struct capdata[2];
if (capget(&capheader, &capdata[0]) == -1) {
- ALOGE("capget failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "capget failed");
+ *error_msg = CREATE_ERROR("capget failed: %s", strerror(errno));
+ return false;
}
capdata[0].inheritable = inheritable;
capdata[1].inheritable = inheritable >> 32;
if (capset(&capheader, &capdata[0]) == -1) {
- ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
- RuntimeAbort(env, __LINE__, "capset failed");
+ *error_msg = CREATE_ERROR("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
+ return false;
}
+
+ return true;
}
-static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective,
- uint64_t inheritable) {
+static bool SetCapabilities(uint64_t permitted, uint64_t effective, uint64_t inheritable,
+ std::string* error_msg) {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -319,18 +332,20 @@
capdata[1].inheritable = inheritable >> 32;
if (capset(&capheader, &capdata[0]) == -1) {
- ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted,
- effective, inheritable, strerror(errno));
- RuntimeAbort(env, __LINE__, "capset failed");
+ *error_msg = CREATE_ERROR("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") "
+ "failed: %s", permitted, effective, inheritable, strerror(errno));
+ return false;
}
+ return true;
}
-static void SetSchedulerPolicy(JNIEnv* env) {
+static bool SetSchedulerPolicy(std::string* error_msg) {
errno = -set_sched_policy(0, SP_DEFAULT);
if (errno != 0) {
- ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
- RuntimeAbort(env, __LINE__, "set_sched_policy(0, SP_DEFAULT) failed");
+ *error_msg = CREATE_ERROR("set_sched_policy(0, SP_DEFAULT) failed: %s", strerror(errno));
+ return false;
}
+ return true;
}
static int UnmountTree(const char* path) {
@@ -364,7 +379,7 @@
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
- bool force_mount_namespace) {
+ bool force_mount_namespace, std::string* error_msg) {
// See storage config details at http://source.android.com/tech/storage/
String8 storageSource;
@@ -381,7 +396,7 @@
// Create a second private mount namespace for our process
if (unshare(CLONE_NEWNS) == -1) {
- ALOGW("Failed to unshare(): %s", strerror(errno));
+ *error_msg = CREATE_ERROR("Failed to unshare(): %s", strerror(errno));
return false;
}
@@ -392,7 +407,9 @@
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
- ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
+ *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+ storageSource.string(),
+ strerror(errno));
return false;
}
@@ -400,11 +417,14 @@
userid_t user_id = multiuser_get_user_id(uid);
const String8 userSource(String8::format("/mnt/user/%d", user_id));
if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+ *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
return false;
}
if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
NULL, MS_BIND, NULL)) == -1) {
- ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno));
+ *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+ userSource.string(),
+ strerror(errno));
return false;
}
@@ -436,31 +456,32 @@
// descriptor (if any) is closed via dup2(), replacing it with a valid
// (open) descriptor to /dev/null.
-static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+static bool DetachDescriptors(JNIEnv* env, jintArray fdsToClose, std::string* error_msg) {
if (!fdsToClose) {
- return;
+ return true;
}
jsize count = env->GetArrayLength(fdsToClose);
ScopedIntArrayRO ar(env, fdsToClose);
if (ar.get() == NULL) {
- RuntimeAbort(env, __LINE__, "Bad fd array");
+ *error_msg = "Bad fd array";
+ return false;
}
jsize i;
int devnull;
for (i = 0; i < count; i++) {
devnull = open("/dev/null", O_RDWR);
if (devnull < 0) {
- ALOGE("Failed to open /dev/null: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "Failed to open /dev/null");
- continue;
+ *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
+ return false;
}
ALOGV("Switching descriptor %d to /dev/null: %s", ar[i], strerror(errno));
if (dup2(devnull, ar[i]) < 0) {
- ALOGE("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
- RuntimeAbort(env, __LINE__, "Failed dup2()");
+ *error_msg = StringPrintf("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
+ return false;
}
close(devnull);
}
+ return true;
}
void SetThreadName(const char* thread_name) {
@@ -495,20 +516,23 @@
// The list of open zygote file descriptors.
static FileDescriptorTable* gOpenFdTable = NULL;
-static void FillFileDescriptorVector(JNIEnv* env,
+static bool FillFileDescriptorVector(JNIEnv* env,
jintArray java_fds,
- std::vector<int>* fds) {
+ std::vector<int>* fds,
+ std::string* error_msg) {
CHECK(fds != nullptr);
if (java_fds != nullptr) {
ScopedIntArrayRO ar(env, java_fds);
if (ar.get() == nullptr) {
- RuntimeAbort(env, __LINE__, "Bad fd array");
+ *error_msg = "Bad fd array";
+ return false;
}
fds->reserve(ar.size());
for (size_t i = 0; i < ar.size(); ++i) {
fds->push_back(ar[i]);
}
}
+ return true;
}
// Utility routine to fork zygote and specialize the child process.
@@ -526,32 +550,53 @@
sigemptyset(&sigchld);
sigaddset(&sigchld, SIGCHLD);
+ auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
+ __attribute__ ((noreturn)) {
+ const char* se_name_c_str = nullptr;
+ std::unique_ptr<ScopedUtfChars> se_name;
+ if (java_se_name != nullptr) {
+ se_name.reset(new ScopedUtfChars(env, java_se_name));
+ se_name_c_str = se_name->c_str();
+ }
+ if (se_name_c_str == nullptr && is_system_server) {
+ se_name_c_str = "system_server";
+ }
+ const std::string& error_msg = (se_name_c_str == nullptr)
+ ? msg
+ : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
+ env->FatalError(error_msg.c_str());
+ __builtin_unreachable();
+ };
+
// Temporarily block SIGCHLD during forks. The SIGCHLD handler might
// log, which would result in the logging FDs we close being reopened.
// This would cause failures because the FDs are not whitelisted.
//
// Note that the zygote process is single threaded at this point.
if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
- ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
+ fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
}
// Close any logging related FDs before we start evaluating the list of
// file descriptors.
__android_log_close();
+ std::string error_msg;
+
// If this is the first fork for this zygote, create the open FD table.
// If it isn't, we just need to check whether the list of open files has
// changed (and it shouldn't in the normal case).
std::vector<int> fds_to_ignore;
- FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
+ if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
+ fail_fn(error_msg);
+ }
if (gOpenFdTable == NULL) {
- gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
+ gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
if (gOpenFdTable == NULL) {
- RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
+ fail_fn(error_msg);
}
- } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
- RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
+ } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
+ fail_fn(error_msg);
}
pid_t pid = fork();
@@ -560,17 +605,18 @@
PreApplicationInit();
// Clean up any descriptors which must be closed immediately
- DetachDescriptors(env, fdsToClose);
+ if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
+ fail_fn(error_msg);
+ }
// Re-open all remaining open file descriptors so that they aren't shared
// with the zygote across a fork.
- if (!gOpenFdTable->ReopenOrDetach()) {
- RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
+ if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
+ fail_fn(error_msg);
}
if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
- ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+ fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
}
// Must be called when the new process still has CAP_SYS_ADMIN. The other alternative is to
@@ -580,11 +626,17 @@
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
- EnableKeepCapabilities(env);
+ if (!EnableKeepCapabilities(&error_msg)) {
+ fail_fn(error_msg);
+ }
}
- SetInheritable(env, permittedCapabilities);
- DropCapabilitiesBoundingSet(env);
+ if (!SetInheritable(permittedCapabilities, &error_msg)) {
+ fail_fn(error_msg);
+ }
+ if (!DropCapabilitiesBoundingSet(&error_msg)) {
+ fail_fn(error_msg);
+ }
bool use_native_bridge = !is_system_server && (instructionSet != NULL)
&& android::NativeBridgeAvailable();
@@ -601,8 +653,8 @@
ALOGW("Native bridge will not be used because dataDir == NULL.");
}
- if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
- ALOGW("Failed to mount emulated storage: %s", strerror(errno));
+ if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) {
+ ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
if (errno == ENOTCONN || errno == EROFS) {
// When device is actively encrypting, we get ENOTCONN here
// since FUSE was mounted before the framework restarted.
@@ -610,7 +662,7 @@
// FUSE hasn't been created yet by init.
// In either case, continue without external storage.
} else {
- RuntimeAbort(env, __LINE__, "Cannot continue without emulated storage");
+ fail_fn(error_msg);
}
}
@@ -625,9 +677,14 @@
}
}
- SetGids(env, javaGids);
+ std::string error_msg;
+ if (!SetGids(env, javaGids, &error_msg)) {
+ fail_fn(error_msg);
+ }
- SetRLimits(env, javaRlimits);
+ if (!SetRLimits(env, javaRlimits, &error_msg)) {
+ fail_fn(error_msg);
+ }
if (use_native_bridge) {
ScopedUtfChars isa_string(env, instructionSet);
@@ -637,14 +694,12 @@
int rc = setresgid(gid, gid, gid);
if (rc == -1) {
- ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
- RuntimeAbort(env, __LINE__, "setresgid failed");
+ fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
}
rc = setresuid(uid, uid, uid);
if (rc == -1) {
- ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
- RuntimeAbort(env, __LINE__, "setresuid failed");
+ fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
}
if (NeedsNoRandomizeWorkaround()) {
@@ -656,9 +711,14 @@
}
}
- SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
+ if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
+ &error_msg)) {
+ fail_fn(error_msg);
+ }
- SetSchedulerPolicy(env);
+ if (!SetSchedulerPolicy(&error_msg)) {
+ fail_fn(error_msg);
+ }
const char* se_info_c_str = NULL;
ScopedUtfChars* se_info = NULL;
@@ -666,7 +726,7 @@
se_info = new ScopedUtfChars(env, java_se_info);
se_info_c_str = se_info->c_str();
if (se_info_c_str == NULL) {
- RuntimeAbort(env, __LINE__, "se_info_c_str == NULL");
+ fail_fn("se_info_c_str == NULL");
}
}
const char* se_name_c_str = NULL;
@@ -675,14 +735,13 @@
se_name = new ScopedUtfChars(env, java_se_name);
se_name_c_str = se_name->c_str();
if (se_name_c_str == NULL) {
- RuntimeAbort(env, __LINE__, "se_name_c_str == NULL");
+ fail_fn("se_name_c_str == NULL");
}
}
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
if (rc == -1) {
- ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
- is_system_server, se_info_c_str, se_name_c_str);
- RuntimeAbort(env, __LINE__, "selinux_android_setcontext failed");
+ fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+ is_system_server, se_info_c_str, se_name_c_str));
}
// Make it easier to debug audit logs by setting the main thread's name to the
@@ -703,15 +762,14 @@
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
is_system_server, is_child_zygote, instructionSet);
if (env->ExceptionCheck()) {
- RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
+ fail_fn("Error calling post fork hooks.");
}
} else if (pid > 0) {
// the parent process
// We blocked SIGCHLD prior to a fork, we unblock it here.
if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
- ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+ fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
}
}
return pid;
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 1383bbd..b19848b 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -119,14 +119,57 @@
FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+ // Create a FileDescriptorInfo for a given file descriptor. Returns
+ // |NULL| if an error occurred.
+ static FileDescriptorInfo* CreateFromFd(int fd, std::string* error_msg);
+
+ // Checks whether the file descriptor associated with this object
+ // refers to the same description.
+ bool Restat() const;
+
+ bool ReopenOrDetach(std::string* error_msg) const;
+
+ const int fd;
+ const struct stat stat;
+ const std::string file_path;
+ const int open_flags;
+ const int fd_flags;
+ const int fs_flags;
+ const off_t offset;
+ const bool is_sock;
+
+ private:
+ FileDescriptorInfo(int fd);
+
+ FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+ int fd_flags, int fs_flags, off_t offset);
+
+ // Returns the locally-bound name of the socket |fd|. Returns true
+ // iff. all of the following hold :
+ //
+ // - the socket's sa_family is AF_UNIX.
+ // - the length of the path is greater than zero (i.e, not an unnamed socket).
+ // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+ // address).
+ static bool GetSocketName(const int fd, std::string* result);
+
+ bool DetachSocket(std::string* error_msg) const;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
// static
-FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
+FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, std::string* error_msg) {
struct stat f_stat;
// This should never happen; the zygote should always have the right set
// of permissions required to stat all its open files.
if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
- PLOG(ERROR) << "Unable to stat fd " << fd;
- return NULL;
+ *error_msg = android::base::StringPrintf("Unable to stat %d", fd);
+ return nullptr;
}
const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
@@ -134,13 +177,15 @@
if (S_ISSOCK(f_stat.st_mode)) {
std::string socket_name;
if (!GetSocketName(fd, &socket_name)) {
- return NULL;
+ *error_msg = "Unable to get socket name";
+ return nullptr;
}
if (!whitelist->IsAllowed(socket_name)) {
- LOG(ERROR) << "Socket name not whitelisted : " << socket_name
- << " (fd=" << fd << ")";
- return NULL;
+ *error_msg = android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
+ socket_name.c_str(),
+ fd);
+ return nullptr;
}
return new FileDescriptorInfo(fd);
@@ -157,19 +202,22 @@
// with the child process across forks but those should have been closed
// before we got to this point.
if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
- LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
- return NULL;
+ *error_msg = android::base::StringPrintf("Unsupported st_mode %u", f_stat.st_mode);
+ return nullptr;
}
std::string file_path;
const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
if (!android::base::Readlink(fd_path, &file_path)) {
- return NULL;
+ *error_msg = android::base::StringPrintf("Could not read fd link %s: %s",
+ fd_path.c_str(),
+ strerror(errno));
+ return nullptr;
}
if (!whitelist->IsAllowed(file_path)) {
- LOG(ERROR) << "Not whitelisted : " << file_path;
- return NULL;
+ *error_msg = std::string("Not whitelisted : ").append(file_path);
+ return nullptr;
}
// File descriptor flags : currently on FD_CLOEXEC. We can set these
@@ -177,8 +225,11 @@
// there won't be any races.
const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
if (fd_flags == -1) {
- PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
- return NULL;
+ *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
+ fd,
+ file_path.c_str(),
+ strerror(errno));
+ return nullptr;
}
// File status flags :
@@ -195,8 +246,11 @@
// their presence and pass them in to open().
int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (fs_flags == -1) {
- PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
- return NULL;
+ *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
+ fd,
+ file_path.c_str(),
+ strerror(errno));
+ return nullptr;
}
// File offset : Ignore the offset for non seekable files.
@@ -221,9 +275,9 @@
return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
}
-bool FileDescriptorInfo::ReopenOrDetach() const {
+bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const {
if (is_sock) {
- return DetachSocket();
+ return DetachSocket(error_msg);
}
// NOTE: This might happen if the file was unlinked after being opened.
@@ -232,31 +286,49 @@
const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
if (new_fd == -1) {
- PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
+ *error_msg = android::base::StringPrintf("Failed open(%s, %i): %s",
+ file_path.c_str(),
+ open_flags,
+ strerror(errno));
return false;
}
if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
close(new_fd);
- PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
+ *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
+ new_fd,
+ fd_flags,
+ file_path.c_str(),
+ strerror(errno));
return false;
}
if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
close(new_fd);
- PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
+ *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
+ new_fd,
+ fs_flags,
+ file_path.c_str(),
+ strerror(errno));
return false;
}
if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
close(new_fd);
- PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
+ *error_msg = android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
+ new_fd,
+ file_path.c_str(),
+ strerror(errno));
return false;
}
if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
close(new_fd);
- PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
+ *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s",
+ fd,
+ new_fd,
+ file_path.c_str(),
+ strerror(errno));
return false;
}
@@ -332,20 +404,22 @@
return true;
}
-bool FileDescriptorInfo::DetachSocket() const {
+bool FileDescriptorInfo::DetachSocket(std::string* error_msg) const {
const int dev_null_fd = open("/dev/null", O_RDWR);
if (dev_null_fd < 0) {
- PLOG(ERROR) << "Failed to open /dev/null";
+ *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
return false;
}
if (dup2(dev_null_fd, fd) == -1) {
- PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
+ *error_msg = android::base::StringPrintf("Failed dup2 on socket descriptor %d: %s",
+ fd,
+ strerror(errno));
return false;
}
if (close(dev_null_fd) == -1) {
- PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
+ *error_msg = android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno));
return false;
}
@@ -353,11 +427,12 @@
}
// static
-FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
+ std::string* error_msg) {
DIR* d = opendir(kFdPath);
- if (d == NULL) {
- PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
- return NULL;
+ if (d == nullptr) {
+ *error_msg = std::string("Unable to open directory ").append(kFdPath);
+ return nullptr;
}
int dir_fd = dirfd(d);
dirent* e;
@@ -373,7 +448,7 @@
continue;
}
- FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+ FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
if (info == NULL) {
if (closedir(d) == -1) {
PLOG(ERROR) << "Unable to close directory";
@@ -384,19 +459,21 @@
}
if (closedir(d) == -1) {
- PLOG(ERROR) << "Unable to close directory";
- return NULL;
+ *error_msg = "Unable to close directory";
+ return nullptr;
}
return new FileDescriptorTable(open_fd_map);
}
-bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg) {
std::set<int> open_fds;
// First get the list of open descriptors.
DIR* d = opendir(kFdPath);
if (d == NULL) {
- PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
+ *error_msg = android::base::StringPrintf("Unable to open directory %s: %s",
+ kFdPath,
+ strerror(errno));
return false;
}
@@ -416,21 +493,21 @@
}
if (closedir(d) == -1) {
- PLOG(ERROR) << "Unable to close directory";
+ *error_msg = android::base::StringPrintf("Unable to close directory: %s", strerror(errno));
return false;
}
- return RestatInternal(open_fds);
+ return RestatInternal(open_fds, error_msg);
}
// Reopens all file descriptors that are contained in the table. Returns true
// if all descriptors were successfully re-opened or detached, and false if an
// error occurred.
-bool FileDescriptorTable::ReopenOrDetach() {
+bool FileDescriptorTable::ReopenOrDetach(std::string* error_msg) {
std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
const FileDescriptorInfo* info = it->second;
- if (info == NULL || !info->ReopenOrDetach()) {
+ if (info == NULL || !info->ReopenOrDetach(error_msg)) {
return false;
}
}
@@ -443,7 +520,7 @@
: open_fd_map_(map) {
}
-bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) {
+bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds, std::string* error_msg) {
bool error = false;
// Iterate through the list of file descriptors we've already recorded
@@ -451,6 +528,8 @@
//
// (a) they continue to be open.
// (b) they refer to the same file.
+ //
+ // We'll only store the last error message.
std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
while (it != open_fd_map_.end()) {
std::set<int>::const_iterator element = open_fds.find(it->first);
@@ -471,7 +550,7 @@
// The file descriptor refers to a different description. We must
// update our entry in the table.
delete it->second;
- it->second = FileDescriptorInfo::CreateFromFd(*element);
+ it->second = FileDescriptorInfo::CreateFromFd(*element, error_msg);
if (it->second == NULL) {
// The descriptor no longer no longer refers to a whitelisted file.
// We flag an error and remove it from the list of files we're
@@ -506,7 +585,7 @@
std::set<int>::const_iterator it;
for (it = open_fds.begin(); it != open_fds.end(); ++it) {
const int fd = (*it);
- FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+ FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
if (info == NULL) {
// A newly opened file is not on the whitelist. Flag an error and
// continue.
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a39e387..a3570d7 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -28,6 +28,8 @@
#include <android-base/macros.h>
+class FileDescriptorInfo;
+
// Whitelist of open paths that the zygote is allowed to keep open.
//
// In addition to the paths listed in kPathWhitelist in file_utils.cpp, and
@@ -66,49 +68,6 @@
DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist);
};
-// Keeps track of all relevant information (flags, offset etc.) of an
-// open zygote file descriptor.
-class FileDescriptorInfo {
- public:
- // Create a FileDescriptorInfo for a given file descriptor. Returns
- // |NULL| if an error occurred.
- static FileDescriptorInfo* CreateFromFd(int fd);
-
- // Checks whether the file descriptor associated with this object
- // refers to the same description.
- bool Restat() const;
-
- bool ReopenOrDetach() const;
-
- const int fd;
- const struct stat stat;
- const std::string file_path;
- const int open_flags;
- const int fd_flags;
- const int fs_flags;
- const off_t offset;
- const bool is_sock;
-
- private:
- FileDescriptorInfo(int fd);
-
- FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
- int fd_flags, int fs_flags, off_t offset);
-
- // Returns the locally-bound name of the socket |fd|. Returns true
- // iff. all of the following hold :
- //
- // - the socket's sa_family is AF_UNIX.
- // - the length of the path is greater than zero (i.e, not an unnamed socket).
- // - the first byte of the path isn't zero (i.e, not a socket with an abstract
- // address).
- static bool GetSocketName(const int fd, std::string* result);
-
- bool DetachSocket() const;
-
- DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
-};
-
// A FileDescriptorTable is a collection of FileDescriptorInfo objects
// keyed by their FDs.
class FileDescriptorTable {
@@ -116,19 +75,20 @@
// Creates a new FileDescriptorTable. This function scans
// /proc/self/fd for the list of open file descriptors and collects
// information about them. Returns NULL if an error occurs.
- static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
+ static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore,
+ std::string* error_msg);
- bool Restat(const std::vector<int>& fds_to_ignore);
+ bool Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg);
// Reopens all file descriptors that are contained in the table. Returns true
// if all descriptors were successfully re-opened or detached, and false if an
// error occurred.
- bool ReopenOrDetach();
+ bool ReopenOrDetach(std::string* error_msg);
private:
FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
- bool RestatInternal(std::set<int>& open_fds);
+ bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
static int ParseFd(dirent* e, int dir_fd);
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dc14b23..9e38efe 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -138,25 +138,28 @@
<string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
<!-- Notification title to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnDataTitle">No data service</string>
+ <string name="RestrictedOnDataTitle">No mobile data service</string>
<!-- Notification title to tell the user that emergency calling is blocked by access control. -->
- <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
+ <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
<!-- Notification title to tell the user that normal service is blocked by access control. -->
<string name="RestrictedOnNormalTitle">No voice service</string>
<!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
+ <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
<!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
- <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
+ <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
+
+ <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control when multiple SIMs are active. -->
+ <string name="RestrictedStateContentMsimTemplate">Temporarily turned off by your carrier for SIM <xliff:g id="simNumber" example="1">%d</xliff:g></string>
<!-- Displayed to tell the user that they should switch their network preference. -->
- <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
+ <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach mobile network</string>
<!-- Displayed to tell the user that they should switch their network preference. -->
- <string name="NetworkPreferenceSwitchSummary">To improve reception, try changing the type selected at Settings > Network & Internet > Mobile networks > Preferred network type."</string>
+ <string name="NetworkPreferenceSwitchSummary">Try changing preferred network. Tap to change.</string>
<!-- Displayed to tell the user that emergency calls might not be available. -->
- <string name="EmergencyCallWarningTitle">Wi\u2011Fi calling is active</string>
+ <string name="EmergencyCallWarningTitle">Emergency calling unavailable</string>
<!-- Displayed to tell the user that emergency calls might not be available. -->
- <string name="EmergencyCallWarningSummary">Emergency calls require a mobile network.</string>
+ <string name="EmergencyCallWarningSummary">Can\u2019t make emergency calls over Wi\u2011Fi</string>
<!-- Telephony notification channel name for a channel containing network alert notifications. -->
<string name="notification_channel_network_alert">Alerts</string>
@@ -215,14 +218,14 @@
<string name="roamingTextSearching">Searching for Service</string>
<!-- Displayed when WFC registration fails -->
- <string name="wfcRegErrorTitle">Wi-Fi Calling</string>
+ <string name="wfcRegErrorTitle">Couldn\u2019t set up Wi\u2011Fi calling</string>
<!-- WFC Operator Error Messages showed as alerts -->
<string-array name="wfcOperatorErrorAlertMessages">
<item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g>)</item>
</string-array>
<!-- WFC Operator Error Messages showed as notifications -->
<string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier (Error code: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g>)</item>
+ <item>Issue registering Wi\u2011Fi calling with your carrier: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g></item>
</string-array>
<!-- Template for showing mobile network operator name while WFC is active -->
<string-array name="wfcSpnFormats">
@@ -4437,14 +4440,14 @@
<!-- Displayed when the USSD/SS request is modified by STK CC to a
different request. This will be displayed in a toast. -->
- <string name="stk_cc_ussd_to_dial">USSD request is modified to DIAL request.</string>
- <string name="stk_cc_ussd_to_ss">USSD request is modified to SS request.</string>
- <string name="stk_cc_ussd_to_ussd">USSD request is modified to new USSD request.</string>
- <string name="stk_cc_ussd_to_dial_video">USSD request is modified to Video DIAL request.</string>
- <string name="stk_cc_ss_to_dial">SS request is modified to DIAL request.</string>
- <string name="stk_cc_ss_to_dial_video">SS request is modified to Video DIAL request.</string>
- <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
- <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
+ <string name="stk_cc_ussd_to_dial">USSD request changed to regular call</string>
+ <string name="stk_cc_ussd_to_ss">USSD request changed to SS request</string>
+ <string name="stk_cc_ussd_to_ussd">Changed to new USSD request</string>
+ <string name="stk_cc_ussd_to_dial_video">USSD request changed to video call</string>
+ <string name="stk_cc_ss_to_dial">SS request changed to regular call</string>
+ <string name="stk_cc_ss_to_dial_video">SS request changed to video call</string>
+ <string name="stk_cc_ss_to_ussd">SS request changed to USSD request</string>
+ <string name="stk_cc_ss_to_ss">Changed to new SS request</string>
<!-- Content description of the work profile icon in the notification. -->
<string name="notification_work_profile_content_description">Work profile</string>
@@ -4682,11 +4685,17 @@
<!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for others -->
<string name="etws_primary_default_message_others"></string>
- <!-- Title of notification when UE fails to register network with MM reject cause code. -->
- <string name="mmcc_authentication_reject">SIM not allowed</string>
- <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned</string>
- <string name="mmcc_illegal_ms">SIM not allowed</string>
- <string name="mmcc_illegal_me">Phone not allowed</string>
+ <!-- Title of notification when UE fails CS registration network with MM reject cause code from network. -->
+ <string name="mmcc_authentication_reject">SIM not allowed for voice</string>
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned for voice</string>
+ <string name="mmcc_illegal_ms">SIM not allowed for voice</string>
+ <string name="mmcc_illegal_me">Phone not allowed for voice</string>
+
+ <!-- Title of notification when UE fails to register network with MM reject cause code when multiple SIMs are active. -->
+ <string name="mmcc_authentication_reject_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not provisioned</string>
+ <string name="mmcc_illegal_ms_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
+ <string name="mmcc_illegal_me_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
<!-- Popup window default title to be read by a screen reader-->
<string name="popup_window_default_title">Popup Window</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f089ff0..e52f0f8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -547,6 +547,7 @@
<java-symbol type="string" name="RestrictedOnEmergencyTitle" />
<java-symbol type="string" name="RestrictedOnNormalTitle" />
<java-symbol type="string" name="RestrictedStateContent" />
+ <java-symbol type="string" name="RestrictedStateContentMsimTemplate" />
<java-symbol type="string" name="notification_channel_network_alert" />
<java-symbol type="string" name="notification_channel_call_forward" />
<java-symbol type="string" name="notification_channel_emergency_callback" />
@@ -1956,6 +1957,10 @@
<java-symbol type="string" name="mmcc_imsi_unknown_in_hlr" />
<java-symbol type="string" name="mmcc_illegal_ms" />
<java-symbol type="string" name="mmcc_illegal_me" />
+ <java-symbol type="string" name="mmcc_authentication_reject_msim_template" />
+ <java-symbol type="string" name="mmcc_imsi_unknown_in_hlr_msim_template" />
+ <java-symbol type="string" name="mmcc_illegal_ms_msim_template" />
+ <java-symbol type="string" name="mmcc_illegal_me_msim_template" />
<java-symbol type="string" name="notification_listener_binding_label" />
<java-symbol type="string" name="vr_listener_binding_label" />
<java-symbol type="string" name="condition_provider_service_binding_label" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 757a70c..8a7c586 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -64,6 +64,7 @@
Settings.System.NOTIFICATION_LIGHT_PULSE, // candidate for backup?
Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
Settings.System.POINTER_LOCATION, // backup candidate?
+ Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, // used for testing only
Settings.System.RINGTONE_CACHE, // internal cache
Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
@@ -117,6 +118,7 @@
Settings.Global.BLE_SCAN_BALANCED_INTERVAL_MS,
Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
+ Settings.Global.BLE_SCAN_BACKGROUND_MODE,
Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 282b001..933e54e 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -16,6 +16,9 @@
package android.os;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
import junit.framework.TestCase;
import android.os.SystemProperties;
@@ -141,4 +144,48 @@
} catch (NullPointerException npe) {
}
}
+
+ @SmallTest
+ public void testCallbacks() {
+ // Latches are not really necessary, but are easy to use.
+ final CountDownLatch wait1 = new CountDownLatch(1);
+ final CountDownLatch wait2 = new CountDownLatch(1);
+
+ Runnable r1 = new Runnable() {
+ boolean done = false;
+ @Override
+ public void run() {
+ if (done) {
+ return;
+ }
+ done = true;
+
+ wait1.countDown();
+ throw new RuntimeException("test");
+ }
+ };
+
+ Runnable r2 = new Runnable() {
+ @Override
+ public void run() {
+ wait2.countDown();
+ }
+ };
+
+ SystemProperties.addChangeCallback(r1);
+ SystemProperties.addChangeCallback(r2);
+
+ SystemProperties.reportSyspropChanged();
+
+ try {
+ assertTrue(wait1.await(5, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ fail("InterruptedException");
+ }
+ try {
+ assertTrue(wait2.await(5, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ fail("InterruptedException");
+ }
+ }
}
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index fd1027c..bacddf14 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -25,56 +25,67 @@
<hidden-api-whitelisted-app package="android.car.input.service" />
<hidden-api-whitelisted-app package="android.car.usb.handler" />
<hidden-api-whitelisted-app package="android.ext.services" />
- <hidden-api-whitelisted-app package="android.ext.shared" />
+ <hidden-api-whitelisted-app package="com.android.apps.tag" />
<hidden-api-whitelisted-app package="com.android.backupconfirm" />
+ <hidden-api-whitelisted-app package="com.android.basicsmsreceiver" />
<hidden-api-whitelisted-app package="com.android.bluetooth" />
<hidden-api-whitelisted-app package="com.android.bluetoothdebug" />
<hidden-api-whitelisted-app package="com.android.bluetoothmidiservice" />
+ <hidden-api-whitelisted-app package="com.android.bookmarkprovider" />
<hidden-api-whitelisted-app package="com.android.calllogbackup" />
+ <hidden-api-whitelisted-app package="com.android.camera" />
<hidden-api-whitelisted-app package="com.android.captiveportallogin" />
<hidden-api-whitelisted-app package="com.android.car" />
+ <hidden-api-whitelisted-app package="com.android.car.dialer" />
<hidden-api-whitelisted-app package="com.android.car.hvac" />
<hidden-api-whitelisted-app package="com.android.car.mapsplaceholder" />
<hidden-api-whitelisted-app package="com.android.car.media" />
<hidden-api-whitelisted-app package="com.android.car.media.localmediaplayer" />
+ <hidden-api-whitelisted-app package="com.android.car.messenger" />
+ <hidden-api-whitelisted-app package="com.android.car.overview" />
<hidden-api-whitelisted-app package="com.android.car.radio" />
<hidden-api-whitelisted-app package="com.android.car.settings" />
+ <hidden-api-whitelisted-app package="com.android.car.stream" />
<hidden-api-whitelisted-app package="com.android.car.systemupdater" />
<hidden-api-whitelisted-app package="com.android.car.trust" />
<hidden-api-whitelisted-app package="com.android.carrierconfig" />
<hidden-api-whitelisted-app package="com.android.carrierdefaultapp" />
<hidden-api-whitelisted-app package="com.android.cellbroadcastreceiver" />
<hidden-api-whitelisted-app package="com.android.certinstaller" />
+ <hidden-api-whitelisted-app package="com.android.companiondevicemanager" />
<hidden-api-whitelisted-app package="com.android.customlocale2" />
<hidden-api-whitelisted-app package="com.android.defcontainer" />
<hidden-api-whitelisted-app package="com.android.documentsui" />
+ <hidden-api-whitelisted-app package="com.android.dreams.basic" />
<hidden-api-whitelisted-app package="com.android.egg" />
- <hidden-api-whitelisted-app package="com.android.email.policy" />
<hidden-api-whitelisted-app package="com.android.emergency" />
<hidden-api-whitelisted-app package="com.android.externalstorage" />
<hidden-api-whitelisted-app package="com.android.fakeoemfeatures" />
<hidden-api-whitelisted-app package="com.android.gallery" />
<hidden-api-whitelisted-app package="com.android.hotspot2" />
- <hidden-api-whitelisted-app package="com.android.inputdevices" />
<hidden-api-whitelisted-app package="com.android.keychain" />
<hidden-api-whitelisted-app package="com.android.location.fused" />
<hidden-api-whitelisted-app package="com.android.managedprovisioning" />
<hidden-api-whitelisted-app package="com.android.mms.service" />
<hidden-api-whitelisted-app package="com.android.mtp" />
+ <hidden-api-whitelisted-app package="com.android.musicfx" />
<hidden-api-whitelisted-app package="com.android.nfc" />
<hidden-api-whitelisted-app package="com.android.osu" />
<hidden-api-whitelisted-app package="com.android.packageinstaller" />
<hidden-api-whitelisted-app package="com.android.pacprocessor" />
<hidden-api-whitelisted-app package="com.android.phone" />
<hidden-api-whitelisted-app package="com.android.pmc" />
+ <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
<hidden-api-whitelisted-app package="com.android.printspooler" />
<hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
+ <hidden-api-whitelisted-app package="com.android.providers.calendar" />
<hidden-api-whitelisted-app package="com.android.providers.contacts" />
<hidden-api-whitelisted-app package="com.android.providers.downloads" />
<hidden-api-whitelisted-app package="com.android.providers.downloads.ui" />
<hidden-api-whitelisted-app package="com.android.providers.media" />
<hidden-api-whitelisted-app package="com.android.providers.settings" />
<hidden-api-whitelisted-app package="com.android.providers.telephony" />
+ <hidden-api-whitelisted-app package="com.android.providers.tv" />
<hidden-api-whitelisted-app package="com.android.providers.userdictionary" />
<hidden-api-whitelisted-app package="com.android.provision" />
<hidden-api-whitelisted-app package="com.android.proxyhandler" />
@@ -86,10 +97,15 @@
<hidden-api-whitelisted-app package="com.android.settings" />
<hidden-api-whitelisted-app package="com.android.sharedstoragebackup" />
<hidden-api-whitelisted-app package="com.android.shell" />
+ <hidden-api-whitelisted-app package="com.android.smspush" />
+ <hidden-api-whitelisted-app package="com.android.spare_parts" />
+ <hidden-api-whitelisted-app package="com.android.statementservice" />
<hidden-api-whitelisted-app package="com.android.stk" />
+ <hidden-api-whitelisted-app package="com.android.storagemanager" />
<hidden-api-whitelisted-app package="com.android.support.car.lenspicker" />
<hidden-api-whitelisted-app package="com.android.systemui" />
- <hidden-api-whitelisted-app package="com.android.systemui.theme.dark" />
+ <hidden-api-whitelisted-app package="com.android.systemui.plugins" />
+ <hidden-api-whitelisted-app package="com.android.terminal" />
<hidden-api-whitelisted-app package="com.android.timezone.updater" />
<hidden-api-whitelisted-app package="com.android.traceur" />
<hidden-api-whitelisted-app package="com.android.tv.settings" />
@@ -98,5 +114,5 @@
<hidden-api-whitelisted-app package="com.android.wallpaperbackup" />
<hidden-api-whitelisted-app package="com.android.wallpapercropper" />
<hidden-api-whitelisted-app package="com.googlecode.android_scripting" />
+ <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
</config>
-
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 52b4c0a..9845c51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -174,6 +174,7 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
+ if (mController == null) return;
final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
final boolean newValue = zen != ZEN_MODE_OFF;
final boolean valueChanged = state.value != newValue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index b22ce18..0adb439 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -64,6 +64,7 @@
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .setUids(null)
.build();
private static final int NO_NETWORK = -1;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index 7ca9d73..f76de5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -19,11 +19,15 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -32,6 +36,9 @@
import android.content.pm.StringParceledListSlice;
import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.os.UserManager;
import android.security.IKeyChainService;
import android.support.test.runner.AndroidJUnit4;
@@ -61,6 +68,7 @@
private final UserManager mUserManager = mock(UserManager.class);
private SecurityControllerImpl mSecurityController;
private CountDownLatch mStateChangedLatch;
+ private ConnectivityManager mConnectivityManager = mock(ConnectivityManager.class);
// implementing SecurityControllerCallback
@Override
@@ -72,7 +80,7 @@
public void setUp() throws Exception {
mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
mContext.addMockSystemService(Context.USER_SERVICE, mUserManager);
- mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mock(ConnectivityManager.class));
+ mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mConnectivityManager);
Intent intent = new Intent(IKeyChainService.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
@@ -176,4 +184,12 @@
//assertTrue(mStateChangedLatch.await(31, TimeUnit.SECONDS));
//assertFalse(mSecurityController.hasCACertInCurrentUser());
}
+
+ @Test
+ public void testNetworkRequest() {
+ verify(mConnectivityManager, times(1)).registerNetworkCallback(argThat(
+ (NetworkRequest request) -> request.networkCapabilities.getUids() == null
+ && request.networkCapabilities.getCapabilities().length == 0
+ ), any(NetworkCallback.class));
+ }
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 029dc7b..6494a81d 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -60,6 +60,7 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
+import android.util.StatsLog;
import com.android.internal.R;
import com.android.internal.util.DumpUtils;
@@ -632,23 +633,14 @@
if (DBG) {
Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
}
- if (isBleAppPresent()) {
- // Nothing to do, another app is here.
- return;
- }
- if (DBG) {
- Slog.d(TAG, "Disabling LE only mode after application crash");
- }
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
- mEnable = false;
- mBluetooth.onBrEdrDown();
+
+ for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
+ IBinder token = entry.getKey();
+ ClientDeathRecipient deathRec = entry.getValue();
+ if (deathRec.equals(this)) {
+ updateBleAppCount(token, false, mPackageName);
+ break;
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onBrEdrDown", e);
- } finally {
- mBluetoothLock.readLock().unlock();
}
}
@@ -2154,6 +2146,11 @@
mActiveLogs.add(
new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
}
+
+ int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
+ StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
+ StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
+ Binder.getCallingUid(), null, state, reason, packageName);
}
private void addCrashLog() {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6c24e94..ae7ac8f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1356,6 +1356,12 @@
}
}
+ private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
+ if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
+ nc.addCapability(NET_CAPABILITY_FOREGROUND);
+ }
+ }
+
@Override
public NetworkState[] getAllNetworkState() {
// Require internal since we're handing out IMSI details
@@ -4365,15 +4371,13 @@
NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
restrictRequestUidsForCaller(nc);
- if (!ConnectivityManager.checkChangePermission(mContext)) {
- // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
- // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
- // onLost and onAvailable callbacks when networks move in and out of the background.
- // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
- // can't request networks.
- nc.addCapability(NET_CAPABILITY_FOREGROUND);
- }
- ensureValidNetworkSpecifier(networkCapabilities);
+ // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
+ // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
+ // onLost and onAvailable callbacks when networks move in and out of the background.
+ // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
+ // can't request networks.
+ restrictBackgroundRequestForCaller(nc);
+ ensureValidNetworkSpecifier(nc);
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
@@ -4531,17 +4535,17 @@
return nai.network.netId;
}
- private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
+ private void handleRegisterNetworkAgent(NetworkAgentInfo nai) {
if (VDBG) log("Got NetworkAgent Messenger");
- mNetworkAgentInfos.put(na.messenger, na);
+ mNetworkAgentInfos.put(nai.messenger, nai);
synchronized (mNetworkForNetId) {
- mNetworkForNetId.put(na.network.netId, na);
+ mNetworkForNetId.put(nai.network.netId, nai);
}
- na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
- NetworkInfo networkInfo = na.networkInfo;
- na.networkInfo = null;
- updateNetworkInfo(na, networkInfo);
- updateUids(na, null, na.networkCapabilities);
+ nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
+ NetworkInfo networkInfo = nai.networkInfo;
+ nai.networkInfo = null;
+ updateNetworkInfo(nai, networkInfo);
+ updateUids(nai, null, nai.networkCapabilities);
}
private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
@@ -5268,7 +5272,6 @@
for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
final String stackedIface = stacked.getInterfaceName();
bs.noteNetworkInterfaceType(stackedIface, type);
- NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
}
} catch (RemoteException ignored) {
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 45a4dfb9..d09a161 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -36,6 +36,7 @@
import android.net.IpSecTransformResponse;
import android.net.IpSecTunnelInterfaceResponse;
import android.net.IpSecUdpEncapResponse;
+import android.net.LinkAddress;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.TrafficStats;
@@ -618,10 +619,8 @@
spi,
mConfig.getMarkValue(),
mConfig.getMarkMask());
- } catch (ServiceSpecificException e) {
- // FIXME: get the error code and throw is at an IOException from Errno Exception
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to delete SA with ID: " + mResourceId);
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
}
getResourceTracker().give();
@@ -677,14 +676,14 @@
@Override
public void freeUnderlyingResources() {
try {
- mSrvConfig
- .getNetdInstance()
- .ipSecDeleteSecurityAssociation(
- mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
- } catch (ServiceSpecificException e) {
- // FIXME: get the error code and throw is at an IOException from Errno Exception
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId);
+ if (!mOwnedByTransform) {
+ mSrvConfig
+ .getNetdInstance()
+ .ipSecDeleteSecurityAssociation(
+ mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
+ }
+ } catch (ServiceSpecificException | RemoteException e) {
+ Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
}
mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -829,15 +828,13 @@
0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff);
}
}
- } catch (ServiceSpecificException e) {
- // FIXME: get the error code and throw is at an IOException from Errno Exception
- } catch (RemoteException e) {
+ } catch (ServiceSpecificException | RemoteException e) {
Log.e(
TAG,
"Failed to delete VTI with interface name: "
+ mInterfaceName
+ " and id: "
- + mResourceId);
+ + mResourceId, e);
}
getResourceTracker().give();
@@ -1319,7 +1316,9 @@
* from multiple local IP addresses over the same tunnel.
*/
@Override
- public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) {
+ public synchronized void addAddressToTunnelInterface(
+ int tunnelResourceId, LinkAddress localAddr) {
+ enforceNetworkStackPermission();
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1327,8 +1326,21 @@
TunnelInterfaceRecord tunnelInterfaceInfo =
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
- // TODO: Add calls to netd:
- // Add address to TunnelInterface
+ try {
+ // We can assume general validity of the IP address, since we get them as a
+ // LinkAddress, which does some validation.
+ mSrvConfig
+ .getNetdInstance()
+ .interfaceAddAddress(
+ tunnelInterfaceInfo.mInterfaceName,
+ localAddr.getAddress().getHostAddress(),
+ localAddr.getPrefixLength());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw.
+ throw new IllegalArgumentException(e);
+ }
}
/**
@@ -1337,7 +1349,8 @@
*/
@Override
public synchronized void removeAddressFromTunnelInterface(
- int tunnelResourceId, String localAddr) {
+ int tunnelResourceId, LinkAddress localAddr) {
+ enforceNetworkStackPermission();
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1345,8 +1358,21 @@
TunnelInterfaceRecord tunnelInterfaceInfo =
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
- // TODO: Add calls to netd:
- // Remove address from TunnelInterface
+ try {
+ // We can assume general validity of the IP address, since we get them as a
+ // LinkAddress, which does some validation.
+ mSrvConfig
+ .getNetdInstance()
+ .interfaceDelAddress(
+ tunnelInterfaceInfo.mInterfaceName,
+ localAddr.getAddress().getHostAddress(),
+ localAddr.getPrefixLength());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw.
+ throw new IllegalArgumentException(e);
+ }
}
/**
@@ -1467,6 +1493,13 @@
IpSecAlgorithm crypt = c.getEncryption();
IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
+ String cryptName;
+ if (crypt == null) {
+ cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : "";
+ } else {
+ cryptName = crypt.getName();
+ }
+
mSrvConfig
.getNetdInstance()
.ipSecAddSecurityAssociation(
@@ -1481,7 +1514,7 @@
(auth != null) ? auth.getName() : "",
(auth != null) ? auth.getKey() : new byte[] {},
(auth != null) ? auth.getTruncationLengthBits() : 0,
- (crypt != null) ? crypt.getName() : "",
+ cryptName,
(crypt != null) ? crypt.getKey() : new byte[] {},
(crypt != null) ? crypt.getTruncationLengthBits() : 0,
(authCrypt != null) ? authCrypt.getName() : "",
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 88ae224..5d719ad 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1867,10 +1867,10 @@
}
@Override
- public NetworkStats getNetworkStatsUidDetail(int uid) {
+ public NetworkStats getNetworkStatsUidDetail(int uid, String[] ifaces) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
+ return mStatsFactory.readNetworkStatsDetail(uid, ifaces, TAG_ALL, null);
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -1942,13 +1942,13 @@
@Override
public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains,
- int[] params, boolean useTls, String tlsHostname) {
+ int[] params, String tlsHostname, String[] tlsServers) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
final String[] tlsFingerprints = new String[0];
try {
mNetdService.setResolverConfiguration(
- netId, servers, domains, params, useTls, tlsHostname, tlsFingerprints);
+ netId, servers, domains, params, tlsHostname, tlsServers, tlsFingerprints);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 3927ebd..539c001 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -65,7 +65,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
@@ -90,6 +89,8 @@
private static final boolean VDBG = false; // STOPSHIP if true
private static class Record {
+ Context context;
+
String callingPackage;
IBinder binder;
@@ -108,8 +109,6 @@
int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
- boolean canReadPhoneState;
-
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
}
@@ -118,6 +117,15 @@
return (onSubscriptionsChangedListenerCallback != null);
}
+ boolean canReadPhoneState() {
+ try {
+ return TelephonyPermissions.checkReadPhoneState(
+ context, subId, callerPid, callerUid, callingPackage, "listen");
+ } catch (SecurityException e) {
+ return false;
+ }
+ }
+
@Override
public String toString() {
return "{callingPackage=" + callingPackage + " binder=" + binder
@@ -125,8 +133,7 @@
+ " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
- + " events=" + Integer.toHexString(events)
- + " canReadPhoneState=" + canReadPhoneState + "}";
+ + " events=" + Integer.toHexString(events) + "}";
}
}
@@ -164,14 +171,9 @@
private int[] mDataActivity;
+ // Connection state of default APN type data (i.e. internet) of phones
private int[] mDataConnectionState;
- private ArrayList<String>[] mConnectedApns;
-
- private LinkProperties[] mDataConnectionLinkProperties;
-
- private NetworkCapabilities[] mDataConnectionNetworkCapabilities;
-
private Bundle[] mCellLocation;
private int[] mDataConnectionNetworkType;
@@ -212,11 +214,6 @@
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
PhoneStateListener.LISTEN_VOLTE_STATE;
- static final int CHECK_PHONE_STATE_PERMISSION_MASK =
- PhoneStateListener.LISTEN_CALL_STATE |
- PhoneStateListener.LISTEN_DATA_ACTIVITY |
- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
-
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
@@ -323,9 +320,8 @@
mBatteryStats = BatteryStatsService.getService();
int numPhones = TelephonyManager.getDefault().getPhoneCount();
- if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
+ if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones);
mNumPhones = numPhones;
- mConnectedApns = new ArrayList[numPhones];
mCallState = new int[numPhones];
mDataActivity = new int[numPhones];
mDataConnectionState = new int[numPhones];
@@ -339,8 +335,6 @@
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
mCellLocation = new Bundle[numPhones];
- mDataConnectionLinkProperties = new LinkProperties[numPhones];
- mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
mCellInfo = new ArrayList<List<CellInfo>>();
mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
for (int i = 0; i < numPhones; i++) {
@@ -358,7 +352,6 @@
mCellLocation[i] = new Bundle();
mCellInfo.add(i, null);
mPhysicalChannelConfigs.add(i, null);
- mConnectedApns[i] = new ArrayList<String>();
}
// Note that location can be null for non-phone builds like
@@ -386,20 +379,13 @@
public void addOnSubscriptionsChangedListener(String callingPackage,
IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
- mContext.getSystemService(AppOpsManager.class)
- .checkPackage(Binder.getCallingUid(), callingPackage);
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (VDBG) {
log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
+ " callerUserId=" + callerUserId + " callback=" + callback
+ " callback.asBinder=" + callback.asBinder());
}
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, "addOnSubscriptionsChangedListener")) {
- return;
- }
-
-
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
@@ -409,12 +395,12 @@
return;
}
+ r.context = mContext;
r.onSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
- r.canReadPhoneState = true; // permission has been enforced above
if (DBG) {
log("listen oscl: Register r=" + r);
}
@@ -483,8 +469,7 @@
private void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
- mContext.getSystemService(AppOpsManager.class)
- .checkPackage(Binder.getCallingUid(), callingPackage);
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (VDBG) {
log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
+ " notifyNow=" + notifyNow + " subId=" + subId + " myUserId="
@@ -495,7 +480,7 @@
// Checks permission and throws SecurityException for disallowed operations. For pre-M
// apps whose runtime permission has been revoked, we return immediately to skip sending
// events to the app without crashing it.
- if (!checkListenerPermission(events, callingPackage, "listen")) {
+ if (!checkListenerPermission(events, subId, callingPackage, "listen")) {
return;
}
@@ -509,14 +494,11 @@
return;
}
+ r.context = mContext;
r.callback = callback;
r.callingPackage = callingPackage;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
- boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
- | ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
- r.canReadPhoneState =
- isPhoneStateEvent && canReadPhoneState(callingPackage, "listen");
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
// force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -684,18 +666,9 @@
}
}
- private boolean canReadPhoneState(String callingPackage, String message) {
- try {
- return TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, message);
- } catch (SecurityException e) {
- return false;
- }
- }
-
private String getCallIncomingNumber(Record record, int phoneId) {
- // Hide the number if record's process has no READ_PHONE_STATE permission
- return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
+ // Hide the number if record's process can't currently read phone state.
+ return record.canReadPhoneState() ? mCallIncomingNumber[phoneId] : "";
}
private Record add(IBinder binder) {
@@ -770,7 +743,7 @@
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
(r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try {
- String incomingNumberOrEmpty = r.canReadPhoneState ? incomingNumber : "";
+ String incomingNumberOrEmpty = r.canReadPhoneState() ? incomingNumber : "";
r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -1216,36 +1189,12 @@
int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- boolean modified = false;
- if (state == TelephonyManager.DATA_CONNECTED) {
- if (!mConnectedApns[phoneId].contains(apnType)) {
- mConnectedApns[phoneId].add(apnType);
- if (mDataConnectionState[phoneId] != state) {
- mDataConnectionState[phoneId] = state;
- modified = true;
- }
- }
- } else {
- if (mConnectedApns[phoneId].remove(apnType)) {
- if (mConnectedApns[phoneId].isEmpty()) {
- mDataConnectionState[phoneId] = state;
- modified = true;
- } else {
- // leave mDataConnectionState as is and
- // send out the new status for the APN in question.
- }
- }
- }
- mDataConnectionLinkProperties[phoneId] = linkProperties;
- mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
- if (mDataConnectionNetworkType[phoneId] != networkType) {
- mDataConnectionNetworkType[phoneId] = networkType;
- // need to tell registered listeners about the new network type
- modified = true;
- }
- if (modified) {
- String str = "onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
- + ", " + mDataConnectionNetworkType[phoneId] + ")";
+ // We only call the callback when the change is for default APN type.
+ if (PhoneConstants.APN_TYPE_DEFAULT.equals(apnType)
+ && (mDataConnectionState[phoneId] != state
+ || mDataConnectionNetworkType[phoneId] != networkType)) {
+ String str = "onDataConnectionStateChanged(" + state
+ + ", " + networkType + ")";
log(str);
mLocalLog.log(str);
for (Record r : mRecords) {
@@ -1256,15 +1205,16 @@
if (DBG) {
log("Notify data connection state changed on sub: " + subId);
}
- r.callback.onDataConnectionStateChanged(
- mDataConnectionState[phoneId],
- mDataConnectionNetworkType[phoneId]);
+ r.callback.onDataConnectionStateChanged(state, networkType);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
}
handleRemoveListLocked();
+
+ mDataConnectionState[phoneId] = state;
+ mDataConnectionNetworkType[phoneId] = networkType;
}
mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
apnType, apn, reason, linkProperties, "");
@@ -1500,14 +1450,10 @@
pw.println("mCallForwarding=" + mCallForwarding[i]);
pw.println("mDataActivity=" + mDataActivity[i]);
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
- pw.println("mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
- pw.println("mDataConnectionNetworkCapabilities=" +
- mDataConnectionNetworkCapabilities[i]);
pw.println("mCellLocation=" + mCellLocation[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.decreaseIndent();
}
- pw.println("mConnectedApns=" + Arrays.toString(mConnectedApns));
pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
pw.println("mPreciseCallState=" + mPreciseCallState);
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
@@ -1724,7 +1670,8 @@
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(int events, String callingPackage, String message) {
+ private boolean checkListenerPermission(
+ int events, int subId, String callingPackage, String message) {
if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
@@ -1736,7 +1683,7 @@
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, message)) {
+ mContext, subId, callingPackage, message)) {
return false;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c60b74..4f24d9f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -257,6 +257,7 @@
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy;
import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageManager;
@@ -3944,12 +3945,14 @@
runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
}
- if (!app.info.isAllowedToUseHiddenApi() &&
- !disableHiddenApiChecks &&
- !mHiddenApiBlacklist.isDisabled()) {
- // This app is not allowed to use undocumented and private APIs, or blacklisting is
- // enabled. Set up its runtime with the appropriate flag.
- runtimeFlags |= Zygote.ENABLE_HIDDEN_API_CHECKS;
+ if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
+ @HiddenApiEnforcementPolicy int policy =
+ app.info.getHiddenApiEnforcementPolicy();
+ int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
+ if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
+ throw new IllegalStateException("Invalid API policy: " + policy);
+ }
+ runtimeFlags |= policyBits;
}
String invokeWith = null;
@@ -5678,15 +5681,16 @@
* since it's the system_server that creates trace files for most ANRs.
*/
private static void maybePruneOldTraces(File tracesDir) {
- final long now = System.currentTimeMillis();
- final File[] traceFiles = tracesDir.listFiles();
+ final File[] files = tracesDir.listFiles();
+ if (files == null) return;
- if (traceFiles != null) {
- for (File file : traceFiles) {
- if ((now - file.lastModified()) > DAY_IN_MILLIS) {
- if (!file.delete()) {
- Slog.w(TAG, "Unable to prune stale trace file: " + file);
- }
+ final int max = SystemProperties.getInt("tombstoned.max_anr_count", 64);
+ final long now = System.currentTimeMillis();
+ Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
+ for (int i = 0; i < files.length; ++i) {
+ if (i > max || (now - files[i].lastModified()) > DAY_IN_MILLIS) {
+ if (!files[i].delete()) {
+ Slog.w(TAG, "Unable to prune stale trace file: " + files[i]);
}
}
}
@@ -7145,6 +7149,9 @@
if (profilerInfo != null && profilerInfo.profileFd != null) {
profilerInfo.profileFd = profilerInfo.profileFd.dup();
+ if (TextUtils.equals(mProfileApp, processName) && mProfilerInfo != null) {
+ clearProfilerLocked();
+ }
}
// We deprecated Build.SERIAL and it is not accessible to
@@ -7211,7 +7218,10 @@
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
-
+ if (profilerInfo != null) {
+ profilerInfo.closeFd();
+ profilerInfo = null;
+ }
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
@@ -23603,6 +23613,14 @@
} catch (IOException e) {
}
mProfilerInfo.profileFd = null;
+
+ if (proc.pid == MY_PID) {
+ // When profiling the system server itself, avoid closing the file
+ // descriptor, as profilerControl will not create a copy.
+ // Note: it is also not correct to just set profileFd to null, as the
+ // whole ProfilerInfo instance is passed down!
+ profilerInfo = null;
+ }
} else {
stopProfilerLocked(proc, profileType);
if (profilerInfo != null && profilerInfo.profileFd != null) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9e37c78..5573cd9 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -684,6 +684,14 @@
int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
if (maxCallVolume != -1) {
MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
+ }
+
+ int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
+ if (defaultCallVolume != -1 &&
+ defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
+ defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
+ } else {
AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
(maxCallVolume * 3) / 4;
}
@@ -695,7 +703,8 @@
int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
if (defaultMusicVolume != -1 &&
- defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
+ defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
+ defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
} else {
if (isPlatformTelevision()) {
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 557828a..36f5a6c 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -192,6 +192,12 @@
public void setDnsConfigurationForNetwork(
int netId, LinkProperties lp, boolean isDefaultNetwork) {
+ final String[] assignedServers = NetworkUtils.makeStrings(lp.getDnsServers());
+ final String[] domainStrs = getDomainStrings(lp.getDomains());
+
+ updateParametersSettings();
+ final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+
// We only use the PrivateDnsConfig data pushed to this class instance
// from ConnectivityService because it works in coordination with
// NetworkMonitor to decide which networks need validation and runs the
@@ -204,23 +210,20 @@
final boolean useTls = (privateDnsCfg != null) && privateDnsCfg.useTls;
final boolean strictMode = (privateDnsCfg != null) && privateDnsCfg.inStrictMode();
final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
-
- final String[] serverStrs = NetworkUtils.makeStrings(
- strictMode ? Arrays.stream(privateDnsCfg.ips)
- .filter((ip) -> lp.isReachable(ip))
- .collect(Collectors.toList())
- : lp.getDnsServers());
- final String[] domainStrs = getDomainStrings(lp.getDomains());
-
- updateParametersSettings();
- final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+ final String[] tlsServers =
+ strictMode ? NetworkUtils.makeStrings(
+ Arrays.stream(privateDnsCfg.ips)
+ .filter((ip) -> lp.isReachable(ip))
+ .collect(Collectors.toList()))
+ : useTls ? assignedServers // Opportunistic
+ : new String[0]; // Off
Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)",
- netId, Arrays.toString(serverStrs), Arrays.toString(domainStrs),
- Arrays.toString(params), useTls, tlsHostname));
+ netId, Arrays.toString(assignedServers), Arrays.toString(domainStrs),
+ Arrays.toString(params), tlsHostname, Arrays.toString(tlsServers)));
try {
mNMS.setDnsConfigurationForNetwork(
- netId, serverStrs, domainStrs, params, useTls, tlsHostname);
+ netId, assignedServers, domainStrs, params, tlsHostname, tlsServers);
} catch (Exception e) {
Slog.e(TAG, "Error setting DNS configuration: " + e);
return;
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index e084ff8..d578e95 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.NETWORK_STACK;
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
@@ -27,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -39,6 +41,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -150,7 +154,14 @@
update(mUsers, mApps, true);
}
- private boolean hasPermission(PackageInfo app, String permission) {
+ @VisibleForTesting
+ boolean isPreinstalledSystemApp(PackageInfo app) {
+ int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
+ return (flags & (FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP)) != 0;
+ }
+
+ @VisibleForTesting
+ boolean hasPermission(PackageInfo app, String permission) {
if (app.requestedPermissions != null) {
for (String p : app.requestedPermissions) {
if (permission.equals(p)) {
@@ -166,14 +177,40 @@
}
private boolean hasRestrictedNetworkPermission(PackageInfo app) {
- int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
- if ((flags & FLAG_SYSTEM) != 0 || (flags & FLAG_UPDATED_SYSTEM_APP) != 0) {
- return true;
- }
+ if (isPreinstalledSystemApp(app)) return true;
return hasPermission(app, CONNECTIVITY_INTERNAL)
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
}
+ private boolean hasUseBackgroundNetworksPermission(PackageInfo app) {
+ // This function defines what it means to hold the permission to use
+ // background networks.
+ return hasPermission(app, CHANGE_NETWORK_STATE)
+ || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)
+ || hasPermission(app, CONNECTIVITY_INTERNAL)
+ || hasPermission(app, NETWORK_STACK)
+ // TODO : remove this check (b/31479477). Not all preinstalled apps should
+ // have access to background networks, they should just request the appropriate
+ // permission for their use case from the list above.
+ || isPreinstalledSystemApp(app);
+ }
+
+ public boolean hasUseBackgroundNetworksPermission(int uid) {
+ final String[] names = mPackageManager.getPackagesForUid(uid);
+ if (null == names || names.length == 0) return false;
+ try {
+ // Only using the first package name. There may be multiple names if multiple
+ // apps share the same UID, but in that case they also share permissions so
+ // querying with any of the names will return the same results.
+ final PackageInfo app = mPackageManager.getPackageInfo(names[0], GET_PERMISSIONS);
+ return hasUseBackgroundNetworksPermission(app);
+ } catch (NameNotFoundException e) {
+ // App not found.
+ loge("NameNotFoundException " + names[0], e);
+ return false;
+ }
+ }
+
private int[] toIntArray(List<Integer> list) {
int[] array = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
@@ -308,4 +345,8 @@
private static void loge(String s) {
Log.e(TAG, s);
}
+
+ private static void loge(String s, Throwable e) {
+ Log.e(TAG, s, e);
+ }
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 8298127..e0a8643 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -27,6 +27,7 @@
import static android.net.ConnectivityManager.isNetworkTypeMobile;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkStats.SET_ALL;
@@ -34,6 +35,7 @@
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.STATS_PER_IFACE;
import static android.net.NetworkStats.STATS_PER_UID;
+import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
@@ -128,6 +130,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -143,6 +146,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
/**
* Collect and persist detailed network statistics, and provide this data to
@@ -726,7 +730,8 @@
final long token = Binder.clearCallingIdentity();
final NetworkStats networkLayer;
try {
- networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
+ networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid,
+ NetworkStats.INTERFACES_ALL);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -748,6 +753,18 @@
}
@Override
+ public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+ try {
+ final String[] ifacesToQuery =
+ NetworkStatsFactory.augmentWithStackedInterfacesLocked(requiredIfaces);
+ return getNetworkStatsUidDetail(ifacesToQuery);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error compiling UID stats", e);
+ return new NetworkStats(0L, 0);
+ }
+ }
+
+ @Override
public String[] getMobileIfaces() {
return mMobileIfaces;
}
@@ -1109,6 +1126,8 @@
if (isMobile) {
mobileIfaces.add(stackedIface);
}
+
+ NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
}
}
}
@@ -1130,7 +1149,7 @@
private void recordSnapshotLocked(long currentTime) throws RemoteException {
// snapshot and record current counters; read UID stats first to
// avoid over counting dev stats.
- final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
+ final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
final NetworkStats xtSnapshot = getNetworkStatsXt();
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
@@ -1464,12 +1483,19 @@
* Return snapshot of current UID statistics, including any
* {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
* values.
+ *
+ * @param ifaces A list of interfaces the stats should be restricted to, or
+ * {@link NetworkStats#INTERFACES_ALL}.
*/
- private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
- final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
+ throws RemoteException {
+
+ final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL,
+ ifaces);
// fold tethering stats and operations into uid snapshot
final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
+ tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
uidSnapshot.combineAllValues(tetherSnapshot);
final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
@@ -1478,10 +1504,14 @@
// fold video calling data usage stats into uid snapshot
final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
if (vtStats != null) {
+ vtStats.filter(UID_ALL, ifaces, TAG_ALL);
uidSnapshot.combineAllValues(vtStats);
}
+
uidSnapshot.combineAllValues(mUidOperations);
+ // TODO: apply tethering & VC 464xlat adjustments here
+
return uidSnapshot;
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 5ea778b..ae48844 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -47,6 +47,8 @@
import dalvik.system.DexFile;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+
import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
import static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED;
@@ -532,7 +534,10 @@
int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
- int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+ // TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
+ int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+ ? 0
+ : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
// Avoid generating CompactDex for modes that are latency critical.
final int compilationReason = options.getCompilationReason();
boolean generateCompactDex = true;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2579e56..0971058 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -992,7 +992,7 @@
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.POLICY_CONTROL), false, this,
UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.Global.getUriFor(
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
UserHandle.USER_ALL);
updateSettings();
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 73243d2..1c0e260 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -881,7 +881,7 @@
*/
@IntDef(prefix = { "HANDOVER_" },
value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
- HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+ HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
HANDOVER_FAILURE_UNKNOWN})
@Retention(RetentionPolicy.SOURCE)
public @interface HandoverFailureErrors {}
@@ -939,7 +939,7 @@
* For more information on call handovers, see
* {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
+ public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
/**
* Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4b1f0ad..05a3020 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1257,7 +1257,7 @@
* @hide
*/
@SystemApi
- public int getCallState() {
+ public @TelephonyManager.CallState int getCallState() {
try {
if (isServiceConnected()) {
return getTelecomService().getCallState();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index fa07777..cc3cd4d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1926,7 +1926,7 @@
sDefaults.putBoolean(KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL, false);
- sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false);
+ sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
@@ -2209,7 +2209,9 @@
/**
* Gets the configuration values for a particular subscription, which is associated with a
* specific SIM card. If an invalid subId is used, the returned config will contain default
- * values.
+ * values. After using this method to get the configuration bundle,
+ * {@link #isConfigForIdentifiedCarrier(PersistableBundle)} should be called to confirm whether
+ * any carrier specific configuration has been applied.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -2236,7 +2238,9 @@
}
/**
- * Gets the configuration values for the default subscription.
+ * Gets the configuration values for the default subscription. After using this method to get
+ * the configuration bundle, {@link #isConfigForIdentifiedCarrier(PersistableBundle)} should be
+ * called to confirm whether any carrier specific configuration has been applied.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -2265,6 +2269,9 @@
* <p>
* After using {@link #getConfig()} or {@link #getConfigForSubId(int)} an app should always
* use this method to confirm whether any carrier specific configuration has been applied.
+ * Especially when an app misses the broadcast {@link #ACTION_CARRIER_CONFIG_CHANGED} but it
+ * still needs to get the current configuration, it must use this method to verify whether the
+ * configuration is default or carrier overridden.
* </p>
*
* @param bundle the configuration bundle to be checked.
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 105ddb0..713ac00 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -181,6 +182,7 @@
* @return The long alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaLong() {
return mAlphaLong;
}
@@ -189,6 +191,7 @@
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaShort() {
return mAlphaShort;
}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 52944a8..aae7929 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -191,6 +192,7 @@
* @return The long alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaLong() {
return mAlphaLong;
}
@@ -199,6 +201,7 @@
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaShort() {
return mAlphaShort;
}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 37fb075..9b3ef56 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -201,6 +202,7 @@
* @return The long alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaLong() {
return mAlphaLong;
}
@@ -209,6 +211,7 @@
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaShort() {
return mAlphaShort;
}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 992545d..7475c74 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -34,6 +35,10 @@
private final int mCid;
// 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
private final int mCpid;
+ // long alpha Operator Name String or Enhanced Operator Name String
+ private final String mAlphaLong;
+ // short alpha Operator Name String or Enhanced Operator Name String
+ private final String mAlphaShort;
/**
* @hide
@@ -43,6 +48,8 @@
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mCpid = Integer.MAX_VALUE;
+ mAlphaLong = null;
+ mAlphaShort = null;
}
/**
@@ -55,7 +62,7 @@
* @hide
*/
public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
- this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid);
+ this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, null, null);
}
/**
@@ -65,6 +72,7 @@
* @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
* @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
*
+ * FIXME: This is a temporary constructor to facilitate migration.
* @hide
*/
public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
@@ -72,10 +80,34 @@
mLac = lac;
mCid = cid;
mCpid = cpid;
+ mAlphaLong = null;
+ mAlphaShort = null;
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code in string format
+ * @param mnc 2 or 3-digit Mobile Network Code in string format
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ * @param alphal long alpha Operator Name String or Enhanced Operator Name String
+ * @param alphas short alpha Operator Name String or Enhanced Operator Name String
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid,
+ String alphal, String alphas) {
+ super(TAG, TYPE_TDSCDMA, mcc, mnc);
+ mLac = lac;
+ mCid = cid;
+ mCpid = cpid;
+ mAlphaLong = alphal;
+ mAlphaShort = alphas;
}
private CellIdentityTdscdma(CellIdentityTdscdma cid) {
- this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, cid.mCpid);
+ this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid,
+ cid.mCpid, cid.mAlphaLong, cid.mAlphaShort);
}
CellIdentityTdscdma copy() {
@@ -119,9 +151,31 @@
return mCpid;
}
+ /**
+ * @return The long alpha tag associated with the current scan result (may be the operator
+ * name string or extended operator name string). May be null if unknown.
+ *
+ * @hide
+ */
+ @Nullable
+ public CharSequence getOperatorAlphaLong() {
+ return mAlphaLong;
+ }
+
+ /**
+ * @return The short alpha tag associated with the current scan result (may be the operator
+ * name string or extended operator name string). May be null if unknown.
+ *
+ * @hide
+ */
+ @Nullable
+ public CharSequence getOperatorAlphaShort() {
+ return mAlphaShort;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(mMccStr, mMncStr, mLac, mCid, mCpid);
+ return Objects.hash(mMccStr, mMncStr, mLac, mCid, mCpid, mAlphaLong, mAlphaShort);
}
@Override
@@ -139,7 +193,9 @@
&& TextUtils.equals(mMncStr, o.mMncStr)
&& mLac == o.mLac
&& mCid == o.mCid
- && mCpid == o.mCpid;
+ && mCpid == o.mCpid
+ && mAlphaLong == o.mAlphaLong
+ && mAlphaShort == o.mAlphaShort;
}
@Override
@@ -150,6 +206,8 @@
.append(" mLac=").append(mLac)
.append(" mCid=").append(mCid)
.append(" mCpid=").append(mCpid)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
.append("}").toString();
}
@@ -161,6 +219,8 @@
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mCpid);
+ dest.writeString(mAlphaLong);
+ dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
@@ -169,6 +229,8 @@
mLac = in.readInt();
mCid = in.readInt();
mCpid = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
if (DBG) log(toString());
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index affa0c1..52fa54f 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -182,6 +183,7 @@
* @return The long alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaLong() {
return mAlphaLong;
}
@@ -190,6 +192,7 @@
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
+ @Nullable
public CharSequence getOperatorAlphaShort() {
return mAlphaShort;
}
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 7f43ee5..073c313 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -115,6 +115,8 @@
telephony.stopNetworkScan(mSubId, mScanId);
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
+ } catch (RuntimeException ex) {
+ Rlog.e(TAG, "stopNetworkScan RuntimeException", ex);
}
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 0446925..7db83f6 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -20,6 +20,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.telecom.TelecomManager;
import com.android.internal.telephony.IPhoneStateListener;
@@ -61,9 +62,6 @@
/**
* Listen for changes to the network signal strength (cellular).
* {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
- * READ_PHONE_STATE}
- * <p>
*
* @see #onSignalStrengthChanged
*
@@ -76,7 +74,8 @@
* Listen for changes to the message-waiting indicator.
* {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
- * READ_PHONE_STATE}
+ * READ_PHONE_STATE} or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
* <p>
* Example: The status bar uses this to determine when to display the
* voicemail icon.
@@ -89,7 +88,9 @@
* Listen for changes to the call-forwarding indicator.
* {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
- * READ_PHONE_STATE}
+ * READ_PHONE_STATE} or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @see #onCallForwardingIndicatorChanged
*/
public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008;
@@ -428,16 +429,21 @@
/**
* Callback invoked when device call state changes.
+ * <p>
+ * Reports the state of Telephony (mobile) calls on the device.
+ * <p>
+ * Note: The state returned here may differ from that returned by
+ * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
+ * calling {@link TelephonyManager#getCallState()} from within this callback may return a
+ * different state than the callback reports.
+ *
* @param state call state
* @param phoneNumber call phone number. If application does not have
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission, an empty
- * string will be passed as an argument.
- *
- * @see TelephonyManager#CALL_STATE_IDLE
- * @see TelephonyManager#CALL_STATE_RINGING
- * @see TelephonyManager#CALL_STATE_OFFHOOK
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission or carrier
+ * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be
+ * passed as an argument.
*/
- public void onCallStateChanged(int state, String phoneNumber) {
+ public void onCallStateChanged(@TelephonyManager.CallState int state, String phoneNumber) {
// default implementation empty
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index d2e7ae5..e971d08 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -17,8 +17,8 @@
package android.telephony;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -220,7 +220,7 @@
public static final int ROAMING_TYPE_INTERNATIONAL = 3;
/**
- * Unknown ID. Could be returned by {@link #getNetworkId()} or {@link #getSystemId()}
+ * Unknown ID. Could be returned by {@link #getCdmaNetworkId()} or {@link #getCdmaSystemId()}
*/
public static final int UNKNOWN_ID = -1;
@@ -495,9 +495,8 @@
*
* @return Current serving cell bandwidths
*/
- @Nullable
public int[] getCellBandwidths() {
- return mCellBandwidths;
+ return mCellBandwidths == null ? new int[0] : mCellBandwidths;
}
/**
@@ -1220,7 +1219,8 @@
}
/** @hide */
- public void setSystemAndNetworkId(int systemId, int networkId) {
+ @TestApi
+ public void setCdmaSystemAndNetworkId(int systemId, int networkId) {
this.mSystemId = systemId;
this.mNetworkId = networkId;
}
@@ -1386,7 +1386,7 @@
* within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
* @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
*/
- public int getNetworkId() {
+ public int getCdmaNetworkId() {
return this.mNetworkId;
}
@@ -1395,7 +1395,7 @@
* system. (Defined in 3GPP2 C.S0023 3.4.8)
* @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
*/
- public int getSystemId() {
+ public int getCdmaSystemId() {
return this.mSystemId;
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index b44f830..7506f4a 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
@@ -338,16 +339,17 @@
/**
* Send a text based SMS without writing it into the SMS Provider.
*
- * <p>Requires Permission:
- * {@link android.Manifest.permission#SEND_SMS} and
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
- * privileges.
- * </p>
+ * <p>Requires Permission: Both {@link android.Manifest.permission#SEND_SMS} and
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or that the calling app has carrier
+ * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or that the calling app is
+ * the default IMS app (see
+ * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}).
*
* @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent)
* @hide
*/
@SystemApi
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
android.Manifest.permission.MODIFY_PHONE_STATE,
android.Manifest.permission.SEND_SMS
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d09d426..05b8b57 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -17,9 +17,11 @@
package android.telephony;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
@@ -47,9 +49,6 @@
/**
* SubscriptionManager is the application interface to SubscriptionController
* and provides information about the current Telephony Subscriptions.
- * <p>
- * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise
- * specified.
*/
@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
public class SubscriptionManager {
@@ -590,9 +589,15 @@
/**
* Get the active SubscriptionInfo with the input subId.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @param subId The unique SubscriptionInfo key in database.
* @return SubscriptionInfo, maybe null if its not active.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
if (!isValidSubscriptionId(subId)) {
@@ -646,9 +651,16 @@
/**
* Get the active SubscriptionInfo associated with the slotIndex
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @param slotIndex the slot which the subscription is inserted
* @return SubscriptionInfo, maybe null if its not active
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
if (!isValidSlotIndex(slotIndex)) {
@@ -700,6 +712,11 @@
* Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
+ * to the calling app are returned.
+ *
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
@@ -716,6 +733,8 @@
* </li>
* </ul>
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
List<SubscriptionInfo> result = null;
@@ -858,10 +877,18 @@
}
/**
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include
+ * only those subscriptions accessible to the caller.
+ *
* @return the current number of active subscriptions. There is no guarantee the value
* returned by this method will be the same as the length of the list returned by
* {@link #getActiveSubscriptionInfoList}.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getActiveSubscriptionInfoCount() {
int result = 0;
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index 4f78c4c..f1653ce 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -3165,8 +3165,8 @@
values.put(RIL_VOICE_RADIO_TECHNOLOGY, state.getRilVoiceRadioTechnology());
values.put(RIL_DATA_RADIO_TECHNOLOGY, state.getRilDataRadioTechnology());
values.put(CSS_INDICATOR, state.getCssIndicator());
- values.put(NETWORK_ID, state.getNetworkId());
- values.put(SYSTEM_ID, state.getSystemId());
+ values.put(NETWORK_ID, state.getCdmaNetworkId());
+ values.put(SYSTEM_ID, state.getCdmaSystemId());
values.put(CDMA_ROAMING_INDICATOR, state.getCdmaRoamingIndicator());
values.put(CDMA_DEFAULT_ROAMING_INDICATOR, state.getCdmaDefaultRoamingIndicator());
values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex());
@@ -3296,13 +3296,13 @@
public static final String CSS_INDICATOR = "css_indicator";
/**
- * This is the same as {@link ServiceState#getNetworkId()}.
+ * This is the same as {@link ServiceState#getCdmaNetworkId()}.
* @hide
*/
public static final String NETWORK_ID = "network_id";
/**
- * This is the same as {@link ServiceState#getSystemId()}.
+ * This is the same as {@link ServiceState#getCdmaSystemId()}.
* @hide
*/
public static final String SYSTEM_ID = "system_id";
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8ccabcb..fc003a6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -47,6 +48,7 @@
import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
@@ -109,6 +111,13 @@
BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY;
/**
+ * The process name of the Phone app as well as many other apps that use this process name, such
+ * as settings and vendor components.
+ * @hide
+ */
+ public static final String PHONE_PROCESS_NAME = "com.android.phone";
+
+ /**
* The allowed states of Wi-Fi calling.
*
* @hide
@@ -1081,7 +1090,11 @@
* Returns the software version number for the device, for example,
* the IMEI/SV for GSM phones. Return null if the software version is
* not available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceSoftwareVersion() {
return getDeviceSoftwareVersion(getSlotIndex());
@@ -1113,10 +1126,14 @@
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
* or ESN for CDMA phones. Return null if device ID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
* MEID for CDMA.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceId() {
try {
@@ -1135,12 +1152,16 @@
* Returns the unique device ID of a subscription, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which deviceID is returned
*
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
* MEID for CDMA.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceId(int slotIndex) {
// FIXME this assumes phoneId == slotIndex
@@ -1159,7 +1180,11 @@
/**
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getImei() {
return getImei(getSlotIndex());
@@ -1169,8 +1194,12 @@
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which IMEI is returned
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -1187,7 +1216,11 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getMeid() {
return getMeid(getSlotIndex());
@@ -1196,8 +1229,12 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which MEID is returned
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getMeid(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -1214,10 +1251,11 @@
/**
* Returns the Network Access Identifier (NAI). Return null if NAI is not available.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getNai() {
return getNaiBySubscriberId(getSubId());
@@ -1714,10 +1752,17 @@
* invalid subscription ID is pinned to the TelephonyManager, the returned config will contain
* default values.
*
+ * <p>This method may take several seconds to complete, so it should only be called from a
+ * worker thread.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @see CarrierConfigManager#getConfigForSubId(int)
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public PersistableBundle getCarrierConfig() {
@@ -1917,6 +1962,9 @@
* If this object has been created with {@link #createForSubscriptionId}, applies to the given
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @return the network type
*
* @see #NETWORK_TYPE_UNKNOWN
@@ -1936,6 +1984,7 @@
* @see #NETWORK_TYPE_EHRPD
* @see #NETWORK_TYPE_HSPAP
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getDataNetworkType() {
return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
@@ -1970,7 +2019,11 @@
/**
* Returns the NETWORK_TYPE_xxxx for voice
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getVoiceNetworkType() {
return getVoiceNetworkType(getSubId());
@@ -2556,7 +2609,11 @@
/**
* Returns the serial number of the SIM, if applicable. Return null if it is
* unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getSimSerialNumber() {
return getSimSerialNumber(getSubId());
@@ -2681,7 +2738,11 @@
/**
* Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
* Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getSubscriberId() {
return getSubscriberId(getSubId());
@@ -2822,7 +2883,11 @@
/**
* Returns the Group Identifier Level1 for a GSM phone.
* Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getGroupIdLevel1() {
try {
@@ -2863,9 +2928,15 @@
/**
* Returns the phone number string for line 1, for example, the MSISDN
* for a GSM phone. Return null if it is unavailable.
- * <p>
- * The default SMS app can also use this.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE},
+ * {@link android.Manifest.permission#READ_SMS READ_SMS},
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+ * that the caller is the default SMS app,
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_SMS,
@@ -2920,8 +2991,7 @@
* change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
* value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
@@ -2937,8 +3007,7 @@
* change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
* value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId the subscriber that the alphatag and dialing number belongs to.
* @param alphaTag alpha-tagging of the dailing nubmer
@@ -3057,7 +3126,11 @@
/**
* Returns the voice mail number. Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVoiceMailNumber() {
return getVoiceMailNumber(getSubId());
@@ -3118,8 +3191,7 @@
/**
* Sets the voice mail number.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param alphaTag The alpha tag to display.
* @param number The voicemail number.
@@ -3131,8 +3203,7 @@
/**
* Sets the voicemail number for the given subscriber.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param alphaTag The alpha tag to display.
@@ -3153,9 +3224,9 @@
/**
* Enables or disables the visual voicemail client for a phone account.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
- * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}), or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle the phone account to change the client state
* @param enabled the new state of the client
@@ -3218,11 +3289,15 @@
* to the TelephonyManager. Returns {@code null} when there is no package responsible for
* processing visual voicemail for the subscription.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
* @see VisualVoicemailService
*/
@Nullable
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVisualVoicemailPackageName() {
try {
@@ -3465,15 +3540,14 @@
* Sets the voice activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param activationState The voice activation state
* @see #SIM_ACTIVATION_STATE_UNKNOWN
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3486,8 +3560,8 @@
* Sets the voice activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param activationState The voice activation state of the given subscriber.
@@ -3495,7 +3569,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3513,8 +3586,8 @@
* Sets the data activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param activationState The data activation state
* @see #SIM_ACTIVATION_STATE_UNKNOWN
@@ -3522,7 +3595,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3535,8 +3607,8 @@
* Sets the data activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param activationState The data activation state of the given subscriber.
@@ -3545,7 +3617,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3563,15 +3634,14 @@
* Returns the voice activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return voiceActivationState
* @see #SIM_ACTIVATION_STATE_UNKNOWN
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3584,8 +3654,8 @@
* Returns the voice activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
*
@@ -3594,7 +3664,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3613,8 +3682,8 @@
* Returns the data activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return dataActivationState for the given subscriber
* @see #SIM_ACTIVATION_STATE_UNKNOWN
@@ -3622,7 +3691,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3635,8 +3703,8 @@
* Returns the data activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
*
@@ -3646,7 +3714,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3694,7 +3761,11 @@
/**
* Retrieves the alphabetic identifier associated with the voice
* mail number.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVoiceMailAlphaTag() {
return getVoiceMailAlphaTag(getSubId());
@@ -3723,9 +3794,8 @@
}
/**
- * Send the special dialer code. The IPC caller must be the current default dialer or has
- * carrier privileges.
- * @see #hasCarrierPrivileges
+ * Send the special dialer code. The IPC caller must be the current default dialer or have
+ * carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param inputCode The special dialer code to send
*
@@ -3816,26 +3886,45 @@
return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
}
- /** Device call state: No activity. */
+ /**
+ * Device call state: No activity.
+ */
public static final int CALL_STATE_IDLE = 0;
- /** Device call state: Ringing. A new call arrived and is
+ /**
+ * Device call state: Ringing. A new call arrived and is
* ringing or waiting. In the latter case, another call is
- * already active. */
+ * already active.
+ */
public static final int CALL_STATE_RINGING = 1;
- /** Device call state: Off-hook. At least one call exists
- * that is dialing, active, or on hold, and no calls are ringing
- * or waiting. */
+ /**
+ * Device call state: Off-hook. At least one call exists
+ * that is dialing, active, or on hold, and no calls are ringing
+ * or waiting.
+ */
public static final int CALL_STATE_OFFHOOK = 2;
+ /** @hide */
+ @IntDef(prefix = { "CALL_STATE_" }, value = {
+ CALL_STATE_IDLE,
+ CALL_STATE_RINGING,
+ CALL_STATE_OFFHOOK
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallState{}
+
/**
- * Returns one of the following constants that represents the current state of all
- * phone calls.
+ * Returns the state of all calls on the device.
+ * <p>
+ * This method considers not only calls in the Telephony stack, but also calls via other
+ * {@link android.telecom.ConnectionService} implementations.
+ * <p>
+ * Note: The call state returned via this method may differ from what is reported by
+ * {@link PhoneStateListener#onCallStateChanged(int, String)}, as that callback only considers
+ * Telephony (mobile) calls.
*
- * {@link TelephonyManager#CALL_STATE_RINGING}
- * {@link TelephonyManager#CALL_STATE_OFFHOOK}
- * {@link TelephonyManager#CALL_STATE_IDLE}
+ * @return the current call state.
*/
- public int getCallState() {
+ public @CallState int getCallState() {
try {
ITelecomService telecom = getTelecomService();
if (telecom != null) {
@@ -3848,23 +3937,31 @@
}
/**
- * Returns a constant indicating the call state (cellular) on the device
- * for a subscription.
+ * Returns the Telephony call state for calls on a specific subscription.
+ * <p>
+ * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
+ * considers the state of calls from other {@link android.telecom.ConnectionService}
+ * implementations.
*
- * @param subId whose call state is returned
+ * @param subId the subscription to check call state for.
* @hide
*/
- public int getCallState(int subId) {
+ public @CallState int getCallState(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getCallStateForSlot(phoneId);
}
/**
- * See getCallState.
+ * Returns the Telephony call state for calls on a specific SIM slot.
+ * <p>
+ * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
+ * considers the state of calls from other {@link android.telecom.ConnectionService}
+ * implementations.
*
+ * @param slotIndex the SIM slot index to check call state for.
* @hide
*/
- public int getCallStateForSlot(int slotIndex) {
+ public @CallState int getCallStateForSlot(int slotIndex) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
@@ -4253,8 +4350,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
@@ -4271,8 +4368,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
@@ -4288,8 +4385,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
@@ -4314,8 +4411,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param channel is the channel id to be closed as retruned by a successful
* iccOpenLogicalChannel.
@@ -4331,8 +4428,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param channel is the channel id to be closed as retruned by a successful
@@ -4357,8 +4454,8 @@
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param channel is the channel id to be closed as returned by a successful
* iccOpenLogicalChannel.
@@ -4384,8 +4481,8 @@
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param channel is the channel id to be closed as returned by a successful
@@ -4420,8 +4517,8 @@
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param cla Class of the APDU command.
* @param instruction Instruction of the APDU command.
@@ -4445,8 +4542,8 @@
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param cla Class of the APDU command.
@@ -4477,8 +4574,8 @@
* Returns the response APDU for a command APDU sent through SIM_IO.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param fileID
* @param command
@@ -4497,8 +4594,8 @@
* Returns the response APDU for a command APDU sent through SIM_IO.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param fileID
@@ -4526,8 +4623,8 @@
* Send ENVELOPE to the SIM and return the response.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param content String containing SAT/USAT response in hexadecimal
* format starting with command tag. See TS 102 223 for
@@ -4544,8 +4641,8 @@
* Send ENVELOPE to the SIM and return the response.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param content String containing SAT/USAT response in hexadecimal
@@ -4570,10 +4667,10 @@
/**
* Read one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param itemID the ID of the item to read.
* @return the NV item as a String, or null on any failure.
@@ -4596,10 +4693,10 @@
/**
* Write one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param itemID the ID of the item to read.
* @param itemValue the value to write, as a String.
@@ -4623,10 +4720,10 @@
/**
* Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param preferredRoamingList byte array containing the new PRL.
* @return true on success; false on any failure.
@@ -4650,10 +4747,10 @@
* Perform the specified type of NV config reset. The radio will be taken offline
* and the device must be rebooted after the operation. Used for device
* configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
* @return true on success; false on any failure.
@@ -5001,8 +5098,8 @@
* Returns the response of authentication for the default subscription.
* Returns null if the authentication hasn't been successful
*
- * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
- * permission.
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param appType the icc application type, like {@link #APPTYPE_USIM}
* @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
@@ -5010,9 +5107,10 @@
* @param data authentication challenge data, base64 encoded.
* See 3GPP TS 31.102 7.1.2 for more details.
* @return the response of authentication, or null if not available
- *
- * @see #hasCarrierPrivileges
*/
+ // TODO(b/73660190): This should probably require MODIFY_PHONE_STATE, not
+ // READ_PRIVILEGED_PHONE_STATE. It certainly shouldn't reference the permission in Javadoc since
+ // it's not public API.
public String getIccAuthentication(int appType, int authType, String data) {
return getIccAuthentication(getSubId(), appType, authType, data);
}
@@ -5021,7 +5119,7 @@
* Returns the response of USIM Authentication for specified subId.
* Returns null if the authentication hasn't been successful
*
- * <p>Requires that the calling app has carrier privileges.
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId subscription ID used for authentication
* @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -5030,8 +5128,6 @@
* @param data authentication challenge data, base64 encoded.
* See 3GPP TS 31.102 7.1.2 for more details.
* @return the response of authentication, or null if not available
- *
- * @see #hasCarrierPrivileges
* @hide
*/
public String getIccAuthentication(int subId, int appType, int authType, String data) {
@@ -5052,8 +5148,12 @@
* Returns an array of Forbidden PLMNs from the USIM App
* Returns null if the query fails.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @return an array of forbidden PLMNs or null if not available
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String[] getForbiddenPlmns() {
return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
@@ -5258,10 +5358,10 @@
/**
* Get the preferred network type.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return the preferred network type, defined in RILConstants.java.
* @hide
@@ -5281,11 +5381,12 @@
/**
* Sets the network selection mode to automatic.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setNetworkSelectionModeAutomatic() {
try {
@@ -5301,15 +5402,14 @@
}
/**
- * Perform a radio scan and return the list of avialble networks.
+ * Perform a radio scan and return the list of available networks.
*
* The return value is a list of the OperatorInfo of the networks found. Note that this
* scan can take a long time (sometimes minutes) to happen.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @hide
* TODO: Add an overload that takes no args.
@@ -5333,17 +5433,19 @@
* This method is asynchronous, so the network scan results will be returned by callback.
* The returned NetworkScan will contain a callback method which can be used to stop the scan.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
- * @see #hasCarrierPrivileges()
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
- * @param executor The executor through which the callback should be invoked.
+ * @param executor The executor through which the callback should be invoked. Since the scan
+ * request may trigger multiple callbacks and they must be invoked in the same order as
+ * they are received by the platform, the user should provide an executor which executes
+ * tasks one at a time in serial order. For example AsyncTask.SERIAL_EXECUTOR.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public NetworkScan requestNetworkScan(
NetworkScanRequest request, Executor executor,
@@ -5365,16 +5467,15 @@
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public NetworkScan requestNetworkScan(
NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
- return requestNetworkScan(request, AsyncTask.THREAD_POOL_EXECUTOR, callback);
+ return requestNetworkScan(request, AsyncTask.SERIAL_EXECUTOR, callback);
}
/**
* Ask the radio to connect to the input network and change selection mode to manual.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param operatorNumeric the PLMN ID of the network to select.
* @param persistSelection whether the selection will persist until reboot. If true, only allows
@@ -5382,6 +5483,7 @@
* normal network selection next time.
* @return true on success; false on any failure.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setNetworkSelectionModeManual(String operatorNumeric, boolean persistSelection) {
try {
@@ -5401,10 +5503,10 @@
/**
* Set the preferred network type.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId the id of the subscription to set the preferred network type for.
* @param networkType the preferred network type, defined in RILConstants.java.
@@ -5428,9 +5530,7 @@
/**
* Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
*
- * <p>
- * Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return true on success; false on any failure.
*/
@@ -5441,9 +5541,7 @@
/**
* Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
*
- * <p>
- * Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return true on success; false on any failure.
* @hide
@@ -5533,8 +5631,7 @@
* brand value input. To unset the value, the same function should be
* called with a null brand value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
@@ -5551,8 +5648,7 @@
* brand value input. To unset the value, the same function should be
* called with a null brand value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param brand The brand name to display/set.
@@ -6206,15 +6302,15 @@
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
- * calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param enable Whether to enable mobile data.
*
- * @see #hasCarrierPrivileges
* @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
setUserMobileDataEnabled(enable);
@@ -6251,7 +6347,7 @@
* <p>Requires one of the following permissions:
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
- * calling app has carrier privileges.
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* <p>Note that this does not take into account any data restrictions that may be present on the
* calling app. Such restrictions may be inspected with
@@ -6259,7 +6355,6 @@
*
* @return true if mobile data is enabled.
*
- * @see #hasCarrierPrivileges
* @deprecated use {@link #isUserMobileDataEnabled()} instead.
*/
@Deprecated
@@ -6989,7 +7084,11 @@
/**
* Returns the current {@link ServiceState} information.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
@@ -7035,14 +7134,14 @@
/**
* Sets the per-account voicemail ringtone.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
- * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}, or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
* voicemail ringtone.
* @param uri The URI for the ringtone to play when receiving a voicemail from a specific
* PhoneAccount.
- * @see #hasCarrierPrivileges
*
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
@@ -7080,14 +7179,14 @@
/**
* Sets the per-account preference whether vibration is enabled for voicemail notifications.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
- * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}, or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
* voicemail vibration setting.
* @param enabled Whether to enable or disable vibration for voicemail notifications from a
* specific PhoneAccount.
- * @see #hasCarrierPrivileges
*
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
@@ -7507,12 +7606,10 @@
* Otherwise, it applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
- * calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}.
*
* @param enable Whether to enable mobile data.
- *
- * @see #hasCarrierPrivileges
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setUserMobileDataEnabled(boolean enable) {
@@ -7530,15 +7627,13 @@
* <p>Requires one of the following permissions:
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
- * calling app has carrier privileges.
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}.
*
* <p>Note that this does not take into account any data restrictions that may be present on the
* calling app. Such restrictions may be inspected with
* {@link ConnectivityManager#getRestrictBackgroundStatus}.
*
* @return true if mobile data is enabled.
- *
- * @see #hasCarrierPrivileges
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.ACCESS_NETWORK_STATE,
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 946cecf..96ff332 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -137,22 +137,31 @@
for (int i = 0; i < parcelables.length; i++) {
ci[i] = (CellInfo) parcelables[i];
}
- executor.execute(() ->
- callback.onResults((List<CellInfo>) Arrays.asList(ci)));
+ executor.execute(() ->{
+ Rlog.d(TAG, "onResults: " + ci.toString());
+ callback.onResults((List<CellInfo>) Arrays.asList(ci));
+ });
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onResults", e);
}
break;
case CALLBACK_SCAN_ERROR:
try {
- executor.execute(() -> callback.onError(message.arg1));
+ final int errorCode = message.arg1;
+ executor.execute(() -> {
+ Rlog.d(TAG, "onError: " + errorCode);
+ callback.onError(errorCode);
+ });
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onError", e);
}
break;
case CALLBACK_SCAN_COMPLETE:
try {
- executor.execute(() -> callback.onComplete());
+ executor.execute(() -> {
+ Rlog.d(TAG, "onComplete");
+ callback.onComplete();
+ });
mScanInfo.remove(message.arg2);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 0c17147..125161d 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -60,6 +60,7 @@
private final String mCardId;
private final @CardStateInfo int mCardStateInfo;
private final int mLogicalSlotIdx;
+ private final boolean mIsExtendedApduSupported;
public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
@Override
@@ -79,6 +80,7 @@
mCardId = in.readString();
mCardStateInfo = in.readInt();
mLogicalSlotIdx = in.readInt();
+ mIsExtendedApduSupported = in.readByte() != 0;
}
@Override
@@ -88,6 +90,7 @@
dest.writeString(mCardId);
dest.writeInt(mCardStateInfo);
dest.writeInt(mLogicalSlotIdx);
+ dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
}
@Override
@@ -96,12 +99,13 @@
}
public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
- @CardStateInfo int cardStateInfo, int logicalSlotIdx) {
+ @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported) {
this.mIsActive = isActive;
this.mIsEuicc = isEuicc;
this.mCardId = cardId;
this.mCardStateInfo = cardStateInfo;
this.mLogicalSlotIdx = logicalSlotIdx;
+ this.mIsExtendedApduSupported = isExtendedApduSupported;
}
public boolean getIsActive() {
@@ -125,6 +129,13 @@
return mLogicalSlotIdx;
}
+ /**
+ * @return {@code true} if this slot supports extended APDU from ATR, {@code false} otherwise.
+ */
+ public boolean getIsExtendedApduSupported() {
+ return mIsExtendedApduSupported;
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -139,7 +150,8 @@
&& (mIsEuicc == that.mIsEuicc)
&& (mCardId == that.mCardId)
&& (mCardStateInfo == that.mCardStateInfo)
- && (mLogicalSlotIdx == that.mLogicalSlotIdx);
+ && (mLogicalSlotIdx == that.mLogicalSlotIdx)
+ && (mIsExtendedApduSupported == that.mIsExtendedApduSupported);
}
@Override
@@ -150,6 +162,7 @@
result = 31 * result + Objects.hashCode(mCardId);
result = 31 * result + mCardStateInfo;
result = 31 * result + mLogicalSlotIdx;
+ result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
return result;
}
@@ -165,6 +178,8 @@
+ mCardStateInfo
+ ", phoneId="
+ mLogicalSlotIdx
+ + ", mIsExtendedApduSupported="
+ + mIsExtendedApduSupported
+ ")";
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 73a05af..145ed7e 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -17,10 +17,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.StringDef;
import android.content.ContentValues;
import android.database.Cursor;
import android.hardware.radio.V1_0.ApnTypes;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Telephony;
@@ -28,17 +28,15 @@
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
@@ -46,25 +44,184 @@
*/
public class ApnSetting implements Parcelable {
- static final String LOG_TAG = "ApnSetting";
+ private static final String LOG_TAG = "ApnSetting";
private static final boolean VDBG = false;
+ private static final Map<String, Integer> APN_TYPE_STRING_MAP;
+ private static final Map<Integer, String> APN_TYPE_INT_MAP;
+ private static final Map<String, Integer> PROTOCOL_STRING_MAP;
+ private static final Map<Integer, String> PROTOCOL_INT_MAP;
+ private static final Map<String, Integer> MVNO_TYPE_STRING_MAP;
+ private static final Map<Integer, String> MVNO_TYPE_INT_MAP;
+ private static final int NOT_IN_MAP_INT = -1;
+ private static final int NO_PORT_SPECIFIED = -1;
+
+ /** All APN types except IA. */
+ private static final int TYPE_ALL_BUT_IA = ApnTypes.ALL & (~ApnTypes.IA);
+
+ /** APN type for default data traffic and HiPri traffic. */
+ public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI;
+ /** APN type for MMS traffic. */
+ public static final int TYPE_MMS = ApnTypes.MMS;
+ /** APN type for SUPL assisted GPS. */
+ public static final int TYPE_SUPL = ApnTypes.SUPL;
+ /** APN type for DUN traffic. */
+ public static final int TYPE_DUN = ApnTypes.DUN;
+ /** APN type for HiPri traffic. */
+ public static final int TYPE_HIPRI = ApnTypes.HIPRI;
+ /** APN type for accessing the carrier's FOTA portal, used for over the air updates. */
+ public static final int TYPE_FOTA = ApnTypes.FOTA;
+ /** APN type for IMS. */
+ public static final int TYPE_IMS = ApnTypes.IMS;
+ /** APN type for CBS. */
+ public static final int TYPE_CBS = ApnTypes.CBS;
+ /** APN type for IA Initial Attach APN. */
+ public static final int TYPE_IA = ApnTypes.IA;
+ /**
+ * APN type for Emergency PDN. This is not an IA apn, but is used
+ * for access to carrier services in an emergency call situation.
+ */
+ public static final int TYPE_EMERGENCY = ApnTypes.EMERGENCY;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ApnType {}
+
+ // Possible values for authentication types.
+ /** No authentication type. */
+ public static final int AUTH_TYPE_NONE = 0;
+ /** Authentication type for PAP. */
+ public static final int AUTH_TYPE_PAP = 1;
+ /** Authentication type for CHAP. */
+ public static final int AUTH_TYPE_CHAP = 2;
+ /** Authentication type for PAP or CHAP. */
+ public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "AUTH_TYPE_" }, value = {
+ AUTH_TYPE_NONE,
+ AUTH_TYPE_PAP,
+ AUTH_TYPE_CHAP,
+ AUTH_TYPE_PAP_OR_CHAP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AuthType {}
+
+ // Possible values for protocol.
+ /** Protocol type for IP. */
+ public static final int PROTOCOL_IP = 0;
+ /** Protocol type for IPV6. */
+ public static final int PROTOCOL_IPV6 = 1;
+ /** Protocol type for IPV4V6. */
+ public static final int PROTOCOL_IPV4V6 = 2;
+ /** Protocol type for PPP. */
+ public static final int PROTOCOL_PPP = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "PROTOCOL_" }, value = {
+ PROTOCOL_IP,
+ PROTOCOL_IPV6,
+ PROTOCOL_IPV4V6,
+ PROTOCOL_PPP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtocolType {}
+
+ // Possible values for MVNO type.
+ /** MVNO type for service provider name. */
+ public static final int MVNO_TYPE_SPN = 0;
+ /** MVNO type for IMSI. */
+ public static final int MVNO_TYPE_IMSI = 1;
+ /** MVNO type for group identifier level 1. */
+ public static final int MVNO_TYPE_GID = 2;
+ /** MVNO type for ICCID. */
+ public static final int MVNO_TYPE_ICCID = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "MVNO_TYPE_" }, value = {
+ MVNO_TYPE_SPN,
+ MVNO_TYPE_IMSI,
+ MVNO_TYPE_GID,
+ MVNO_TYPE_ICCID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MvnoType {}
+
+ static {
+ APN_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
+ APN_TYPE_STRING_MAP.put("*", TYPE_ALL_BUT_IA);
+ APN_TYPE_STRING_MAP.put("default", TYPE_DEFAULT);
+ APN_TYPE_STRING_MAP.put("mms", TYPE_MMS);
+ APN_TYPE_STRING_MAP.put("supl", TYPE_SUPL);
+ APN_TYPE_STRING_MAP.put("dun", TYPE_DUN);
+ APN_TYPE_STRING_MAP.put("hipri", TYPE_HIPRI);
+ APN_TYPE_STRING_MAP.put("fota", TYPE_FOTA);
+ APN_TYPE_STRING_MAP.put("ims", TYPE_IMS);
+ APN_TYPE_STRING_MAP.put("cbs", TYPE_CBS);
+ APN_TYPE_STRING_MAP.put("ia", TYPE_IA);
+ APN_TYPE_STRING_MAP.put("emergency", TYPE_EMERGENCY);
+ APN_TYPE_INT_MAP = new ArrayMap<Integer, String>();
+ APN_TYPE_INT_MAP.put(TYPE_DEFAULT, "default");
+ APN_TYPE_INT_MAP.put(TYPE_MMS, "mms");
+ APN_TYPE_INT_MAP.put(TYPE_SUPL, "supl");
+ APN_TYPE_INT_MAP.put(TYPE_DUN, "dun");
+ APN_TYPE_INT_MAP.put(TYPE_HIPRI, "hipri");
+ APN_TYPE_INT_MAP.put(TYPE_FOTA, "fota");
+ APN_TYPE_INT_MAP.put(TYPE_IMS, "ims");
+ APN_TYPE_INT_MAP.put(TYPE_CBS, "cbs");
+ APN_TYPE_INT_MAP.put(TYPE_IA, "ia");
+ APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, "emergency");
+
+ PROTOCOL_STRING_MAP = new ArrayMap<String, Integer>();
+ PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
+ PROTOCOL_STRING_MAP.put("IPV6", PROTOCOL_IPV6);
+ PROTOCOL_STRING_MAP.put("IPV4V6", PROTOCOL_IPV4V6);
+ PROTOCOL_STRING_MAP.put("PPP", PROTOCOL_PPP);
+ PROTOCOL_INT_MAP = new ArrayMap<Integer, String>();
+ PROTOCOL_INT_MAP.put(PROTOCOL_IP, "IP");
+ PROTOCOL_INT_MAP.put(PROTOCOL_IPV6, "IPV6");
+ PROTOCOL_INT_MAP.put(PROTOCOL_IPV4V6, "IPV4V6");
+ PROTOCOL_INT_MAP.put(PROTOCOL_PPP, "PPP");
+
+ MVNO_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
+ MVNO_TYPE_STRING_MAP.put("spn", MVNO_TYPE_SPN);
+ MVNO_TYPE_STRING_MAP.put("imsi", MVNO_TYPE_IMSI);
+ MVNO_TYPE_STRING_MAP.put("gid", MVNO_TYPE_GID);
+ MVNO_TYPE_STRING_MAP.put("iccid", MVNO_TYPE_ICCID);
+ MVNO_TYPE_INT_MAP = new ArrayMap<Integer, String>();
+ MVNO_TYPE_INT_MAP.put(MVNO_TYPE_SPN, "spn");
+ MVNO_TYPE_INT_MAP.put(MVNO_TYPE_IMSI, "imsi");
+ MVNO_TYPE_INT_MAP.put(MVNO_TYPE_GID, "gid");
+ MVNO_TYPE_INT_MAP.put(MVNO_TYPE_ICCID, "iccid");
+ }
+
private final String mEntryName;
private final String mApnName;
- private final InetAddress mProxy;
- private final int mPort;
- private final URL mMmsc;
- private final InetAddress mMmsProxy;
- private final int mMmsPort;
+ private final InetAddress mProxyAddress;
+ private final int mProxyPort;
+ private final Uri mMmsc;
+ private final InetAddress mMmsProxyAddress;
+ private final int mMmsProxyPort;
private final String mUser;
private final String mPassword;
private final int mAuthType;
- private final List<String> mTypes;
- private final int mTypesBitmap;
+ private final int mApnTypeBitmask;
private final int mId;
private final String mOperatorNumeric;
- private final String mProtocol;
- private final String mRoamingProtocol;
+ private final int mProtocol;
+ private final int mRoamingProtocol;
private final int mMtu;
private final boolean mCarrierEnabled;
@@ -78,22 +235,12 @@
private final int mWaitTime;
private final int mMaxConnsTime;
- private final String mMvnoType;
+ private final int mMvnoType;
private final String mMvnoMatchData;
private boolean mPermanentFailed = false;
/**
- * Returns the types bitmap of the APN.
- *
- * @return types bitmap of the APN
- * @hide
- */
- public int getTypesBitmap() {
- return mTypesBitmap;
- }
-
- /**
* Returns the MTU size of the mobile interface to which the APN connected.
*
* @return the MTU size of the APN
@@ -211,8 +358,8 @@
*
* @return proxy address.
*/
- public InetAddress getProxy() {
- return mProxy;
+ public InetAddress getProxyAddress() {
+ return mProxyAddress;
}
/**
@@ -220,15 +367,15 @@
*
* @return proxy port
*/
- public int getPort() {
- return mPort;
+ public int getProxyPort() {
+ return mProxyPort;
}
/**
- * Returns the MMSC URL of the APN.
+ * Returns the MMSC Uri of the APN.
*
- * @return MMSC URL.
+ * @return MMSC Uri.
*/
- public URL getMmsc() {
+ public Uri getMmsc() {
return mMmsc;
}
@@ -237,8 +384,8 @@
*
* @return MMS proxy address.
*/
- public InetAddress getMmsProxy() {
- return mMmsProxy;
+ public InetAddress getMmsProxyAddress() {
+ return mMmsProxyAddress;
}
/**
@@ -246,8 +393,8 @@
*
* @return MMS proxy port
*/
- public int getMmsPort() {
- return mMmsPort;
+ public int getMmsProxyPort() {
+ return mMmsProxyPort;
}
/**
@@ -268,21 +415,9 @@
return mPassword;
}
- /** @hide */
- @IntDef({
- AUTH_TYPE_NONE,
- AUTH_TYPE_PAP,
- AUTH_TYPE_CHAP,
- AUTH_TYPE_PAP_OR_CHAP,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AuthType {}
-
/**
* Returns the authentication type of the APN.
*
- * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
- *
* @return authentication type
*/
@AuthType
@@ -290,32 +425,20 @@
return mAuthType;
}
- /** @hide */
- @StringDef({
- TYPE_DEFAULT,
- TYPE_MMS,
- TYPE_SUPL,
- TYPE_DUN,
- TYPE_HIPRI,
- TYPE_FOTA,
- TYPE_IMS,
- TYPE_CBS,
- TYPE_IA,
- TYPE_EMERGENCY
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ApnType {}
-
/**
- * Returns the list of APN types of the APN.
+ * Returns the bitmask of APN types.
*
- * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ * <p>Apn types are usage categories for an APN entry. One APN entry may support multiple
+ * APN types, eg, a single APN may service regular internet traffic ("default") as well as
+ * MMS-specific connections.
*
- * @return the list of APN types
+ * <p>The bitmask of APN types is calculated from APN types defined in {@link ApnSetting}.
+ *
+ * @see Builder#setApnTypeBitmask(int)
+ * @return a bitmask describing the types of the APN
*/
- @ApnType
- public List<String> getTypes() {
- return mTypes;
+ public @ApnType int getApnTypeBitmask() {
+ return mApnTypeBitmask;
}
/**
@@ -328,7 +451,7 @@
}
/**
- * Returns the numeric operator ID for the APN. Usually
+ * Returns the numeric operator ID for the APN. Numeric operator ID is defined as
* {@link android.provider.Telephony.Carriers#MCC} +
* {@link android.provider.Telephony.Carriers#MNC}.
*
@@ -338,37 +461,29 @@
return mOperatorNumeric;
}
- /** @hide */
- @StringDef({
- PROTOCOL_IP,
- PROTOCOL_IPV6,
- PROTOCOL_IPV4V6,
- PROTOCOL_PPP,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ProtocolType {}
-
/**
* Returns the protocol to use to connect to this APN.
*
- * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
- * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ * <p>Protocol is one of the {@code PDP_type} values in TS 27.007 section 10.1.1.
*
+ * @see Builder#setProtocol(int)
* @return the protocol
*/
@ProtocolType
- public String getProtocol() {
+ public int getProtocol() {
return mProtocol;
}
/**
- * Returns the protocol to use to connect to this APN when roaming.
+ * Returns the protocol to use to connect to this APN while the device is roaming.
*
- * The syntax is the same as {@link android.provider.Telephony.Carriers#PROTOCOL}.
+ * <p>Roaming protocol is one of the {@code PDP_type} values in TS 27.007 section 10.1.1.
*
+ * @see Builder#setRoamingProtocol(int)
* @return the roaming protocol
*/
- public String getRoamingProtocol() {
+ @ProtocolType
+ public int getRoamingProtocol() {
return mRoamingProtocol;
}
@@ -398,41 +513,29 @@
return mNetworkTypeBitmask;
}
- /** @hide */
- @StringDef({
- MVNO_TYPE_SPN,
- MVNO_TYPE_IMSI,
- MVNO_TYPE_GID,
- MVNO_TYPE_ICCID,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface MvnoType {}
-
/**
* Returns the MVNO match type for this APN.
*
- * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
- *
+ * @see Builder#setMvnoType(int)
* @return the MVNO match type
*/
@MvnoType
- public String getMvnoType() {
+ public int getMvnoType() {
return mMvnoType;
}
private ApnSetting(Builder builder) {
this.mEntryName = builder.mEntryName;
this.mApnName = builder.mApnName;
- this.mProxy = builder.mProxy;
- this.mPort = builder.mPort;
+ this.mProxyAddress = builder.mProxyAddress;
+ this.mProxyPort = builder.mProxyPort;
this.mMmsc = builder.mMmsc;
- this.mMmsProxy = builder.mMmsProxy;
- this.mMmsPort = builder.mMmsPort;
+ this.mMmsProxyAddress = builder.mMmsProxyAddress;
+ this.mMmsProxyPort = builder.mMmsProxyPort;
this.mUser = builder.mUser;
this.mPassword = builder.mPassword;
this.mAuthType = builder.mAuthType;
- this.mTypes = (builder.mTypes == null ? new ArrayList<String>() : builder.mTypes);
- this.mTypesBitmap = builder.mTypesBitmap;
+ this.mApnTypeBitmask = builder.mApnTypeBitmask;
this.mId = builder.mId;
this.mOperatorNumeric = builder.mOperatorNumeric;
this.mProtocol = builder.mProtocol;
@@ -451,25 +554,25 @@
/** @hide */
public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
- String apnName, InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy,
- int mmsPort, String user, String password, int authType, List<String> types,
- String protocol, String roamingProtocol, boolean carrierEnabled,
+ String apnName, InetAddress proxy, int port, Uri mmsc, InetAddress mmsProxy,
+ int mmsPort, String user, String password, int authType, int mApnTypeBitmask,
+ int protocol, int roamingProtocol, boolean carrierEnabled,
int networkTypeBitmask, int profileId, boolean modemCognitive, int maxConns,
- int waitTime, int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
+ int waitTime, int maxConnsTime, int mtu, int mvnoType, String mvnoMatchData) {
return new Builder()
.setId(id)
.setOperatorNumeric(operatorNumeric)
.setEntryName(entryName)
.setApnName(apnName)
- .setProxy(proxy)
- .setPort(port)
+ .setProxyAddress(proxy)
+ .setProxyPort(port)
.setMmsc(mmsc)
- .setMmsProxy(mmsProxy)
- .setMmsPort(mmsPort)
+ .setMmsProxyAddress(mmsProxy)
+ .setMmsProxyPort(mmsPort)
.setUser(user)
.setPassword(password)
.setAuthType(authType)
- .setTypes(types)
+ .setApnTypeBitmask(mApnTypeBitmask)
.setProtocol(protocol)
.setRoamingProtocol(roamingProtocol)
.setCarrierEnabled(carrierEnabled)
@@ -487,7 +590,7 @@
/** @hide */
public static ApnSetting makeApnSetting(Cursor cursor) {
- String[] types = parseTypes(
+ final int apnTypesBitmask = parseTypes(
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
int networkTypeBitmask = cursor.getInt(
cursor.getColumnIndexOrThrow(Telephony.Carriers.NETWORK_TYPE_BITMASK));
@@ -507,7 +610,7 @@
cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
portFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
- URLFromString(cursor.getString(
+ UriFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
inetAddressFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
@@ -516,10 +619,12 @@
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
- Arrays.asList(types),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.ROAMING_PROTOCOL)),
+ apnTypesBitmask,
+ nullToNotInMapInt(PROTOCOL_STRING_MAP.get(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)))),
+ nullToNotInMapInt(PROTOCOL_STRING_MAP.get(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL)))),
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.CARRIER_ENABLED)) == 1,
networkTypeBitmask,
@@ -531,8 +636,9 @@
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MAX_CONNS_TIME)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_TYPE)),
+ nullToNotInMapInt(MVNO_TYPE_STRING_MAP.get(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE)))),
cursor.getString(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MVNO_MATCH_DATA)));
}
@@ -540,8 +646,8 @@
/** @hide */
public static ApnSetting makeApnSetting(ApnSetting apn) {
return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
- apn.mProxy, apn.mPort, apn.mMmsc, apn.mMmsProxy, apn.mMmsPort, apn.mUser,
- apn.mPassword, apn.mAuthType, apn.mTypes, apn.mProtocol, apn.mRoamingProtocol,
+ apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress, apn.mMmsProxyPort, apn.mUser,
+ apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask, apn.mProtocol, apn.mRoamingProtocol,
apn.mCarrierEnabled, apn.mNetworkTypeBitmask, apn.mProfileId,
apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime, apn.mMaxConnsTime, apn.mMtu,
apn.mMvnoType, apn.mMvnoMatchData);
@@ -555,18 +661,14 @@
.append(", ").append(mId)
.append(", ").append(mOperatorNumeric)
.append(", ").append(mApnName)
- .append(", ").append(inetAddressToString(mProxy))
- .append(", ").append(URLToString(mMmsc))
- .append(", ").append(inetAddressToString(mMmsProxy))
- .append(", ").append(portToString(mMmsPort))
- .append(", ").append(portToString(mPort))
+ .append(", ").append(inetAddressToString(mProxyAddress))
+ .append(", ").append(UriToString(mMmsc))
+ .append(", ").append(inetAddressToString(mMmsProxyAddress))
+ .append(", ").append(portToString(mMmsProxyPort))
+ .append(", ").append(portToString(mProxyPort))
.append(", ").append(mAuthType).append(", ");
- for (int i = 0; i < mTypes.size(); i++) {
- sb.append(mTypes.get(i));
- if (i < mTypes.size() - 1) {
- sb.append(" | ");
- }
- }
+ final String[] types = deParseTypes(mApnTypeBitmask).split(",");
+ sb.append(TextUtils.join(" | ", types)).append(", ");
sb.append(", ").append(mProtocol);
sb.append(", ").append(mRoamingProtocol);
sb.append(", ").append(mCarrierEnabled);
@@ -588,56 +690,37 @@
* @hide
*/
public boolean hasMvnoParams() {
- return !TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData);
+ return (mMvnoType != NOT_IN_MAP_INT) && !TextUtils.isEmpty(mMvnoMatchData);
}
/** @hide */
- public boolean canHandleType(String type) {
- if (!mCarrierEnabled) return false;
- boolean wildcardable = true;
- if (TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
- for (String t : mTypes) {
- // DEFAULT handles all, and HIPRI is handled by DEFAULT
- if (t.equalsIgnoreCase(type)
- || (wildcardable && t.equalsIgnoreCase(TYPE_ALL))
- || (t.equalsIgnoreCase(TYPE_DEFAULT)
- && type.equalsIgnoreCase(TYPE_HIPRI))) {
- return true;
- }
- }
- return false;
+ public boolean canHandleType(@ApnType int type) {
+ return mCarrierEnabled && ((mApnTypeBitmask & type) == type);
}
// check whether the types of two APN same (even only one type of each APN is same)
private boolean typeSameAny(ApnSetting first, ApnSetting second) {
if (VDBG) {
StringBuilder apnType1 = new StringBuilder(first.mApnName + ": ");
- for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
- apnType1.append(first.mTypes.get(index1));
- apnType1.append(",");
- }
+ apnType1.append(deParseTypes(first.mApnTypeBitmask));
StringBuilder apnType2 = new StringBuilder(second.mApnName + ": ");
- for (int index1 = 0; index1 < second.mTypes.size(); index1++) {
- apnType2.append(second.mTypes.get(index1));
- apnType2.append(",");
- }
+ apnType2.append(deParseTypes(second.mApnTypeBitmask));
+
Rlog.d(LOG_TAG, "APN1: is " + apnType1);
Rlog.d(LOG_TAG, "APN2: is " + apnType2);
}
- for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
- for (int index2 = 0; index2 < second.mTypes.size(); index2++) {
- if (first.mTypes.get(index1).equals(ApnSetting.TYPE_ALL)
- || second.mTypes.get(index2).equals(ApnSetting.TYPE_ALL)
- || first.mTypes.get(index1).equals(second.mTypes.get(index2))) {
- if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
- return true;
- }
+ if ((first.mApnTypeBitmask & second.mApnTypeBitmask) != 0) {
+ if (VDBG) {
+ Rlog.d(LOG_TAG, "typeSameAny: return true");
}
+ return true;
}
- if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
+ if (VDBG) {
+ Rlog.d(LOG_TAG, "typeSameAny: return false");
+ }
return false;
}
@@ -655,16 +738,15 @@
&& Objects.equals(mId, other.mId)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
&& Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxy, other.mMmsProxy)
- && Objects.equals(mMmsPort, other.mMmsPort)
- && Objects.equals(mPort,other.mPort)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort,other.mProxyPort)
&& Objects.equals(mUser, other.mUser)
&& Objects.equals(mPassword, other.mPassword)
&& Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mTypes, other.mTypes)
- && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
&& Objects.equals(mProtocol, other.mProtocol)
&& Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
&& Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
@@ -701,16 +783,15 @@
return mEntryName.equals(other.mEntryName)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
&& Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxy, other.mMmsProxy)
- && Objects.equals(mMmsPort, other.mMmsPort)
- && Objects.equals(mPort, other.mPort)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort, other.mProxyPort)
&& Objects.equals(mUser, other.mUser)
&& Objects.equals(mPassword, other.mPassword)
&& Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mTypes, other.mTypes)
- && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
&& (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
&& (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
&& Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
@@ -736,17 +817,17 @@
&& !other.canHandleType(TYPE_DUN)
&& Objects.equals(this.mApnName, other.mApnName)
&& !typeSameAny(this, other)
- && xorEqualsInetAddress(this.mProxy, other.mProxy)
- && xorEqualsPort(this.mPort, other.mPort)
+ && xorEquals(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsPort(this.mProxyPort, other.mProxyPort)
&& xorEquals(this.mProtocol, other.mProtocol)
&& xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
&& Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
&& Objects.equals(this.mProfileId, other.mProfileId)
&& Objects.equals(this.mMvnoType, other.mMvnoType)
&& Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
- && xorEqualsURL(this.mMmsc, other.mMmsc)
- && xorEqualsInetAddress(this.mMmsProxy, other.mMmsProxy)
- && xorEqualsPort(this.mMmsPort, other.mMmsPort))
+ && xorEquals(this.mMmsc, other.mMmsc)
+ && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsPort(this.mMmsProxyPort, other.mMmsProxyPort))
&& Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask);
}
@@ -757,42 +838,23 @@
|| TextUtils.isEmpty(second));
}
- // Equal or one is not specified.
- private boolean xorEqualsInetAddress(InetAddress first, InetAddress second) {
- return first == null || second == null || first.equals(second);
- }
-
- // Equal or one is not specified.
- private boolean xorEqualsURL(URL first, URL second) {
+ // Equal or one is not null.
+ private boolean xorEquals(Object first, Object second) {
return first == null || second == null || first.equals(second);
}
// Equal or one is not specified.
private boolean xorEqualsPort(int first, int second) {
- return first == -1 || second == -1 || Objects.equals(first, second);
+ return first == NO_PORT_SPECIFIED || second == NO_PORT_SPECIFIED
+ || Objects.equals(first, second);
}
- // Helper function to convert APN string into a 32-bit bitmask.
- private static int getApnBitmask(String apn) {
- switch (apn) {
- case TYPE_DEFAULT: return ApnTypes.DEFAULT;
- case TYPE_MMS: return ApnTypes.MMS;
- case TYPE_SUPL: return ApnTypes.SUPL;
- case TYPE_DUN: return ApnTypes.DUN;
- case TYPE_HIPRI: return ApnTypes.HIPRI;
- case TYPE_FOTA: return ApnTypes.FOTA;
- case TYPE_IMS: return ApnTypes.IMS;
- case TYPE_CBS: return ApnTypes.CBS;
- case TYPE_IA: return ApnTypes.IA;
- case TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
- case TYPE_ALL: return ApnTypes.ALL;
- default: return ApnTypes.NONE;
- }
- }
-
- private String deParseTypes(List<String> types) {
- if (types == null) {
- return null;
+ private String deParseTypes(int apnTypeBitmask) {
+ List<String> types = new ArrayList<>();
+ for (Integer type : APN_TYPE_INT_MAP.keySet()) {
+ if ((apnTypeBitmask & type) == type) {
+ types.add(APN_TYPE_INT_MAP.get(type));
+ }
}
return TextUtils.join(",", types);
}
@@ -808,21 +870,25 @@
apnValue.put(Telephony.Carriers.NUMERIC, nullToEmpty(mOperatorNumeric));
apnValue.put(Telephony.Carriers.NAME, nullToEmpty(mEntryName));
apnValue.put(Telephony.Carriers.APN, nullToEmpty(mApnName));
- apnValue.put(Telephony.Carriers.PROXY, mProxy == null ? "" : inetAddressToString(mProxy));
- apnValue.put(Telephony.Carriers.PORT, portToString(mPort));
- apnValue.put(Telephony.Carriers.MMSC, mMmsc == null ? "" : URLToString(mMmsc));
- apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsPort));
- apnValue.put(Telephony.Carriers.MMSPROXY, mMmsProxy == null
- ? "" : inetAddressToString(mMmsProxy));
+ apnValue.put(Telephony.Carriers.PROXY, mProxyAddress == null ? ""
+ : inetAddressToString(mProxyAddress));
+ apnValue.put(Telephony.Carriers.PORT, portToString(mProxyPort));
+ apnValue.put(Telephony.Carriers.MMSC, mMmsc == null ? "" : UriToString(mMmsc));
+ apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsProxyPort));
+ apnValue.put(Telephony.Carriers.MMSPROXY, mMmsProxyAddress == null
+ ? "" : inetAddressToString(mMmsProxyAddress));
apnValue.put(Telephony.Carriers.USER, nullToEmpty(mUser));
apnValue.put(Telephony.Carriers.PASSWORD, nullToEmpty(mPassword));
apnValue.put(Telephony.Carriers.AUTH_TYPE, mAuthType);
- String apnType = deParseTypes(mTypes);
+ String apnType = deParseTypes(mApnTypeBitmask);
apnValue.put(Telephony.Carriers.TYPE, nullToEmpty(apnType));
- apnValue.put(Telephony.Carriers.PROTOCOL, nullToEmpty(mProtocol));
- apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL, nullToEmpty(mRoamingProtocol));
+ apnValue.put(Telephony.Carriers.PROTOCOL,
+ nullToEmpty(PROTOCOL_INT_MAP.get(mProtocol)));
+ apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL,
+ nullToEmpty(PROTOCOL_INT_MAP.get(mRoamingProtocol)));
apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
- apnValue.put(Telephony.Carriers.MVNO_TYPE, nullToEmpty(mMvnoType));
+ apnValue.put(Telephony.Carriers.MVNO_TYPE,
+ nullToEmpty(MVNO_TYPE_INT_MAP.get(mMvnoType)));
apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask);
return apnValue;
@@ -830,32 +896,31 @@
/**
* @param types comma delimited list of APN types
- * @return array of APN types
+ * @return bitmask of APN types
* @hide
*/
- public static String[] parseTypes(String types) {
- String[] result;
- // If unset, set to DEFAULT.
+ public static int parseTypes(String types) {
+ // If unset, set to ALL.
if (TextUtils.isEmpty(types)) {
- result = new String[1];
- result[0] = TYPE_ALL;
+ return TYPE_ALL_BUT_IA;
} else {
- result = types.split(",");
- }
- return result;
- }
-
- private static URL URLFromString(String url) {
- try {
- return TextUtils.isEmpty(url) ? null : new URL(url);
- } catch (MalformedURLException e) {
- Log.e(LOG_TAG, "Can't parse URL from string.");
- return null;
+ int result = 0;
+ for (String str : types.split(",")) {
+ Integer type = APN_TYPE_STRING_MAP.get(str);
+ if (type != null) {
+ result |= type;
+ }
+ }
+ return result;
}
}
- private static String URLToString(URL url) {
- return url == null ? "" : url.toString();
+ private static Uri UriFromString(String uri) {
+ return TextUtils.isEmpty(uri) ? null : Uri.parse(uri);
+ }
+
+ private static String UriToString(Uri uri) {
+ return uri == null ? "" : uri.toString();
}
private static InetAddress inetAddressFromString(String inetAddress) {
@@ -887,7 +952,7 @@
}
private static int portFromString(String strPort) {
- int port = -1;
+ int port = NO_PORT_SPECIFIED;
if (!TextUtils.isEmpty(strPort)) {
try {
port = Integer.parseInt(strPort);
@@ -899,7 +964,7 @@
}
private static String portToString(int port) {
- return port == -1 ? "" : Integer.toString(port);
+ return port == NO_PORT_SPECIFIED ? "" : Integer.toString(port);
}
// Implement Parcelable.
@@ -916,19 +981,19 @@
dest.writeString(mOperatorNumeric);
dest.writeString(mEntryName);
dest.writeString(mApnName);
- dest.writeValue(mProxy);
- dest.writeInt(mPort);
+ dest.writeValue(mProxyAddress);
+ dest.writeInt(mProxyPort);
dest.writeValue(mMmsc);
- dest.writeValue(mMmsProxy);
- dest.writeInt(mMmsPort);
+ dest.writeValue(mMmsProxyAddress);
+ dest.writeInt(mMmsProxyPort);
dest.writeString(mUser);
dest.writeString(mPassword);
dest.writeInt(mAuthType);
- dest.writeStringArray(mTypes.toArray(new String[0]));
- dest.writeString(mProtocol);
- dest.writeString(mRoamingProtocol);
+ dest.writeInt(mApnTypeBitmask);
+ dest.writeInt(mProtocol);
+ dest.writeInt(mRoamingProtocol);
dest.writeInt(mCarrierEnabled ? 1: 0);
- dest.writeString(mMvnoType);
+ dest.writeInt(mMvnoType);
dest.writeInt(mNetworkTypeBitmask);
}
@@ -939,23 +1004,23 @@
final String apnName = in.readString();
final InetAddress proxy = (InetAddress)in.readValue(InetAddress.class.getClassLoader());
final int port = in.readInt();
- final URL mmsc = (URL)in.readValue(URL.class.getClassLoader());
+ final Uri mmsc = (Uri)in.readValue(Uri.class.getClassLoader());
final InetAddress mmsProxy = (InetAddress)in.readValue(InetAddress.class.getClassLoader());
final int mmsPort = in.readInt();
final String user = in.readString();
final String password = in.readString();
final int authType = in.readInt();
- final List<String> types = Arrays.asList(in.readStringArray());
- final String protocol = in.readString();
- final String roamingProtocol = in.readString();
+ final int apnTypesBitmask = in.readInt();
+ final int protocol = in.readInt();
+ final int roamingProtocol = in.readInt();
final boolean carrierEnabled = in.readInt() > 0;
- final String mvnoType = in.readString();
+ final int mvnoType = in.readInt();
final int networkTypeBitmask = in.readInt();
return makeApnSetting(id, operatorNumeric, entryName, apnName,
- proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, types, protocol,
- roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
- 0, 0, 0, 0, mvnoType, null);
+ proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
+ protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
+ 0, 0, 0, 0, mvnoType, null);
}
public static final Parcelable.Creator<ApnSetting> CREATOR =
@@ -971,89 +1036,26 @@
}
};
- /**
- * APN types for data connections. These are usage categories for an APN
- * entry. One APN entry may support multiple APN types, eg, a single APN
- * may service regular internet traffic ("default") as well as MMS-specific
- * connections.<br/>
- * ALL is a special type to indicate that this APN entry can
- * service all data connections.
- */
- public static final String TYPE_ALL = "*";
- /** APN type for default data traffic */
- public static final String TYPE_DEFAULT = "default";
- /** APN type for MMS traffic */
- public static final String TYPE_MMS = "mms";
- /** APN type for SUPL assisted GPS */
- public static final String TYPE_SUPL = "supl";
- /** APN type for DUN traffic */
- public static final String TYPE_DUN = "dun";
- /** APN type for HiPri traffic */
- public static final String TYPE_HIPRI = "hipri";
- /** APN type for FOTA */
- public static final String TYPE_FOTA = "fota";
- /** APN type for IMS */
- public static final String TYPE_IMS = "ims";
- /** APN type for CBS */
- public static final String TYPE_CBS = "cbs";
- /** APN type for IA Initial Attach APN */
- public static final String TYPE_IA = "ia";
- /** APN type for Emergency PDN. This is not an IA apn, but is used
- * for access to carrier services in an emergency call situation. */
- public static final String TYPE_EMERGENCY = "emergency";
- /**
- * Array of all APN types
- *
- * @hide
- */
- public static final String[] ALL_TYPES = {
- TYPE_DEFAULT,
- TYPE_MMS,
- TYPE_SUPL,
- TYPE_DUN,
- TYPE_HIPRI,
- TYPE_FOTA,
- TYPE_IMS,
- TYPE_CBS,
- TYPE_IA,
- TYPE_EMERGENCY
- };
-
- // Possible values for authentication types.
- public static final int AUTH_TYPE_NONE = 0;
- public static final int AUTH_TYPE_PAP = 1;
- public static final int AUTH_TYPE_CHAP = 2;
- public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
-
- // Possible values for protocol.
- public static final String PROTOCOL_IP = "IP";
- public static final String PROTOCOL_IPV6 = "IPV6";
- public static final String PROTOCOL_IPV4V6 = "IPV4V6";
- public static final String PROTOCOL_PPP = "PPP";
-
- // Possible values for MVNO type.
- public static final String MVNO_TYPE_SPN = "spn";
- public static final String MVNO_TYPE_IMSI = "imsi";
- public static final String MVNO_TYPE_GID = "gid";
- public static final String MVNO_TYPE_ICCID = "iccid";
+ private static int nullToNotInMapInt(Integer value) {
+ return value == null ? NOT_IN_MAP_INT : value;
+ }
public static class Builder{
private String mEntryName;
private String mApnName;
- private InetAddress mProxy;
- private int mPort = -1;
- private URL mMmsc;
- private InetAddress mMmsProxy;
- private int mMmsPort = -1;
+ private InetAddress mProxyAddress;
+ private int mProxyPort = NO_PORT_SPECIFIED;
+ private Uri mMmsc;
+ private InetAddress mMmsProxyAddress;
+ private int mMmsProxyPort = NO_PORT_SPECIFIED;
private String mUser;
private String mPassword;
private int mAuthType;
- private List<String> mTypes;
- private int mTypesBitmap;
+ private int mApnTypeBitmask;
private int mId;
private String mOperatorNumeric;
- private String mProtocol;
- private String mRoamingProtocol;
+ private int mProtocol = NOT_IN_MAP_INT;
+ private int mRoamingProtocol = NOT_IN_MAP_INT;
private int mMtu;
private int mNetworkTypeBitmask;
private boolean mCarrierEnabled;
@@ -1062,7 +1064,7 @@
private int mMaxConns;
private int mWaitTime;
private int mMaxConnsTime;
- private String mMvnoType;
+ private int mMvnoType = NOT_IN_MAP_INT;
private String mMvnoMatchData;
/**
@@ -1182,8 +1184,8 @@
*
* @param proxy the proxy address to set for the APN
*/
- public Builder setProxy(InetAddress proxy) {
- this.mProxy = proxy;
+ public Builder setProxyAddress(InetAddress proxy) {
+ this.mProxyAddress = proxy;
return this;
}
@@ -1192,17 +1194,17 @@
*
* @param port the proxy port to set for the APN
*/
- public Builder setPort(int port) {
- this.mPort = port;
+ public Builder setProxyPort(int port) {
+ this.mProxyPort = port;
return this;
}
/**
- * Sets the MMSC URL of the APN.
+ * Sets the MMSC Uri of the APN.
*
- * @param mmsc the MMSC URL to set for the APN
+ * @param mmsc the MMSC Uri to set for the APN
*/
- public Builder setMmsc(URL mmsc) {
+ public Builder setMmsc(Uri mmsc) {
this.mMmsc = mmsc;
return this;
}
@@ -1212,8 +1214,8 @@
*
* @param mmsProxy the MMS proxy address to set for the APN
*/
- public Builder setMmsProxy(InetAddress mmsProxy) {
- this.mMmsProxy = mmsProxy;
+ public Builder setMmsProxyAddress(InetAddress mmsProxy) {
+ this.mMmsProxyAddress = mmsProxy;
return this;
}
@@ -1222,8 +1224,8 @@
*
* @param mmsPort the MMS proxy port to set for the APN
*/
- public Builder setMmsPort(int mmsPort) {
- this.mMmsPort = mmsPort;
+ public Builder setMmsProxyPort(int mmsPort) {
+ this.mMmsProxyPort = mmsPort;
return this;
}
@@ -1251,8 +1253,6 @@
/**
* Sets the authentication type of the APN.
*
- * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
- *
* @param authType the authentication type to set for the APN
*/
public Builder setAuthType(@AuthType int authType) {
@@ -1261,25 +1261,25 @@
}
/**
- * Sets the list of APN types of the APN.
+ * Sets the bitmask of APN types.
*
- * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ * <p>Apn types are usage categories for an APN entry. One APN entry may support multiple
+ * APN types, eg, a single APN may service regular internet traffic ("default") as well as
+ * MMS-specific connections.
*
- * @param types the list of APN types to set for the APN
+ * <p>The bitmask of APN types is calculated from APN types defined in {@link ApnSetting}.
+ *
+ * @param apnTypeBitmask a bitmask describing the types of the APN
*/
- public Builder setTypes(@ApnType List<String> types) {
- this.mTypes = types;
- int apnBitmap = 0;
- for (int i = 0; i < mTypes.size(); i++) {
- mTypes.set(i, mTypes.get(i).toLowerCase());
- apnBitmap |= getApnBitmask(mTypes.get(i));
- }
- this.mTypesBitmap = apnBitmap;
+ public Builder setApnTypeBitmask(@ApnType int apnTypeBitmask) {
+ this.mApnTypeBitmask = apnTypeBitmask;
return this;
}
/**
- * Set the numeric operator ID for the APN.
+ * Sets the numeric operator ID for the APN. Numeric operator ID is defined as
+ * {@link android.provider.Telephony.Carriers#MCC} +
+ * {@link android.provider.Telephony.Carriers#MNC}.
*
* @param operatorNumeric the numeric operator ID to set for this entry
*/
@@ -1291,22 +1291,23 @@
/**
* Sets the protocol to use to connect to this APN.
*
- * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
- * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ * <p>Protocol is one of the {@code PDP_type} values in TS 27.007 section 10.1.1.
*
* @param protocol the protocol to set to use to connect to this APN
*/
- public Builder setProtocol(@ProtocolType String protocol) {
+ public Builder setProtocol(@ProtocolType int protocol) {
this.mProtocol = protocol;
return this;
}
/**
- * Sets the protocol to use to connect to this APN when roaming.
+ * Sets the protocol to use to connect to this APN when the device is roaming.
+ *
+ * <p>Roaming protocol is one of the {@code PDP_type} values in TS 27.007 section 10.1.1.
*
* @param roamingProtocol the protocol to set to use to connect to this APN when roaming
*/
- public Builder setRoamingProtocol(String roamingProtocol) {
+ public Builder setRoamingProtocol(@ProtocolType int roamingProtocol) {
this.mRoamingProtocol = roamingProtocol;
return this;
}
@@ -1334,16 +1335,25 @@
/**
* Sets the MVNO match type for this APN.
*
- * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
- *
* @param mvnoType the MVNO match type to set for this APN
*/
- public Builder setMvnoType(@MvnoType String mvnoType) {
+ public Builder setMvnoType(@MvnoType int mvnoType) {
this.mMvnoType = mvnoType;
return this;
}
+ /**
+ * Builds {@link ApnSetting} from this builder.
+ *
+ * @return {@code null} if {@link #setApnName(String)} or {@link #setEntryName(String)}
+ * is empty, or {@link #setApnTypeBitmask(int)} doesn't contain a valid bit,
+ * {@link ApnSetting} built from this builder otherwise.
+ */
public ApnSetting build() {
+ if ((mApnTypeBitmask & ApnTypes.ALL) == 0 || TextUtils.isEmpty(mApnName)
+ || TextUtils.isEmpty(mEntryName)) {
+ return null;
+ }
return new ApnSetting(this);
}
}
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 71ef5de..8279123 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -15,11 +15,12 @@
*/
package android.telephony.euicc;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
@@ -73,6 +74,7 @@
*/
@SystemApi
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public static final String ACTION_OTA_STATUS_CHANGED =
"android.telephony.euicc.action.OTA_STATUS_CHANGED";
@@ -301,6 +303,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public int getOtaStatus() {
if (!isEnabled()) {
return EUICC_OTA_STATUS_UNAVAILABLE;
@@ -325,6 +328,7 @@
* @param switchAfterDownload if true, the profile will be activated upon successful download.
* @param callbackIntent a PendingIntent to launch when the operation completes.
*/
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void downloadSubscription(DownloadableSubscription subscription,
boolean switchAfterDownload, PendingIntent callbackIntent) {
if (!isEnabled()) {
@@ -387,6 +391,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
if (!isEnabled()) {
PendingIntent callbackIntent =
@@ -422,6 +427,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void getDownloadableSubscriptionMetadata(
DownloadableSubscription subscription, PendingIntent callbackIntent) {
if (!isEnabled()) {
@@ -452,6 +458,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
if (!isEnabled()) {
sendUnavailableError(callbackIntent);
@@ -496,6 +503,7 @@
* @param subscriptionId the ID of the subscription to delete.
* @param callbackIntent a PendingIntent to launch when the operation completes.
*/
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void deleteSubscription(int subscriptionId, PendingIntent callbackIntent) {
if (!isEnabled()) {
sendUnavailableError(callbackIntent);
@@ -523,6 +531,7 @@
* current profile without activating another profile to replace it.
* @param callbackIntent a PendingIntent to launch when the operation completes.
*/
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
if (!isEnabled()) {
sendUnavailableError(callbackIntent);
@@ -548,6 +557,7 @@
* @param callbackIntent a PendingIntent to launch when the operation completes.
* @hide
*/
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void updateSubscriptionNickname(
int subscriptionId, String nickname, PendingIntent callbackIntent) {
if (!isEnabled()) {
@@ -566,12 +576,13 @@
* Erase all subscriptions and reset the eUICC.
*
* <p>Requires that the calling app has the
- * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
- * internal system use only.
+ * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
*
* @param callbackIntent a PendingIntent to launch when the operation completes.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void eraseSubscriptions(PendingIntent callbackIntent) {
if (!isEnabled()) {
sendUnavailableError(callbackIntent);
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index c073d1a..aaf1a1cf8 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -139,34 +139,44 @@
@Override
public int queryCapabilityStatus() throws RemoteException {
- return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+ synchronized (mLock) {
+ return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+ }
}
@Override
public void addCapabilityCallback(IImsCapabilityCallback c) {
+ // no need to lock, structure already handles multithreading.
MmTelFeature.this.addCapabilityCallback(c);
}
@Override
public void removeCapabilityCallback(IImsCapabilityCallback c) {
+ // no need to lock, structure already handles multithreading.
MmTelFeature.this.removeCapabilityCallback(c);
}
@Override
public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
IImsCapabilityCallback c) throws RemoteException {
- MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+ synchronized (mLock) {
+ MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+ }
}
@Override
public void queryCapabilityConfiguration(int capability, int radioTech,
IImsCapabilityCallback c) {
- queryCapabilityConfigurationInternal(capability, radioTech, c);
+ synchronized (mLock) {
+ queryCapabilityConfigurationInternal(capability, radioTech, c);
+ }
}
@Override
public void setSmsListener(IImsSmsListener l) throws RemoteException {
- MmTelFeature.this.setSmsListener(l);
+ synchronized (mLock) {
+ MmTelFeature.this.setSmsListener(l);
+ }
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index da8471f..a182f2b 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -26,7 +26,8 @@
import android.telephony.TelephonyManager;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.ITelephony;
+
+import java.util.function.Supplier;
/** Utility class for Telephony permission enforcement. */
public final class TelephonyPermissions {
@@ -34,6 +35,9 @@
private static final boolean DBG = false;
+ private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
+ ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+
private TelephonyPermissions() {}
/**
@@ -41,8 +45,8 @@
*
* <p>This method behaves in one of the following ways:
* <ul>
- * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
- * READ_PHONE_STATE runtime permission.
+ * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+ * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
* <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
* apps which support runtime permissions, if the caller does not currently have any of
* these permissions.
@@ -51,20 +55,30 @@
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
* so we return false to indicate that the calling function should return dummy data.
* </ul>
+ *
+ * <p>Note: for simplicity, this method always returns false for callers using legacy
+ * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+ * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+ * devices.
+ *
+ * @param subId the subId of the relevant subscription; used to check carrier privileges. May be
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases
+ * where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave
+ * inaccesible to carrier-privileged apps).
*/
public static boolean checkCallingOrSelfReadPhoneState(
- Context context, String callingPackage, String message) {
- return checkReadPhoneState(context, Binder.getCallingPid(), Binder.getCallingUid(),
+ Context context, int subId, String callingPackage, String message) {
+ return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
callingPackage, message);
}
/**
* Check whether the app with the given pid/uid can read phone state.
*
- * <p>This method behaves in one of the following ways:
+ * <p>This method behaves in one of the following ways:
* <ul>
- * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
- * READ_PHONE_STATE runtime permission.
+ * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+ * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
* <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
* apps which support runtime permissions, if the caller does not currently have any of
* these permissions.
@@ -73,9 +87,22 @@
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
* so we return false to indicate that the calling function should return dummy data.
* </ul>
+ *
+ * <p>Note: for simplicity, this method always returns false for callers using legacy
+ * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+ * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+ * devices.
*/
public static boolean checkReadPhoneState(
- Context context, int pid, int uid, String callingPackage, String message) {
+ Context context, int subId, int pid, int uid, String callingPackage, String message) {
+ return checkReadPhoneState(
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
+ }
+
+ @VisibleForTesting
+ public static boolean checkReadPhoneState(
+ Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+ String callingPackage, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -83,8 +110,18 @@
// SKIP checking for run-time permission since caller has PRIVILEGED permission
return true;
} catch (SecurityException privilegedPhoneStateException) {
- context.enforcePermission(
- android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+ try {
+ context.enforcePermission(
+ android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+ } catch (SecurityException phoneStateException) {
+ // If we don't have the runtime permission, but do have carrier privileges, that
+ // suffices for reading phone state.
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+ return true;
+ }
+ throw phoneStateException;
+ }
}
// We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
@@ -101,14 +138,16 @@
* default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
- Context context, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, String message) {
return checkReadPhoneNumber(
- context, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
+ context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+ callingPackage, message);
}
@VisibleForTesting
public static boolean checkReadPhoneNumber(
- Context context, int pid, int uid, String callingPackage, String message) {
+ Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+ String callingPackage, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) ==
@@ -121,7 +160,8 @@
// First, check if we can read the phone state.
try {
- return checkReadPhoneState(context, pid, uid, callingPackage, message);
+ return checkReadPhoneState(
+ context, telephonySupplier, subId, pid, uid, callingPackage, message);
} catch (SecurityException readPhoneStateSecurityException) {
}
// Can be read with READ_SMS too.
@@ -186,16 +226,21 @@
}
private static void enforceCarrierPrivilege(int subId, int uid, String message) {
- if (getCarrierPrivilegeStatus(subId, uid) !=
+ enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+ }
+
+ private static void enforceCarrierPrivilege(
+ Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
+ if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) !=
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
throw new SecurityException(message);
}
}
- private static int getCarrierPrivilegeStatus(int subId, int uid) {
- ITelephony telephony =
- ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ private static int getCarrierPrivilegeStatus(
+ Supplier<ITelephony> telephonySupplier, int subId, int uid) {
+ ITelephony telephony = telephonySupplier.get();
try {
if (telephony != null) {
return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 14c5f4b..964a313 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -470,6 +470,9 @@
int bearerDataLength;
SmsEnvelope env = new SmsEnvelope();
CdmaSmsAddress addr = new CdmaSmsAddress();
+ // We currently do not parse subaddress in PDU, but it is required when determining
+ // fingerprint (see getIncomingSmsFingerprint()).
+ CdmaSmsSubaddress subaddr = new CdmaSmsSubaddress();
try {
env.messageType = dis.readInt();
@@ -520,6 +523,7 @@
// link the filled objects to this SMS
mOriginatingAddress = addr;
env.origAddress = addr;
+ env.origSubaddress = subaddr;
mEnvelope = env;
mPdu = pdu;
@@ -1009,8 +1013,11 @@
output.write(mEnvelope.teleService);
output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length);
output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length);
- output.write(mEnvelope.origSubaddress.origBytes, 0,
- mEnvelope.origSubaddress.origBytes.length);
+ // subaddress is not set when parsing some MT SMS.
+ if (mEnvelope.origSubaddress != null && mEnvelope.origSubaddress.origBytes != null) {
+ output.write(mEnvelope.origSubaddress.origBytes, 0,
+ mEnvelope.origSubaddress.origBytes.length);
+ }
return output.toByteArray();
}
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index cc3366f..0ca20de 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -50,13 +50,18 @@
private static final int TEST_UDP_ENCAP_PORT = 34567;
private static final int DROID_SPI = 0xD1201D;
+ private static final int DUMMY_RESOURCE_ID = 0x1234;
private static final InetAddress GOOGLE_DNS_4;
+ private static final String VTI_INTF_NAME = "ipsec_test";
+ private static final InetAddress VTI_LOCAL_ADDRESS;
+ private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24");
static {
try {
// Google Public DNS Addresses;
GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
+ VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
} catch (UnknownHostException e) {
throw new RuntimeException("Could not resolve DNS Addresses", e);
}
@@ -77,9 +82,8 @@
*/
@Test
public void testAllocSpi() throws Exception {
- int resourceId = 1;
IpSecSpiResponse spiResp =
- new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+ new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
when(mMockIpSecService.allocateSecurityParameterIndex(
eq(GOOGLE_DNS_4.getHostAddress()),
eq(DROID_SPI),
@@ -92,14 +96,13 @@
droidSpi.close();
- verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+ verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
}
@Test
public void testAllocRandomSpi() throws Exception {
- int resourceId = 1;
IpSecSpiResponse spiResp =
- new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+ new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
when(mMockIpSecService.allocateSecurityParameterIndex(
eq(GOOGLE_DNS_4.getHostAddress()),
eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
@@ -113,7 +116,7 @@
randomSpi.close();
- verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+ verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
}
/*
@@ -165,11 +168,10 @@
@Test
public void testOpenEncapsulationSocket() throws Exception {
- int resourceId = 1;
IpSecUdpEncapResponse udpEncapResp =
new IpSecUdpEncapResponse(
IpSecManager.Status.OK,
- resourceId,
+ DUMMY_RESOURCE_ID,
TEST_UDP_ENCAP_PORT,
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
@@ -182,16 +184,15 @@
encapSocket.close();
- verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+ verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
}
@Test
public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
- int resourceId = 1;
IpSecUdpEncapResponse udpEncapResp =
new IpSecUdpEncapResponse(
IpSecManager.Status.OK,
- resourceId,
+ DUMMY_RESOURCE_ID,
TEST_UDP_ENCAP_PORT,
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
@@ -206,7 +207,7 @@
encapSocket.close();
- verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+ verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
}
@Test
@@ -219,4 +220,45 @@
}
// TODO: add test when applicable transform builder interface is available
-}
+
+ private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName)
+ throws Exception {
+ IpSecTunnelInterfaceResponse dummyResponse =
+ new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
+ when(mMockIpSecService.createTunnelInterface(
+ eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()),
+ anyObject(), anyObject()))
+ .thenReturn(dummyResponse);
+
+ IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface(
+ VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class));
+
+ assertNotNull(tunnelIntf);
+ return tunnelIntf;
+ }
+
+ @Test
+ public void testCreateVti() throws Exception {
+ IpSecManager.IpSecTunnelInterface tunnelIntf =
+ createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
+
+ assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName());
+
+ tunnelIntf.close();
+ verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID));
+ }
+
+ @Test
+ public void testAddRemoveAddressesFromVti() throws Exception {
+ IpSecManager.IpSecTunnelInterface tunnelIntf =
+ createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
+
+ tunnelIntf.addAddress(VTI_INNER_ADDRESS);
+ verify(mMockIpSecService)
+ .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
+
+ tunnelIntf.removeAddress(VTI_INNER_ADDRESS);
+ verify(mMockIpSecService)
+ .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 035a4cd7..0530a86 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -19,6 +19,7 @@
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -31,6 +32,7 @@
import static android.net.NetworkStats.SET_DBG_VPN_OUT;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static org.junit.Assert.assertEquals;
@@ -641,6 +643,136 @@
ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0);
}
+ @Test
+ public void testFilter_NoFilter() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
+ assertEquals(3, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry2, stats.getValues(1, null));
+ assertEquals(entry3, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testFilter_UidFilter() {
+ final int testUid = 10101;
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", testUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", testUid, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
+ assertEquals(2, stats.size());
+ assertEquals(entry2, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ }
+
+ @Test
+ public void testFilter_InterfaceFilter() {
+ final String testIf1 = "testif1";
+ final String testIf2 = "testif2";
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ testIf1, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "otherif", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ testIf1, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry4 = new NetworkStats.Entry(
+ testIf2, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 4)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3)
+ .addValues(entry4);
+
+ stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
+ assertEquals(3, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ assertEquals(entry4, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testFilter_EmptyInterfaceFilter() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "if1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "if2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2);
+
+ stats.filter(UID_ALL, new String[] { }, TAG_ALL);
+ assertEquals(0, stats.size());
+ }
+
+ @Test
+ public void testFilter_TagFilter() {
+ final int testTag = 123;
+ final int otherTag = 456;
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, otherTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(UID_ALL, INTERFACES_ALL, testTag);
+ assertEquals(2, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry2, stats.getValues(1, null));
+ }
+
private static void assertContains(NetworkStats stats, String iface, int uid, int set,
int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index b14f550..fc46b9c 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -184,7 +184,7 @@
assertStatsEntry(stats, "dummy0", 0, SET_DEFAULT, 0x0, 0L, 168L);
assertStatsEntry(stats, "lo", 0, SET_DEFAULT, 0x0, 1288L, 1288L);
- NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
+ NetworkStatsFactory.clearStackedIfaces();
}
@Test
@@ -212,7 +212,7 @@
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 647587L);
- NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
+ NetworkStatsFactory.clearStackedIfaces();
}
/**
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5ea21ea..82b7bec 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -63,6 +63,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -133,6 +134,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.connectivity.ConnectivityConstants;
import com.android.server.connectivity.DefaultNetworkMetrics;
+import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.NetworkAgentInfo;
@@ -749,6 +751,7 @@
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
private class WrappedNetworkMonitor extends NetworkMonitor {
+ public Handler connectivityHandler;
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
public int gen204ProbeResult = 500;
public String gen204ProbeRedirectUrl = null;
@@ -758,6 +761,7 @@
IpConnectivityLog log) {
super(context, handler, networkAgentInfo, defaultRequest, log,
NetworkMonitor.NetworkMonitorSettings.DEFAULT);
+ connectivityHandler = handler;
}
@Override
@@ -3664,18 +3668,29 @@
@Test
public void testBasicDnsConfigurationPushed() throws Exception {
+ final String IFNAME = "test_rmnet_data0";
+ final String[] EMPTY_TLS_SERVERS = new String[0];
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
waitForIdle();
verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
- anyInt(), any(), any(), any(), anyBoolean(), anyString());
+ anyInt(), any(), any(), any(), anyString(), eq(EMPTY_TLS_SERVERS));
final LinkProperties cellLp = new LinkProperties();
- cellLp.setInterfaceName("test_rmnet_data0");
+ cellLp.setInterfaceName(IFNAME);
+ // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
+ // "is-reachable" testing in order to not program netd with unreachable
+ // nameservers that it might try repeated to validate.
+ cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), IFNAME));
+ cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
+ cellLp.addRoute(
+ new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
- anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ anyString(), eq(EMPTY_TLS_SERVERS));
// CS tells netd about the empty DNS config for this network.
assertEmpty(mStringArrayCaptor.getValue());
reset(mNetworkManagementService);
@@ -3684,7 +3699,8 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
- anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ anyString(), eq(EMPTY_TLS_SERVERS));
assertEquals(1, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
reset(mNetworkManagementService);
@@ -3693,7 +3709,26 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
- anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ anyString(), eq(EMPTY_TLS_SERVERS));
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+
+ final String TLS_SPECIFIER = "tls.example.com";
+ final String TLS_SERVER6 = "2001:db8:53::53";
+ final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
+ final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
+ final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler;
+ h.sendMessage(h.obtainMessage(
+ NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0,
+ mCellNetworkAgent.getNetwork().netId,
+ new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(TLS_SPECIFIER), eq(TLS_SERVERS));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 3e1ff6d..410f754 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -17,11 +17,13 @@
package com.android.server;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,6 +34,9 @@
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransformResponse;
+import android.net.IpSecTunnelInterfaceResponse;
+import android.net.LinkAddress;
+import android.net.Network;
import android.net.NetworkUtils;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
@@ -56,10 +61,15 @@
private final String mDestinationAddr;
private final String mSourceAddr;
+ private final LinkAddress mLocalInnerAddress;
@Parameterized.Parameters
public static Collection ipSecConfigs() {
- return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}});
+ return Arrays.asList(
+ new Object[][] {
+ {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"},
+ {"2601::2", "2601::10", "2001:db8::1/64"}
+ });
}
private static final byte[] AEAD_KEY = {
@@ -86,6 +96,7 @@
INetd mMockNetd;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
IpSecService mIpSecService;
+ Network fakeNetwork = new Network(0xAB);
private static final IpSecAlgorithm AUTH_ALGO =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
@@ -94,9 +105,11 @@
private static final IpSecAlgorithm AEAD_ALGO =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
- public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) {
+ public IpSecServiceParameterizedTest(
+ String sourceAddr, String destAddr, String localInnerAddr) {
mSourceAddr = sourceAddr;
mDestinationAddr = destAddr;
+ mLocalInnerAddress = new LinkAddress(localInnerAddr);
}
@Before
@@ -308,6 +321,30 @@
}
@Test
+ public void testReleaseOwnedSpi() throws Exception {
+ IpSecConfig ipSecConfig = new IpSecConfig();
+ addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+ addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder());
+ IpSecService.UserRecord userRecord =
+ mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+ assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+ mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+ verify(mMockNetd, times(0))
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyString(),
+ anyString(),
+ eq(TEST_SPI),
+ anyInt(),
+ anyInt());
+ // quota is not released until the SPI is released by the Transform
+ assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+ }
+
+ @Test
public void testDeleteTransform() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
@@ -317,7 +354,7 @@
mIpSecService.createTransform(ipSecConfig, new Binder());
mIpSecService.deleteTransform(createTransformResp.resourceId);
- verify(mMockNetd)
+ verify(mMockNetd, times(1))
.ipSecDeleteSecurityAssociation(
eq(createTransformResp.resourceId),
anyString(),
@@ -330,6 +367,21 @@
IpSecService.UserRecord userRecord =
mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
+ assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+
+ mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+ // Verify that ipSecDeleteSa was not called when the SPI was released because the
+ // ownedByTransform property should prevent it; (note, the called count is cumulative).
+ verify(mMockNetd, times(1))
+ .ipSecDeleteSecurityAssociation(
+ anyInt(),
+ anyString(),
+ anyString(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
+
try {
userRecord.mTransformRecords.getRefcountedResourceOrThrow(
createTransformResp.resourceId);
@@ -406,4 +458,103 @@
verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
}
+
+ private IpSecTunnelInterfaceResponse createAndValidateTunnel(
+ String localAddr, String remoteAddr) {
+ IpSecTunnelInterfaceResponse createTunnelResp =
+ mIpSecService.createTunnelInterface(
+ mSourceAddr, mDestinationAddr, fakeNetwork, new Binder());
+
+ assertNotNull(createTunnelResp);
+ assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
+ return createTunnelResp;
+ }
+
+ @Test
+ public void testCreateTunnelInterface() throws Exception {
+ IpSecTunnelInterfaceResponse createTunnelResp =
+ createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+ // Check that we have stored the tracking object, and retrieve it
+ IpSecService.UserRecord userRecord =
+ mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+ IpSecService.RefcountedResource refcountedRecord =
+ userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+ createTunnelResp.resourceId);
+
+ assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
+ verify(mMockNetd)
+ .addVirtualTunnelInterface(
+ eq(createTunnelResp.interfaceName),
+ eq(mSourceAddr),
+ eq(mDestinationAddr),
+ anyInt(),
+ anyInt());
+ }
+
+ @Test
+ public void testDeleteTunnelInterface() throws Exception {
+ IpSecTunnelInterfaceResponse createTunnelResp =
+ createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+ IpSecService.UserRecord userRecord =
+ mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+
+ mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId);
+
+ // Verify quota and RefcountedResource objects cleaned up
+ assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
+ verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
+ try {
+ userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+ createTunnelResp.resourceId);
+ fail("Expected IllegalArgumentException on attempt to access deleted resource");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testTunnelInterfaceBinderDeath() throws Exception {
+ IpSecTunnelInterfaceResponse createTunnelResp =
+ createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+ IpSecService.UserRecord userRecord =
+ mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+ IpSecService.RefcountedResource refcountedRecord =
+ userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+ createTunnelResp.resourceId);
+
+ refcountedRecord.binderDied();
+
+ // Verify quota and RefcountedResource objects cleaned up
+ assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
+ verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
+ try {
+ userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+ createTunnelResp.resourceId);
+ fail("Expected IllegalArgumentException on attempt to access deleted resource");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testAddRemoveAddressFromTunnelInterface() throws Exception {
+ IpSecTunnelInterfaceResponse createTunnelResp =
+ createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+ mIpSecService.addAddressToTunnelInterface(createTunnelResp.resourceId, mLocalInnerAddress);
+ verify(mMockNetd)
+ .interfaceAddAddress(
+ eq(createTunnelResp.interfaceName),
+ eq(mLocalInnerAddress.getAddress().getHostAddress()),
+ eq(mLocalInnerAddress.getPrefixLength()));
+
+ mIpSecService.removeAddressFromTunnelInterface(
+ createTunnelResp.resourceId, mLocalInnerAddress);
+ verify(mMockNetd)
+ .interfaceDelAddress(
+ eq(createTunnelResp.interfaceName),
+ eq(mLocalInnerAddress.getAddress().getHostAddress()),
+ eq(mLocalInnerAddress.getPrefixLength()));
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
new file mode 100644
index 0000000..4a83d1b
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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 com.android.server.connectivity;
+
+import static android.Manifest.permission.CHANGE_NETWORK_STATE;
+import static android.Manifest.permission.CHANGE_WIFI_STATE;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
+import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.NETWORK_STACK;
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PermissionMonitorTest {
+ private static final int MOCK_UID = 10001;
+ private static final String[] MOCK_PACKAGE_NAMES = new String[] { "com.foo.bar" };
+
+ @Mock private Context mContext;
+ @Mock private PackageManager mPackageManager;
+
+ private PermissionMonitor mPermissionMonitor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getPackagesForUid(MOCK_UID)).thenReturn(MOCK_PACKAGE_NAMES);
+ mPermissionMonitor = new PermissionMonitor(mContext, null);
+ }
+
+ private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
+ final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
+ when(mPackageManager.getPackageInfo(MOCK_PACKAGE_NAMES[0], GET_PERMISSIONS))
+ .thenReturn(packageInfo);
+ }
+
+ private PackageInfo packageInfoWithPermissions(String[] permissions, boolean preinstalled) {
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.requestedPermissions = permissions;
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.flags = preinstalled ? FLAG_SYSTEM : 0;
+ return packageInfo;
+ }
+
+ @Test
+ public void testHasPermission() {
+ PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
+ assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
+ assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
+ assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
+
+ app = packageInfoWithPermissions(new String[] {
+ CHANGE_NETWORK_STATE, NETWORK_STACK
+ }, false);
+ assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
+ assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
+ assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
+
+ app = packageInfoWithPermissions(new String[] {
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
+ }, false);
+ assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
+ assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
+ assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
+ }
+
+ @Test
+ public void testIsPreinstalledSystemApp() {
+ PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
+ assertFalse(mPermissionMonitor.isPreinstalledSystemApp(app));
+
+ app = packageInfoWithPermissions(new String[] {}, true);
+ assertTrue(mPermissionMonitor.isPreinstalledSystemApp(app));
+ }
+
+ @Test
+ public void testHasUseBackgroundNetworksPermission() throws Exception {
+ expectPermission(new String[] { CHANGE_NETWORK_STATE }, false);
+ assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+
+ expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, false);
+ assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+
+ // TODO : make this false when b/31479477 is fixed
+ expectPermission(new String[] {}, true);
+ assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+ expectPermission(new String[] { CHANGE_WIFI_STATE }, true);
+ assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+
+ expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, true);
+ assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+
+ expectPermission(new String[] {}, false);
+ assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+
+ expectPermission(new String[] { CHANGE_WIFI_STATE }, false);
+ assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+ }
+}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 47c3455..17ca651 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -25,6 +25,7 @@
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -58,6 +59,9 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -95,6 +99,7 @@
import android.util.TrustedTime;
import com.android.internal.net.VpnInfo;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
@@ -668,6 +673,94 @@
}
@Test
+ public void testDetailedUidStats() throws Exception {
+ // pretend that network comes online
+ expectDefaultSettings();
+ expectNetworkState(buildWifiState());
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(NETWORKS_WIFI);
+
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 50L, 5L, 50L, 5L, 0L);
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, 1024L, 8L, 512L, 4L, 0L);
+
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3));
+ mService.incrementOperationCount(UID_RED, 0xF00D, 1);
+
+ NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
+
+ assertEquals(3, stats.size());
+ entry1.operations = 1;
+ assertEquals(entry1, stats.getValues(0, null));
+ entry2.operations = 1;
+ assertEquals(entry2, stats.getValues(1, null));
+ assertEquals(entry3, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testDetailedUidStats_Filtered() throws Exception {
+ // pretend that network comes online
+ expectDefaultSettings();
+
+ final String stackedIface = "stacked-test0";
+ final LinkProperties stackedProp = new LinkProperties();
+ stackedProp.setInterfaceName(stackedIface);
+ final NetworkState wifiState = buildWifiState();
+ wifiState.linkProperties.addStackedLink(stackedProp);
+ expectNetworkState(wifiState);
+
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(NETWORKS_WIFI);
+
+ NetworkStats.Entry uidStats = new NetworkStats.Entry(
+ TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+ // Stacked on matching interface
+ NetworkStats.Entry tetheredStats1 = new NetworkStats.Entry(
+ stackedIface, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+ // Different interface
+ NetworkStats.Entry tetheredStats2 = new NetworkStats.Entry(
+ "otherif", UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+
+ final String[] ifaceFilter = new String[] { TEST_IFACE };
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats());
+ when(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL), any()))
+ .thenReturn(new NetworkStats(getElapsedRealtime(), 1)
+ .addValues(uidStats));
+ when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
+ .thenReturn(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(tetheredStats1)
+ .addValues(tetheredStats2));
+
+ NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
+
+ verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
+ ifaces != null && ifaces.length == 2
+ && ArrayUtils.contains(ifaces, TEST_IFACE)
+ && ArrayUtils.contains(ifaces, stackedIface)));
+
+ assertEquals(2, stats.size());
+ assertEquals(uidStats, stats.getValues(0, null));
+ assertEquals(tetheredStats1, stats.getValues(1, null));
+ }
+
+ @Test
public void testForegroundBackground() throws Exception {
// pretend that network comes online
expectCurrentTime();
@@ -1056,7 +1149,7 @@
private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats)
throws Exception {
- when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
+ when(mNetManager.getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL)).thenReturn(detail);
// also include tethering details, since they are folded into UID
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats);
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index c6ad4c2..dcb90e4 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -13,6 +13,7 @@
LANG_TO_SCRIPT = {
'as': 'Beng',
+ 'be': 'Cyrl',
'bg': 'Cyrl',
'bn': 'Beng',
'cu': 'Cyrl',
@@ -33,6 +34,7 @@
'ja': 'Jpan',
'kn': 'Knda',
'ko': 'Kore',
+ 'la': 'Latn',
'ml': 'Mlym',
'mn': 'Cyrl',
'mr': 'Deva',